diff options
-rw-r--r-- | libc/unistd/execl.c | 51 | ||||
-rw-r--r-- | libc/unistd/execlp.c | 51 | ||||
-rw-r--r-- | libc/unistd/execv.c | 9 | ||||
-rw-r--r-- | libc/unistd/execvep.c | 43 | ||||
-rw-r--r-- | libc/unistd/execvp.c | 9 | ||||
-rw-r--r-- | libc/unistd/getcwd.c | 120 | ||||
-rw-r--r-- | libc/unistd/getopt.c | 111 | ||||
-rw-r--r-- | libc/unistd/sleep.c | 24 |
8 files changed, 418 insertions, 0 deletions
diff --git a/libc/unistd/execl.c b/libc/unistd/execl.c new file mode 100644 index 000000000..531c2ee60 --- /dev/null +++ b/libc/unistd/execl.c @@ -0,0 +1,51 @@ + +#include <stdlib.h> +#include <unistd.h> +#include <stdarg.h> + +extern char **environ; + +int execl(__const char *path, __const char *arg, ...) +{ + const char *shortargv[16]; + const char **argv; + const char *c; + int i; + va_list args; + + i = 1; + + va_start(args, arg); + + do { + c = va_arg(args, const char *); + + i++; + } while (c); + + va_end(args); + + if (i <= 16) + argv = shortargv; + else { + argv = (const char **) malloc(sizeof(char *) * i); + } + + argv[0] = arg; + i = 1; + + va_start(args, arg); + + do { + argv[i] = va_arg(args, const char *); + } while (argv[i++]); + + va_end(args); + + i = execve(path, (char *const *) argv, environ); + + if (argv != shortargv) + free(argv); + + return i; +} diff --git a/libc/unistd/execlp.c b/libc/unistd/execlp.c new file mode 100644 index 000000000..571ab71b0 --- /dev/null +++ b/libc/unistd/execlp.c @@ -0,0 +1,51 @@ + +#include <stdlib.h> +#include <unistd.h> +#include <stdarg.h> + +extern char **environ; + +int execlp(__const char *file, __const char *arg, ...) +{ + const char *shortargv[16]; + const char **argv; + const char *c; + int i; + va_list args; + + i = 1; + + va_start(args, arg); + + do { + c = va_arg(args, const char *); + + i++; + } while (c); + + va_end(args); + + if (i <= 16) + argv = shortargv; + else { + argv = (const char **) malloc(sizeof(char *) * i); + } + + argv[0] = arg; + i = 1; + + va_start(args, arg); + + do { + argv[i] = va_arg(args, const char *); + } while (argv[i++]); + + va_end(args); + + i = execvep(file, (char *const *) argv, environ); + + if (argv != shortargv) + free(argv); + + return i; +} diff --git a/libc/unistd/execv.c b/libc/unistd/execv.c new file mode 100644 index 000000000..6c8ba0d97 --- /dev/null +++ b/libc/unistd/execv.c @@ -0,0 +1,9 @@ + +#include <unistd.h> + +extern char **environ; + +int execv(__const char *path, char *__const argv[]) +{ + return execve(path, argv, environ); +} diff --git a/libc/unistd/execvep.c b/libc/unistd/execvep.c new file mode 100644 index 000000000..4ac7692e9 --- /dev/null +++ b/libc/unistd/execvep.c @@ -0,0 +1,43 @@ + +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +int execvep(const char *path, char *__const argv[], char *__const envp[]) +{ + if (!strchr(path, '/')) { + char partial[128]; + char *p = getenv("PATH"); + char *p2; + + if (!p) + p = "/bin:/usr/bin"; + + for (; p && *p;) { + + strcpy(partial, p); + + p2 = strchr(partial, ':'); + if (p2) + *p2 = '\0'; + + if (strlen(partial)) + strcat(partial, "/"); + strcat(partial, path); + + execve(partial, argv, envp); + + if (errno != ENOENT) + return -1; + + p2 = strchr(p, ':'); + if (p2) + p = p2 + 1; + else + p = 0; + } + return -1; + } else + return execve(path, argv, envp); +} diff --git a/libc/unistd/execvp.c b/libc/unistd/execvp.c new file mode 100644 index 000000000..b2aeee917 --- /dev/null +++ b/libc/unistd/execvp.c @@ -0,0 +1,9 @@ + +#include <unistd.h> + +extern char **environ; + +int execvp(__const char *path, char *__const argv[]) +{ + return execvep(path, argv, environ); +} diff --git a/libc/unistd/getcwd.c b/libc/unistd/getcwd.c new file mode 100644 index 000000000..12eda45ca --- /dev/null +++ b/libc/unistd/getcwd.c @@ -0,0 +1,120 @@ + +#include <errno.h> +#include <sys/stat.h> +#include <dirent.h> +#include <string.h> +/* + * These functions find the absolute path to the current working directory. + * + * They don't use malloc or large amounts of stack space. + */ + +static char *recurser(); /* Routine to go up tree */ +static char *search_dir(); /* Routine to find the step back down */ +static char *path_buf; +static int path_size; + +static dev_t root_dev; +static ino_t root_ino; + +static struct stat st; + +char *getcwd(buf, size) +char *buf; +int size; +{ + path_buf = buf; + path_size = size; + + if (size < 3) { + errno = ERANGE; + return 0; + } + strcpy(path_buf, "."); + + if (stat("/", &st) < 0) + return 0; + + root_dev = st.st_dev; + root_ino = st.st_ino; + + return recurser(); +} + +static char *recurser() +{ + dev_t this_dev; + ino_t this_ino; + + if (stat(path_buf, &st) < 0) + return 0; + this_dev = st.st_dev; + this_ino = st.st_ino; + if (this_dev == root_dev && this_ino == root_ino) { + strcpy(path_buf, "/"); + return path_buf; + } + if (strlen(path_buf) + 4 > path_size) { + errno = ERANGE; + return 0; + } + strcat(path_buf, "/.."); + if (recurser() == 0) + return 0; + + return search_dir(this_dev, this_ino); +} + +static char *search_dir(this_dev, this_ino) +dev_t this_dev; +ino_t this_ino; +{ + DIR *dp; + struct dirent *d; + char *ptr; + int slen; + + /* The test is for ELKS lib 0.0.9, this should be fixed in the real kernel */ + int slow_search = (sizeof(ino_t) != sizeof(d->d_ino)); + + if (stat(path_buf, &st) < 0) + return 0; + if (this_dev != st.st_dev) + slow_search = 1; + + slen = strlen(path_buf); + ptr = path_buf + slen - 1; + if (*ptr != '/') { + if (slen + 2 > path_size) { + errno = ERANGE; + return 0; + } + strcpy(++ptr, "/"); + slen++; + } + slen++; + + dp = opendir(path_buf); + if (dp == 0) + return 0; + + while ((d = readdir(dp)) != 0) { + if (slow_search || this_ino == d->d_ino) { + if (slen + strlen(d->d_name) > path_size) { + errno = ERANGE; + return 0; + } + strcpy(ptr + 1, d->d_name); + if (stat(path_buf, &st) < 0) + continue; + if (st.st_ino == this_ino && st.st_dev == this_dev) { + closedir(dp); + return path_buf; + } + } + } + + closedir(dp); + errno = ENOENT; + return 0; +} diff --git a/libc/unistd/getopt.c b/libc/unistd/getopt.c new file mode 100644 index 000000000..70d20b06b --- /dev/null +++ b/libc/unistd/getopt.c @@ -0,0 +1,111 @@ + +/* + * From: gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) Newsgroups: net.sources + * Subject: getopt library routine Date: 30 Mar 85 04:45:33 GMT + */ +/* + * getopt -- public domain version of standard System V routine + * + * Strictly enforces the System V Command Syntax Standard; provided by D A + * Gwyn of BRL for generic ANSI C implementations + * + * #define STRICT to prevent acceptance of clustered options with arguments + * and ommision of whitespace between option and arg. + */ + +#include <stdio.h> +#include <string.h> + +int opterr = 1; /* error => print message */ +int optind = 1; /* next argv[] index */ +int optopt = 1; /* Set for unknown arguments */ +char *optarg = NULL; /* option parameter if any */ + +static int Err(name, mess, c) /* returns '?' */ +char *name; /* program name argv[0] */ +char *mess; /* specific message */ +int c; /* defective option letter */ +{ + optopt = c; + if (opterr) { + (void) fprintf(stderr, "%s: %s -- %c\n", name, mess, c); + } + + return '?'; /* erroneous-option marker */ +} + +int getopt(argc, argv, optstring) /* returns letter, '?', EOF */ +int argc; /* argument count from main */ +char *argv[]; /* argument vector from main */ +char *optstring; /* allowed args, e.g. "ab:c" */ +{ + static int sp = 1; /* position within argument */ + register int osp; /* saved `sp' for param test */ + +#ifndef STRICT + register int oind; /* saved `optind' for param test */ +#endif + register int c; /* option letter */ + register char *cp; /* -> option in `optstring' */ + + optarg = NULL; + + if (sp == 1) { /* fresh argument */ + if (optind >= argc /* no more arguments */ + || argv[optind][0] != '-' /* no more options */ + || argv[optind][1] == '\0' /* not option; stdin */ + ) + return EOF; + else if (strcmp(argv[optind], "--") == 0) { + ++optind; /* skip over "--" */ + return EOF; /* "--" marks end of options */ + } + } + + c = argv[optind][sp]; /* option letter */ + osp = sp++; /* get ready for next letter */ + +#ifndef STRICT + oind = optind; /* save optind for param test */ +#endif + if (argv[optind][sp] == '\0') { /* end of argument */ + ++optind; /* get ready for next try */ + sp = 1; /* beginning of next argument */ + } + + if (c == ':' || c == '?' /* optstring syntax conflict */ + || (cp = strchr(optstring, c)) == NULL /* not found */ ) { + return Err(argv[0], "illegal option", c); + } + + if (cp[1] == ':') { /* option takes parameter */ +#ifdef STRICT + if (osp != 1) { + return Err(argv[0], "option must not be clustered", c); + } + + /* reset by end of argument */ + if (sp != 1) { + return Err(argv[0], "option must be followed by white space", + c); + } +#else + if (oind == optind) { /* argument w/o whitespace */ + optarg = &argv[optind][sp]; + sp = 1; /* beginning of next argument */ + } + + else +#endif + if (optind >= argc) { + return Err(argv[0], "option requires an argument", c); + } + + else /* argument w/ whitespace */ + optarg = argv[optind]; + + ++optind; /* skip over parameter */ + } + + return c; +} diff --git a/libc/unistd/sleep.c b/libc/unistd/sleep.c new file mode 100644 index 000000000..5b458e07a --- /dev/null +++ b/libc/unistd/sleep.c @@ -0,0 +1,24 @@ + + +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> + +void usleep(unsigned long usec) +{ + struct timeval tv; + + tv.tv_sec = usec / 1000000; + tv.tv_usec = usec % 1000000; + select(0, 0, 0, 0, &tv); +} + +unsigned int sleep(unsigned int sec) +{ + struct timeval tv; + + tv.tv_sec = sec; + tv.tv_usec = 0; + select(0, 0, 0, 0, &tv); + return tv.tv_sec; +} |