summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libc/unistd/execl.c51
-rw-r--r--libc/unistd/execlp.c51
-rw-r--r--libc/unistd/execv.c9
-rw-r--r--libc/unistd/execvep.c43
-rw-r--r--libc/unistd/execvp.c9
-rw-r--r--libc/unistd/getcwd.c120
-rw-r--r--libc/unistd/getopt.c111
-rw-r--r--libc/unistd/sleep.c24
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;
+}