summaryrefslogtreecommitdiff
path: root/dln.c
diff options
context:
space:
mode:
-rw-r--r--dln.c461
1 files changed, 264 insertions, 197 deletions
@@ -10,162 +10,132 @@
************************************************/
-#include <stdio.h>
-#include <sys/param.h>
-#include <sys/file.h>
#include "config.h"
#include "defines.h"
#include "dln.h"
-#include <sys/types.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-char *strdup();
-extern int errno;
-int dln_errno;
-static int dln_init_p = 0;
-#include <sys/stat.h>
-static char fbuf[MAXPATHLEN];
-static char *dln_find_1();
-char *getenv();
-char *strchr();
-int strcmp();
-char *
-dln_find_exe(fname, path)
- char *fname;
- char *path;
{
- if (!path) path = getenv("PATH");
- if (!path) path = "/usr/local/bin:/usr/ucb:/usr/bin:/bin:.";
- return dln_find_1(fname, path, 1);
}
-char *
-dln_find_file(fname, path)
- char *fname;
- char *path;
{
- if (!path) path = ".";
- return dln_find_1(fname, path, 0);
}
-static char *
-dln_find_1(fname, path, exe_flag)
- char *fname;
- char *path;
- int exe_flag; /* non 0 if looking for executable. */
{
- register char *dp;
- register char *ep;
- register char *bp;
- struct stat st;
- if (fname[0] == '/') return fname;
- for (dp = path;; dp = ++ep)
- {
- register int l;
- int i;
- int fspace;
- /* extract a component */
- ep = strchr(dp, ':');
- if (ep == NULL)
- ep = dp+strlen(dp);
- /* find the length of that component */
- l = ep - dp;
- bp = fbuf;
- fspace = sizeof fbuf - 2;
- if (l > 0)
- {
- /*
- ** If the length of the component is zero length,
- ** start from the current directory. If the
- ** component begins with "~", start from the
- ** user's $HOME environment variable. Otherwise
- ** take the path literally.
- */
- if (*dp == '~' && (l == 1 || dp[1] == '/'))
- {
- char *home;
- home = getenv("HOME");
- if (home != NULL)
- {
- i = strlen(home);
- if ((fspace -= i) < 0)
- goto toolong;
- memcpy(bp, home, i);
- bp += i;
- }
- dp++;
- l--;
- }
- if (l > 0)
- {
- if ((fspace -= l) < 0)
- goto toolong;
- memcpy(bp, dp, l);
- bp += l;
- }
- /* add a "/" between directory and filename */
- if (ep[-1] != '/')
- *bp++ = '/';
- }
- /* now append the file name */
- i = strlen(fname);
- if ((fspace -= i) < 0)
- {
- toolong:
- fprintf(stderr, "openpath: pathname too long (ignored)\n");
- *bp = '\0';
- fprintf(stderr, "\tDirectory \"%s\"\n", fbuf);
- fprintf(stderr, "\tFile \"%s\"\n", fname);
- continue;
- }
- memcpy(bp, fname, i + 1);
- if (stat(fbuf, &st) == 0) {
- if (exe_flag == 0) return fbuf;
- /* looking for executable */
-#ifdef RUBY
- if (eaccess(fbuf, X_OK) == 0) return fbuf;
-#else
- {
- uid_t uid = getuid();
- gid_t gid = getgid();
- if (uid == st.st_uid &&
- (st.st_mode & S_IEXEC) ||
- gid == st.st_gid &&
- (st.st_mode & (S_IEXEC>>3)) ||
- st.st_mode & (S_IEXEC>>6)) {
- return fbuf;
- }
- }
-#endif
- }
- /* if not, and no other alternatives, life is b */
- if (*ep == '\0') {
- dln_errno = DLN_ENOENT;
- return NULL;
- }
- /* otherwise try the next component in the search path */
- }
-}
-#ifdef USE_DLN
#include "st.h"
#include <ar.h>
@@ -573,10 +543,11 @@ unlink_undef(name, value)
st_foreach(reloc_tbl, reloc_undef, &arg);
}
-static int dln_load_1(fd, disp, need_init)
int fd;
long disp;
- int need_init;
{
static char *libc = LIBC_NAME;
struct exec hdr;
@@ -587,6 +558,7 @@ static int dln_load_1(fd, disp, need_init)
struct nlist *sym;
struct nlist *end;
int init_p = 0;
if (dln_load_header(fd, &hdr, disp) == -1) return -1;
if (INVALID_OBJECT(hdr)) {
@@ -764,21 +736,38 @@ static int dln_load_1(fd, disp, need_init)
}
if (need_init) {
if (undef_tbl->num_entries > 0) {
if (dln_load_lib(libc) == -1) goto err_exit;
}
sym = syms;
while (sym < end) {
char *name = sym->n_un.n_name;
if (name[0] == '_' && sym->n_value >= block
- && ((bcmp (name, "_Init_", 6) == 0
|| bcmp (name, "_init_", 6) == 0) && name[6] != '_')) {
init_p = 1;
((int (*)())sym->n_value)();
}
sym++;
}
}
free(reloc);
free(syms);
@@ -815,13 +804,17 @@ dln_load(file)
dln_errno = DLN_ENOINIT;
return -1;
}
fd = open(file, O_RDONLY);
if (fd == -1) {
dln_errno = errno;
return -1;
}
- result = dln_load_1(fd, 0, 1);
close(fd);
return result;
@@ -873,6 +866,12 @@ dln_load_lib(lib)
if (undef_tbl->num_entries == 0) return 0;
dln_errno = DLN_EBADLIB;
/* library search path: */
/* look for environment variable DLN_LIBRARY_PATH first. */
/* then variable dln_library_path. */
@@ -983,6 +982,17 @@ dln_load_lib(lib)
return -1;
}
char *
dln_strerror()
{
@@ -1006,87 +1016,144 @@ dln_strerror()
}
}
-dln_perror(str)
- char *str;
-{
- fprintf(stderr, "%s: %s\n", str, dln_strerror());
-}
-
-void*
-dln_get_sym(name)
- char *name;
-{
- struct nlist *sym;
- if (st_lookup(sym_tbl, name, &sym))
- return (void*)sym->n_value;
- return NULL;
-}
-#ifdef TEST
-xmalloc(size)
- int size;
{
- return malloc(size);
}
-xcalloc(size, n)
- int size, n;
{
- return calloc(size, n);
}
-main(argc, argv)
- int argc;
- char **argv;
{
- if (dln_init(argv[0]) == -1) {
- dln_perror("dln_init");
- exit(1);
- }
- while (argc > 1) {
- printf("obj: %s\n", argv[1]);
- if (dln_load(argv[1]) == -1) {
- dln_perror("dln_load");
- exit(1);
}
- argc--;
- argv++;
- }
- if (dln_load_lib("libdln.a") == -1) {
- dln_perror("dln_init");
- exit(1);
- }
- if (dln_get_sym("_foo"))
- printf("_foo defined\n");
- else
- printf("_foo undefined\n");
-}
-#endif /* TEST */
-#else /* USE_DLN */
-int
-dln_init(file)
- char *file;
-{
- return 0;
-}
-int
-dln_load(file)
- char *file;
-{
- return 0;
}
-int
-dln_load_lib(file)
- char *file;
{
- return 0;
}
-
-#endif /* USE_DLN */