#include <unistd.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <sgs.h>
#include <libintl.h>
#include <debug.h>
#include "msg.h"
#include "_libld.h"
Sdf_desc *
sdf_find(const char *name, APlist *alp)
{
Aliste idx;
Sdf_desc *sdf;
for (APLIST_TRAVERSE(alp, idx, sdf))
if (strcmp(name, sdf->sdf_name) == 0)
return (sdf);
return (NULL);
}
Sdf_desc *
sdf_add(const char *name, APlist **alpp)
{
Sdf_desc *sdf;
if ((sdf = libld_calloc(1, sizeof (Sdf_desc))) == NULL)
return ((Sdf_desc *)S_ERROR);
sdf->sdf_name = name;
if (aplist_append(alpp, sdf, AL_CNT_OFL_LIBS) == NULL)
return ((Sdf_desc *)S_ERROR);
return (sdf);
}
char *
add_string(char *old, char *str)
{
char *new;
if (old) {
char *_str;
size_t len;
if ((_str = strstr(old, str)) != NULL) {
if (((_str == old) ||
(*(_str - 1) == *(MSG_ORIG(MSG_STR_COLON)))) &&
(_str += strlen(str)) &&
((*_str == '\0') ||
(*_str == *(MSG_ORIG(MSG_STR_COLON)))))
return (old);
}
len = strlen(old) + strlen(str) + 2;
if ((new = libld_calloc(1, len)) == NULL)
return ((char *)S_ERROR);
(void) snprintf(new, len, MSG_ORIG(MSG_FMT_COLPATH), old, str);
} else {
if ((new = libld_malloc(strlen(str) + 1)) == NULL)
return ((char *)S_ERROR);
(void) strcpy(new, str);
}
return (new);
}
static int
str2chr_wrap_cb(int c)
{
char *str;
size_t len = MSG_ARG_WRAP_SIZE + strlen(optarg) + 1;
if ((str = libld_malloc(len)) == NULL)
return ('?');
(void) snprintf(str, len, MSG_ORIG(MSG_FMT_STRCAT),
MSG_ORIG(MSG_ARG_WRAP), optarg);
optarg = str;
return (c);
}
static int
str2chr(Lm_list *lml, int ndx, int argc, char **argv, char *arg, int c,
const char *opt, size_t optsz, int (*cbfunc)(int))
{
if (optsz == 0) {
if (strcmp(arg, opt) == 0) {
DBG_CALL(Dbg_args_str2chr(lml, ndx, opt, c));
optind += 1;
optopt = c;
return (c);
}
} else if ((strcmp(arg, opt) == 0) ||
((arg[optsz] == '=') && strncmp(arg, opt, optsz) == 0)) {
DBG_CALL(Dbg_args_str2chr(lml, ndx, opt, c));
if (arg[optsz] == '\0') {
if ((++optind + 1) > argc) {
optopt = arg[0];
return ('?');
}
optarg = argv[optind];
optind++;
} else {
optarg = &arg[optsz];
optind++;
if (*optarg == '=') {
if (*(++optarg) == '\0') {
optopt = arg[0];
return ('?');
}
}
}
if (cbfunc != NULL)
c = (*cbfunc)(c);
optopt = c;
return (c);
}
return (0);
}
int
ld_getopt(Lm_list *lml, int ndx, int argc, char **argv)
{
int c;
if ((optind < argc) && argv[optind] && (argv[optind][0] == '-')) {
char *arg = &argv[optind][1];
switch (*arg) {
case 'r':
if ((c = str2chr(lml, ndx, argc, argv, arg, 'R',
MSG_ORIG(MSG_ARG_T_RPATH),
MSG_ARG_T_RPATH_SIZE, NULL)) != 0) {
return (c);
}
break;
case 's':
if ((c = str2chr(lml, ndx, argc, argv, arg, 'G',
MSG_ORIG(MSG_ARG_T_SHARED), 0, NULL)) != 0) {
return (c);
} else if ((c = str2chr(lml, ndx, argc, argv, arg, 'h',
MSG_ORIG(MSG_ARG_T_SONAME),
MSG_ARG_T_SONAME_SIZE, NULL)) != 0) {
return (c);
}
break;
case 'w':
if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
MSG_ORIG(MSG_ARG_T_WRAP) + 1,
MSG_ARG_T_WRAP_SIZE - 1, str2chr_wrap_cb)) != 0) {
return (c);
}
break;
case '(':
if ((c = str2chr(lml, ndx, argc, argv,
arg, 'z', MSG_ORIG(MSG_ARG_T_OPAR), 0, NULL)) !=
0) {
optarg = (char *)MSG_ORIG(MSG_ARG_RESCAN_START);
return (c);
}
break;
case ')':
if ((c = str2chr(lml, ndx, argc, argv,
arg, 'z', MSG_ORIG(MSG_ARG_T_CPAR), 0, NULL)) !=
0) {
optarg = (char *)MSG_ORIG(MSG_ARG_RESCAN_END);
return (c);
}
break;
case '-':
switch (*(arg + 1)) {
case 'a':
if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
MSG_ORIG(MSG_ARG_T_MULDEFS), 0, NULL)) !=
0) {
optarg =
(char *)MSG_ORIG(MSG_ARG_MULDEFS);
return (c);
} else if ((c = str2chr(lml, argc, ndx, argv,
arg, 'f', MSG_ORIG(MSG_ARG_T_AUXFLTR),
MSG_ARG_T_AUXFLTR_SIZE, NULL)) != 0) {
return (c);
}
break;
case 'd':
if ((c = str2chr(lml, ndx, argc, argv, arg, 'I',
MSG_ORIG(MSG_ARG_T_INTERP),
MSG_ARG_T_INTERP_SIZE, NULL)) != 0) {
return (c);
}
break;
case 'e':
if ((c = str2chr(lml, ndx, argc, argv, arg, 'e',
MSG_ORIG(MSG_ARG_T_ENTRY),
MSG_ARG_T_ENTRY_SIZE, NULL)) != 0) {
return (c);
}
if ((c = str2chr(lml, ndx, argc, argv,
arg, 'z', MSG_ORIG(MSG_ARG_T_ENDGROUP),
0, NULL)) != 0) {
optarg = (char *)
MSG_ORIG(MSG_ARG_RESCAN_END);
return (c);
}
break;
case 'f':
if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
MSG_ORIG(MSG_ARG_T_FATWARN),
0, NULL)) != 0) {
optarg = (char *)
MSG_ORIG(MSG_ARG_FATWARN);
return (c);
}
if ((c = str2chr(lml, ndx, argc, argv, arg, 'F',
MSG_ORIG(MSG_ARG_T_STDFLTR),
MSG_ARG_T_STDFLTR_SIZE, NULL)) != 0) {
return (c);
}
break;
case 'h':
if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
MSG_ORIG(MSG_ARG_T_HELP), 0, NULL)) !=
0) {
optarg = (char *)MSG_ORIG(MSG_ARG_HELP);
return (c);
}
break;
case 'l':
if ((c = str2chr(lml, ndx, argc, argv, arg, 'l',
MSG_ORIG(MSG_ARG_T_LIBRARY),
MSG_ARG_T_LIBRARY_SIZE, NULL)) != 0) {
return (c);
} else if ((c = str2chr(lml, ndx, argc, argv,
arg, 'L', MSG_ORIG(MSG_ARG_T_LIBPATH),
MSG_ARG_T_LIBPATH_SIZE, NULL)) != 0) {
return (c);
}
break;
case 'n':
if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
MSG_ORIG(MSG_ARG_T_NOFATWARN),
0, NULL)) != 0) {
optarg = (char *)
MSG_ORIG(MSG_ARG_NOFATWARN);
return (c);
}
if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
MSG_ORIG(MSG_ARG_T_NOUNDEF), 0, NULL)) !=
0) {
optarg = (char *)MSG_ORIG(MSG_ARG_DEFS);
return (c);
} else if ((c = str2chr(lml, ndx, argc, argv,
arg, 'z', MSG_ORIG(MSG_ARG_T_NOWHOLEARC),
0, NULL)) != 0) {
optarg =
(char *)MSG_ORIG(MSG_ARG_DFLEXTRT);
return (c);
}
break;
case 'o':
if ((c = str2chr(lml, ndx, argc, argv, arg, 'o',
MSG_ORIG(MSG_ARG_T_OUTPUT),
MSG_ARG_T_OUTPUT_SIZE, NULL)) != 0) {
return (c);
}
break;
case 'r':
if ((c = str2chr(lml, ndx, argc, argv, arg, 'r',
MSG_ORIG(MSG_ARG_T_RELOCATABLE), 0,
NULL)) != 0) {
return (c);
}
break;
case 's':
if ((c = str2chr(lml, ndx, argc, argv, arg, 's',
MSG_ORIG(MSG_ARG_T_STRIP), 0, NULL)) !=
0) {
return (c);
}
if ((c = str2chr(lml, ndx, argc, argv,
arg, 'z', MSG_ORIG(MSG_ARG_T_STARTGROUP),
0, NULL)) != 0) {
optarg = (char *)
MSG_ORIG(MSG_ARG_RESCAN_START);
return (c);
}
break;
case 'u':
if ((c = str2chr(lml, ndx, argc, argv, arg, 'u',
MSG_ORIG(MSG_ARG_T_UNDEF),
MSG_ARG_T_UNDEF_SIZE, NULL)) != 0) {
return (c);
}
break;
case 'v':
if ((c = str2chr(lml, ndx, argc, argv, arg, 'V',
MSG_ORIG(MSG_ARG_T_VERSION), 0, NULL)) !=
0) {
return (c);
}
break;
case 'w':
if ((c = str2chr(lml, ndx, argc, argv,
arg, 'z', MSG_ORIG(MSG_ARG_T_WHOLEARC),
0, NULL)) != 0) {
optarg =
(char *)MSG_ORIG(MSG_ARG_ALLEXTRT);
return (c);
}
if ((c = str2chr(lml, ndx, argc, argv,
arg, 'z', MSG_ORIG(MSG_ARG_T_WRAP),
MSG_ARG_T_WRAP_SIZE, str2chr_wrap_cb)) !=
0) {
return (c);
}
break;
}
break;
}
}
if ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) {
if ((c == 'W') && (strncmp(optarg,
MSG_ORIG(MSG_ARG_T_WL), MSG_ARG_T_WL_SIZE) == 0)) {
DBG_CALL(Dbg_args_Wldel(lml, ndx, optarg));
c = optarg[MSG_ARG_T_WL_SIZE];
optarg += MSG_ARG_T_WL_SIZE + 1;
}
}
return (c);
}
int
isdavl_compare(const void *n1, const void *n2)
{
uint_t hash1, hash2;
const char *st1, *st2;
int rc;
hash1 = ((Isd_node *)n1)->isd_hash;
hash2 = ((Isd_node *)n2)->isd_hash;
if (hash1 > hash2)
return (1);
if (hash1 < hash2)
return (-1);
st1 = ((Isd_node *)n1)->isd_name;
st2 = ((Isd_node *)n2)->isd_name;
rc = strcmp(st1, st2);
if (rc > 0)
return (1);
if (rc < 0)
return (-1);
return (0);
}
const char *
_libld_msg(Msg mid)
{
return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid)));
}
const char *
demangle(const char *name)
{
if (demangle_flag)
return (Elf_demangle_name(name));
else
return (name);
}
int
cap_names_match(Alist *alp1, Alist *alp2)
{
Capstr *capstr1;
Aliste idx1;
int match = 0;
Word nitems;
if ((nitems = alist_nitems(alp1)) != alist_nitems(alp2))
return (1);
for (ALIST_TRAVERSE(alp1, idx1, capstr1)) {
Capstr *capstr2;
Aliste idx2;
for (ALIST_TRAVERSE(alp2, idx2, capstr2)) {
if (strcmp(capstr1->cs_str, capstr2->cs_str))
continue;
match++;
break;
}
}
if (nitems == match)
return (0);
return (1);
}