diff options
-rw-r--r-- | alloc.c | 33 | ||||
-rw-r--r-- | alloc.h | 10 | ||||
-rw-r--r-- | alloc_re.c | 19 | ||||
-rw-r--r-- | buffer.h | 61 | ||||
-rw-r--r-- | buffer_2.c | 7 | ||||
-rw-r--r-- | buffer_put.c | 90 | ||||
-rw-r--r-- | buffer_write.c | 9 | ||||
-rw-r--r-- | build.sh | 1 | ||||
-rw-r--r-- | byte.h | 15 | ||||
-rw-r--r-- | byte_chr.c | 22 | ||||
-rw-r--r-- | byte_copy.c | 16 | ||||
-rw-r--r-- | byte_diff.c | 18 | ||||
-rw-r--r-- | chpst.c | 475 | ||||
-rw-r--r-- | direntry.h | 12 | ||||
-rw-r--r-- | env.c | 17 | ||||
-rw-r--r-- | env.h | 10 | ||||
-rw-r--r-- | error.c | 132 | ||||
-rw-r--r-- | error.h | 33 | ||||
-rw-r--r-- | error_str.c | 267 | ||||
-rw-r--r-- | fmt.h | 27 | ||||
-rw-r--r-- | fmt_ulong.c | 15 | ||||
-rw-r--r-- | gen_alloc.h | 9 | ||||
-rw-r--r-- | gen_allocdefs.h | 36 | ||||
-rw-r--r-- | hasflock.h | 4 | ||||
-rw-r--r-- | hasshsgr.h | 4 | ||||
-rw-r--r-- | lock.h | 10 | ||||
-rw-r--r-- | lock_ex.c | 13 | ||||
-rw-r--r-- | lock_exnb.c | 13 | ||||
-rw-r--r-- | open.h | 12 | ||||
-rw-r--r-- | open_append.c | 8 | ||||
-rw-r--r-- | open_read.c | 8 | ||||
-rw-r--r-- | openreadclose.c | 18 | ||||
-rw-r--r-- | openreadclose.h | 10 | ||||
-rw-r--r-- | pathexec.h | 11 | ||||
-rw-r--r-- | pathexec_env.c | 74 | ||||
-rw-r--r-- | pathexec_run.c | 48 | ||||
-rw-r--r-- | prot.c | 21 | ||||
-rw-r--r-- | prot.h | 9 | ||||
-rw-r--r-- | readclose.c | 23 | ||||
-rw-r--r-- | readclose.h | 11 | ||||
-rw-r--r-- | scan.h | 30 | ||||
-rw-r--r-- | scan_ulong.c | 16 | ||||
-rw-r--r-- | sgetopt.c | 53 | ||||
-rw-r--r-- | sgetopt.h | 23 | ||||
-rw-r--r-- | str.h | 16 | ||||
-rw-r--r-- | str_chr.c | 19 | ||||
-rw-r--r-- | str_diff.c | 17 | ||||
-rw-r--r-- | str_len.c | 16 | ||||
-rw-r--r-- | str_start.c | 15 | ||||
-rw-r--r-- | stralloc.h | 31 | ||||
-rw-r--r-- | stralloc_cat.c | 9 | ||||
-rw-r--r-- | stralloc_catb.c | 14 | ||||
-rw-r--r-- | stralloc_cats.c | 10 | ||||
-rw-r--r-- | stralloc_eady.c | 8 | ||||
-rw-r--r-- | stralloc_opyb.c | 13 | ||||
-rw-r--r-- | stralloc_opys.c | 10 | ||||
-rw-r--r-- | stralloc_pend.c | 7 | ||||
-rw-r--r-- | strerr.h | 80 | ||||
-rw-r--r-- | strerr_die.c | 33 | ||||
-rw-r--r-- | strerr_sys.c | 14 | ||||
-rw-r--r-- | subgetopt.c | 67 | ||||
-rw-r--r-- | subgetopt.h | 26 | ||||
-rw-r--r-- | uidgid.c | 74 | ||||
-rw-r--r-- | uidgid.h | 18 |
64 files changed, 2250 insertions, 0 deletions
@@ -0,0 +1,33 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include <stdlib.h> | ||
4 | #include "alloc.h" | ||
5 | #include "error.h" | ||
6 | |||
7 | #define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */ | ||
8 | #define SPACE 2048 /* must be multiple of ALIGNMENT */ | ||
9 | |||
10 | typedef union { char irrelevant[ALIGNMENT]; double d; } aligned; | ||
11 | static aligned realspace[SPACE / ALIGNMENT]; | ||
12 | #define space ((char *) realspace) | ||
13 | static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */ | ||
14 | |||
15 | /*@null@*//*@out@*/char *alloc(n) | ||
16 | unsigned int n; | ||
17 | { | ||
18 | char *x; | ||
19 | n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */ | ||
20 | if (n <= avail) { avail -= n; return space + avail; } | ||
21 | x = malloc(n); | ||
22 | if (!x) errno = error_nomem; | ||
23 | return x; | ||
24 | } | ||
25 | |||
26 | void alloc_free(x) | ||
27 | char *x; | ||
28 | { | ||
29 | if (x >= space) | ||
30 | if (x < space + SPACE) | ||
31 | return; /* XXX: assuming that pointers are flat */ | ||
32 | free(x); | ||
33 | } | ||
@@ -0,0 +1,10 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef ALLOC_H | ||
4 | #define ALLOC_H | ||
5 | |||
6 | extern /*@null@*//*@out@*/char *alloc(); | ||
7 | extern void alloc_free(); | ||
8 | extern int alloc_re(); | ||
9 | |||
10 | #endif | ||
diff --git a/alloc_re.c b/alloc_re.c new file mode 100644 index 0000000..1074609 --- /dev/null +++ b/alloc_re.c | |||
@@ -0,0 +1,19 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "alloc.h" | ||
4 | #include "byte.h" | ||
5 | |||
6 | int alloc_re(x,m,n) | ||
7 | char **x; | ||
8 | unsigned int m; | ||
9 | unsigned int n; | ||
10 | { | ||
11 | char *y; | ||
12 | |||
13 | y = alloc(n); | ||
14 | if (!y) return 0; | ||
15 | byte_copy(y,m,*x); | ||
16 | alloc_free(*x); | ||
17 | *x = y; | ||
18 | return 1; | ||
19 | } | ||
diff --git a/buffer.h b/buffer.h new file mode 100644 index 0000000..8f2e572 --- /dev/null +++ b/buffer.h | |||
@@ -0,0 +1,61 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef BUFFER_H | ||
4 | #define BUFFER_H | ||
5 | |||
6 | typedef struct buffer { | ||
7 | char *x; | ||
8 | unsigned int p; | ||
9 | unsigned int n; | ||
10 | int fd; | ||
11 | int (*op)(); | ||
12 | } buffer; | ||
13 | |||
14 | #define BUFFER_INIT(op,fd,buf,len) { (buf), 0, (len), (fd), (op) } | ||
15 | #define BUFFER_INSIZE 8192 | ||
16 | #define BUFFER_OUTSIZE 8192 | ||
17 | |||
18 | extern void buffer_init(buffer *,int (*)(),int,char *,unsigned int); | ||
19 | |||
20 | extern int buffer_flush(buffer *); | ||
21 | extern int buffer_put(buffer *,const char *,unsigned int); | ||
22 | extern int buffer_putalign(buffer *,const char *,unsigned int); | ||
23 | extern int buffer_putflush(buffer *,const char *,unsigned int); | ||
24 | extern int buffer_puts(buffer *,const char *); | ||
25 | extern int buffer_putsalign(buffer *,const char *); | ||
26 | extern int buffer_putsflush(buffer *,const char *); | ||
27 | |||
28 | #define buffer_PUTC(s,c) \ | ||
29 | ( ((s)->n != (s)->p) \ | ||
30 | ? ( (s)->x[(s)->p++] = (c), 0 ) \ | ||
31 | : buffer_put((s),&(c),1) \ | ||
32 | ) | ||
33 | |||
34 | extern int buffer_get(buffer *,char *,unsigned int); | ||
35 | extern int buffer_bget(buffer *,char *,unsigned int); | ||
36 | extern int buffer_feed(buffer *); | ||
37 | |||
38 | extern char *buffer_peek(buffer *); | ||
39 | extern void buffer_seek(buffer *,unsigned int); | ||
40 | |||
41 | #define buffer_PEEK(s) ( (s)->x + (s)->n ) | ||
42 | #define buffer_SEEK(s,len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) ) | ||
43 | |||
44 | #define buffer_GETC(s,c) \ | ||
45 | ( ((s)->p > 0) \ | ||
46 | ? ( *(c) = (s)->x[(s)->n], buffer_SEEK((s),1), 1 ) \ | ||
47 | : buffer_get((s),(c),1) \ | ||
48 | ) | ||
49 | |||
50 | extern int buffer_copy(buffer *,buffer *); | ||
51 | |||
52 | extern int buffer_unixread(int,char *,unsigned int); | ||
53 | extern int buffer_unixwrite(int,const char *,unsigned int); | ||
54 | |||
55 | extern buffer *buffer_0; | ||
56 | extern buffer *buffer_0small; | ||
57 | extern buffer *buffer_1; | ||
58 | extern buffer *buffer_1small; | ||
59 | extern buffer *buffer_2; | ||
60 | |||
61 | #endif | ||
diff --git a/buffer_2.c b/buffer_2.c new file mode 100644 index 0000000..f255a92 --- /dev/null +++ b/buffer_2.c | |||
@@ -0,0 +1,7 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "buffer.h" | ||
4 | |||
5 | char buffer_2_space[256]; | ||
6 | static buffer it = BUFFER_INIT(buffer_unixwrite,2,buffer_2_space,sizeof buffer_2_space); | ||
7 | buffer *buffer_2 = ⁢ | ||
diff --git a/buffer_put.c b/buffer_put.c new file mode 100644 index 0000000..23164b3 --- /dev/null +++ b/buffer_put.c | |||
@@ -0,0 +1,90 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "buffer.h" | ||
4 | #include "str.h" | ||
5 | #include "byte.h" | ||
6 | #include "error.h" | ||
7 | |||
8 | static int allwrite(int (*op)(),int fd,const char *buf,unsigned int len) | ||
9 | { | ||
10 | int w; | ||
11 | |||
12 | while (len) { | ||
13 | w = op(fd,buf,len); | ||
14 | if (w == -1) { | ||
15 | if (errno == error_intr) continue; | ||
16 | return -1; /* note that some data may have been written */ | ||
17 | } | ||
18 | if (w == 0) ; /* luser's fault */ | ||
19 | buf += w; | ||
20 | len -= w; | ||
21 | } | ||
22 | return 0; | ||
23 | } | ||
24 | |||
25 | int buffer_flush(buffer *s) | ||
26 | { | ||
27 | int p; | ||
28 | |||
29 | p = s->p; | ||
30 | if (!p) return 0; | ||
31 | s->p = 0; | ||
32 | return allwrite(s->op,s->fd,s->x,p); | ||
33 | } | ||
34 | |||
35 | int buffer_putalign(buffer *s,const char *buf,unsigned int len) | ||
36 | { | ||
37 | unsigned int n; | ||
38 | |||
39 | while (len > (n = s->n - s->p)) { | ||
40 | byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n; | ||
41 | if (buffer_flush(s) == -1) return -1; | ||
42 | } | ||
43 | /* now len <= s->n - s->p */ | ||
44 | byte_copy(s->x + s->p,len,buf); | ||
45 | s->p += len; | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | int buffer_put(buffer *s,const char *buf,unsigned int len) | ||
50 | { | ||
51 | unsigned int n; | ||
52 | |||
53 | n = s->n; | ||
54 | if (len > n - s->p) { | ||
55 | if (buffer_flush(s) == -1) return -1; | ||
56 | /* now s->p == 0 */ | ||
57 | if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE; | ||
58 | while (len > s->n) { | ||
59 | if (n > len) n = len; | ||
60 | if (allwrite(s->op,s->fd,buf,n) == -1) return -1; | ||
61 | buf += n; | ||
62 | len -= n; | ||
63 | } | ||
64 | } | ||
65 | /* now len <= s->n - s->p */ | ||
66 | byte_copy(s->x + s->p,len,buf); | ||
67 | s->p += len; | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | int buffer_putflush(buffer *s,const char *buf,unsigned int len) | ||
72 | { | ||
73 | if (buffer_flush(s) == -1) return -1; | ||
74 | return allwrite(s->op,s->fd,buf,len); | ||
75 | } | ||
76 | |||
77 | int buffer_putsalign(buffer *s,const char *buf) | ||
78 | { | ||
79 | return buffer_putalign(s,buf,str_len(buf)); | ||
80 | } | ||
81 | |||
82 | int buffer_puts(buffer *s,const char *buf) | ||
83 | { | ||
84 | return buffer_put(s,buf,str_len(buf)); | ||
85 | } | ||
86 | |||
87 | int buffer_putsflush(buffer *s,const char *buf) | ||
88 | { | ||
89 | return buffer_putflush(s,buf,str_len(buf)); | ||
90 | } | ||
diff --git a/buffer_write.c b/buffer_write.c new file mode 100644 index 0000000..4ba13ef --- /dev/null +++ b/buffer_write.c | |||
@@ -0,0 +1,9 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include <unistd.h> | ||
4 | #include "buffer.h" | ||
5 | |||
6 | int buffer_unixwrite(int fd,const char *buf,unsigned int len) | ||
7 | { | ||
8 | return write(fd,buf,len); | ||
9 | } | ||
diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..0c8562d --- /dev/null +++ b/build.sh | |||
@@ -0,0 +1 @@ | |||
gcc -I./runit-2.1.2/src/ -I. ./runit-2.1.2/src/chpst.c runit-2.1.2/src/pathexec_env.c runit-2.1.2/src/str_chr.c runit-2.1.2/src/sgetopt.c runit-2.1.2/src/subgetopt.c runit-2.1.2/src/pathexec_run.c runit-2.1.2/src/stralloc_catb.c runit-2.1.2/src/stralloc_cat.c runit-2.1.2/src/stralloc_cats.c runit-2.1.2/src/stralloc_eady.c runit-2.1.2/src/stralloc_opyb.c runit-2.1.2/src/stralloc_opys.c runit-2.1.2/src/stralloc_pend.c runit-2.1.2/src/byte_copy.c runit-2.1.2/src/error.c runit-2.1.2/src/error_str.c runit-2.1.2/src/strerr_sys.c runit-2.1.2/src/buffer_put.c runit-2.1.2/src/str_len.c runit-2.1.2/src/alloc_re.c runit-2.1.2/src/str_diff.c runit-2.1.2/src/strerr_die.c runit-2.1.2/src/buffer_2.c runit-2.1.2/src/scan_ulong.c runit-2.1.2/src/alloc.c runit-2.1.2/src/uidgid.c runit-2.1.2/src/buffer_write.c runit-2.1.2/src/open_append.c runit-2.1.2/src/open_read.c runit-2.1.2/src/prot.c runit-2.1.2/src/fmt_ulong.c runit-2.1.2/src/openreadclose.c runit-2.1.2/src/readclose.c runit-2.1.2/src/byte_diff.c runit-2.1.2/src/byte_chr.c runit-2.1.2/src/lock_exnb.c runit-2.1.2/src/lock_ex.c runit-2.1.2/src/env.c runit-2.1.2/src/str_start.c -ochpst -lnsl | |||
@@ -0,0 +1,15 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef BYTE_H | ||
4 | #define BYTE_H | ||
5 | |||
6 | extern unsigned int byte_chr(); | ||
7 | extern unsigned int byte_rchr(); | ||
8 | extern void byte_copy(); | ||
9 | extern void byte_copyr(); | ||
10 | extern int byte_diff(); | ||
11 | extern void byte_zero(); | ||
12 | |||
13 | #define byte_equal(s,n,t) (!byte_diff((s),(n),(t))) | ||
14 | |||
15 | #endif | ||
diff --git a/byte_chr.c b/byte_chr.c new file mode 100644 index 0000000..fd56056 --- /dev/null +++ b/byte_chr.c | |||
@@ -0,0 +1,22 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "byte.h" | ||
4 | |||
5 | unsigned int byte_chr(s,n,c) | ||
6 | char *s; | ||
7 | register unsigned int n; | ||
8 | int c; | ||
9 | { | ||
10 | register char ch; | ||
11 | register char *t; | ||
12 | |||
13 | ch = c; | ||
14 | t = s; | ||
15 | for (;;) { | ||
16 | if (!n) break; if (*t == ch) break; ++t; --n; | ||
17 | if (!n) break; if (*t == ch) break; ++t; --n; | ||
18 | if (!n) break; if (*t == ch) break; ++t; --n; | ||
19 | if (!n) break; if (*t == ch) break; ++t; --n; | ||
20 | } | ||
21 | return t - s; | ||
22 | } | ||
diff --git a/byte_copy.c b/byte_copy.c new file mode 100644 index 0000000..74c9e4a --- /dev/null +++ b/byte_copy.c | |||
@@ -0,0 +1,16 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "byte.h" | ||
4 | |||
5 | void byte_copy(to,n,from) | ||
6 | register char *to; | ||
7 | register unsigned int n; | ||
8 | register char *from; | ||
9 | { | ||
10 | for (;;) { | ||
11 | if (!n) return; *to++ = *from++; --n; | ||
12 | if (!n) return; *to++ = *from++; --n; | ||
13 | if (!n) return; *to++ = *from++; --n; | ||
14 | if (!n) return; *to++ = *from++; --n; | ||
15 | } | ||
16 | } | ||
diff --git a/byte_diff.c b/byte_diff.c new file mode 100644 index 0000000..0c4d17b --- /dev/null +++ b/byte_diff.c | |||
@@ -0,0 +1,18 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "byte.h" | ||
4 | |||
5 | int byte_diff(s,n,t) | ||
6 | register char *s; | ||
7 | register unsigned int n; | ||
8 | register char *t; | ||
9 | { | ||
10 | for (;;) { | ||
11 | if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; | ||
12 | if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; | ||
13 | if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; | ||
14 | if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; | ||
15 | } | ||
16 | return ((int)(unsigned int)(unsigned char) *s) | ||
17 | - ((int)(unsigned int)(unsigned char) *t); | ||
18 | } | ||
@@ -0,0 +1,475 @@ | |||
1 | #include <sys/types.h> | ||
2 | #include <time.h> | ||
3 | #include <sys/time.h> | ||
4 | #include <sys/resource.h> | ||
5 | #include <unistd.h> | ||
6 | #include "sgetopt.h" | ||
7 | #include "error.h" | ||
8 | #include "strerr.h" | ||
9 | #include "str.h" | ||
10 | #include "uidgid.h" | ||
11 | #include "prot.h" | ||
12 | #include "strerr.h" | ||
13 | #include "scan.h" | ||
14 | #include "fmt.h" | ||
15 | #include "lock.h" | ||
16 | #include "pathexec.h" | ||
17 | #include "stralloc.h" | ||
18 | #include "byte.h" | ||
19 | #include "open.h" | ||
20 | #include "openreadclose.h" | ||
21 | #include "direntry.h" | ||
22 | |||
23 | #define USAGE_MAIN " [-vP012] [-u user[:group]] [-U user[:group]] [-b argv0] [-e dir] [-/ root] [-n nice] [-l|-L lock] [-m n] [-d n] [-o n] [-p n] [-f n] [-c n] prog" | ||
24 | #define FATAL "chpst: fatal: " | ||
25 | #define WARNING "chpst: warning: " | ||
26 | |||
27 | const char *progname; | ||
28 | static stralloc sa; | ||
29 | |||
30 | void fatal(const char *m) { strerr_die3sys(111, FATAL, m, ": "); } | ||
31 | void fatal2(const char *m0, const char *m1) { | ||
32 | strerr_die5sys(111, FATAL, m0, ": ", m1, ": "); | ||
33 | } | ||
34 | void fatalx(const char *m0, const char *m1) { | ||
35 | strerr_die4x(111, FATAL, m0, ": ", m1); | ||
36 | } | ||
37 | void warn(const char *m) { strerr_warn2(WARNING, m, 0); } | ||
38 | void die_nomem() { strerr_die2x(111, FATAL, "out of memory."); } | ||
39 | void usage() { strerr_die4x(100, "usage: ", progname, USAGE_MAIN, "\n"); } | ||
40 | |||
41 | char *set_user =0; | ||
42 | char *env_user =0; | ||
43 | const char *argv0 =0; | ||
44 | const char *env_dir =0; | ||
45 | unsigned int verbose =0; | ||
46 | unsigned int pgrp =0; | ||
47 | unsigned int nostdin =0; | ||
48 | unsigned int nostdout =0; | ||
49 | unsigned int nostderr =0; | ||
50 | long limitd =-2; | ||
51 | long limits =-2; | ||
52 | long limitl =-2; | ||
53 | long limita =-2; | ||
54 | long limito =-2; | ||
55 | long limitp =-2; | ||
56 | long limitf =-2; | ||
57 | long limitc =-2; | ||
58 | long limitr =-2; | ||
59 | long limitt =-2; | ||
60 | long nicelvl =0; | ||
61 | const char *lock =0; | ||
62 | const char *root =0; | ||
63 | unsigned int lockdelay; | ||
64 | |||
65 | void suidgid(char *user, unsigned int ext) { | ||
66 | struct uidgid ugid; | ||
67 | |||
68 | if (ext) { | ||
69 | if (! uidgids_get(&ugid, user)) { | ||
70 | if (*user == ':') fatalx("invalid uid/gids", user +1); | ||
71 | if (errno) fatal("unable to get password/group file entry"); | ||
72 | fatalx("unknown user/group", user); | ||
73 | } | ||
74 | } | ||
75 | else | ||
76 | if (! uidgid_get(&ugid, user)) { | ||
77 | if (errno) fatal("unable to get password file entry"); | ||
78 | fatalx("unknown account", user); | ||
79 | } | ||
80 | if (setgroups(ugid.gids, ugid.gid) == -1) fatal("unable to setgroups"); | ||
81 | if (setgid(*ugid.gid) == -1) fatal("unable to setgid"); | ||
82 | if (prot_uid(ugid.uid) == -1) fatal("unable to setuid"); | ||
83 | } | ||
84 | |||
85 | void euidgid(char *user, unsigned int ext) { | ||
86 | struct uidgid ugid; | ||
87 | char bufnum[FMT_ULONG]; | ||
88 | |||
89 | if (ext) { | ||
90 | if (! uidgids_get(&ugid, user)) { | ||
91 | if (*user == ':') fatalx("invalid uid/gids", user +1); | ||
92 | if (errno) fatal("unable to get password/group file entry"); | ||
93 | fatalx("unknown user/group", user); | ||
94 | } | ||
95 | } | ||
96 | else | ||
97 | if (! uidgid_get(&ugid, user)) { | ||
98 | if (errno) fatal("unable to get password file entry"); | ||
99 | fatalx("unknown account", user); | ||
100 | } | ||
101 | bufnum[fmt_ulong(bufnum, *ugid.gid)] =0; | ||
102 | if (! pathexec_env("GID", bufnum)) die_nomem(); | ||
103 | bufnum[fmt_ulong(bufnum, ugid.uid)] =0; | ||
104 | if (! pathexec_env("UID", bufnum)) die_nomem(); | ||
105 | } | ||
106 | |||
107 | void edir(const char *dirname) { | ||
108 | int wdir; | ||
109 | DIR *dir; | ||
110 | direntry *d; | ||
111 | int i; | ||
112 | |||
113 | if ((wdir =open_read(".")) == -1) | ||
114 | fatal("unable to open current working directory"); | ||
115 | if (chdir(dirname)) fatal2("unable to switch to directory", dirname); | ||
116 | if (! (dir =opendir("."))) fatal2("unable to open directory", dirname); | ||
117 | for (;;) { | ||
118 | errno =0; | ||
119 | d =readdir(dir); | ||
120 | if (! d) { | ||
121 | if (errno) fatal2("unable to read directory", dirname); | ||
122 | break; | ||
123 | } | ||
124 | if (d->d_name[0] == '.') continue; | ||
125 | if (openreadclose(d->d_name, &sa, 256) == -1) { | ||
126 | if ((errno == error_isdir) && env_dir) { | ||
127 | if (verbose) | ||
128 | strerr_warn6(WARNING, "unable to read ", dirname, "/", | ||
129 | d->d_name, ": ", &strerr_sys); | ||
130 | continue; | ||
131 | } | ||
132 | else | ||
133 | strerr_die6sys(111, FATAL, "unable to read ", dirname, "/", | ||
134 | d->d_name, ": "); | ||
135 | } | ||
136 | if (sa.len) { | ||
137 | sa.len =byte_chr(sa.s, sa.len, '\n'); | ||
138 | while (sa.len && (sa.s[sa.len -1] == ' ' || sa.s[sa.len -1] == '\t')) | ||
139 | --sa.len; | ||
140 | for (i =0; i < sa.len; ++i) if (! sa.s[i]) sa.s[i] ='\n'; | ||
141 | if (! stralloc_0(&sa)) die_nomem(); | ||
142 | if (! pathexec_env(d->d_name, sa.s)) die_nomem(); | ||
143 | } | ||
144 | else | ||
145 | if (! pathexec_env(d->d_name, 0)) die_nomem(); | ||
146 | } | ||
147 | closedir(dir); | ||
148 | if (fchdir(wdir) == -1) fatal("unable to switch to starting directory"); | ||
149 | close(wdir); | ||
150 | } | ||
151 | |||
152 | void slock_die(const char *m, const char *f, unsigned int x) { | ||
153 | if (! x) fatal2(m, f); | ||
154 | _exit(0); | ||
155 | } | ||
156 | void slock(const char *f, unsigned int d, unsigned int x) { | ||
157 | int fd; | ||
158 | |||
159 | if ((fd =open_append(f)) == -1) slock_die("unable to open lock", f, x); | ||
160 | if (d) { | ||
161 | if (lock_ex(fd) == -1) slock_die("unable to lock", f, x); | ||
162 | return; | ||
163 | } | ||
164 | if (lock_exnb(fd) == -1) slock_die("unable to lock", f, x); | ||
165 | } | ||
166 | |||
167 | void limit(int what, long l) { | ||
168 | struct rlimit r; | ||
169 | |||
170 | if (getrlimit(what, &r) == -1) fatal("unable to getrlimit()"); | ||
171 | if ((l < 0) || (l > r.rlim_max)) | ||
172 | r.rlim_cur =r.rlim_max; | ||
173 | else | ||
174 | r.rlim_cur =l; | ||
175 | if (setrlimit(what, &r) == -1) fatal("unable to setrlimit()"); | ||
176 | } | ||
177 | void slimit() { | ||
178 | if (limitd >= -1) { | ||
179 | #ifdef RLIMIT_DATA | ||
180 | limit(RLIMIT_DATA, limitd); | ||
181 | #else | ||
182 | if (verbose) warn("system does not support RLIMIT_DATA"); | ||
183 | #endif | ||
184 | } | ||
185 | if (limits >= -1) { | ||
186 | #ifdef RLIMIT_STACK | ||
187 | limit(RLIMIT_STACK, limits); | ||
188 | #else | ||
189 | if (verbose) warn("system does not support RLIMIT_STACK"); | ||
190 | #endif | ||
191 | } | ||
192 | if (limitl >= -1) { | ||
193 | #ifdef RLIMIT_MEMLOCK | ||
194 | limit(RLIMIT_MEMLOCK, limitl); | ||
195 | #else | ||
196 | if (verbose) warn("system does not support RLIMIT_MEMLOCK"); | ||
197 | #endif | ||
198 | } | ||
199 | if (limita >= -1) { | ||
200 | #ifdef RLIMIT_VMEM | ||
201 | limit(RLIMIT_VMEM, limita); | ||
202 | #else | ||
203 | #ifdef RLIMIT_AS | ||
204 | limit(RLIMIT_AS, limita); | ||
205 | #else | ||
206 | if (verbose) | ||
207 | warn("system does neither support RLIMIT_VMEM nor RLIMIT_AS"); | ||
208 | #endif | ||
209 | #endif | ||
210 | } | ||
211 | if (limito >= -1) { | ||
212 | #ifdef RLIMIT_NOFILE | ||
213 | limit(RLIMIT_NOFILE, limito); | ||
214 | #else | ||
215 | #ifdef RLIMIT_OFILE | ||
216 | limit(RLIMIT_OFILE, limito); | ||
217 | #else | ||
218 | if (verbose) | ||
219 | warn("system does neither support RLIMIT_NOFILE nor RLIMIT_OFILE"); | ||
220 | #endif | ||
221 | #endif | ||
222 | } | ||
223 | if (limitp >= -1) { | ||
224 | #ifdef RLIMIT_NPROC | ||
225 | limit(RLIMIT_NPROC, limitp); | ||
226 | #else | ||
227 | if (verbose) warn("system does not support RLIMIT_NPROC"); | ||
228 | #endif | ||
229 | } | ||
230 | if (limitf >= -1) { | ||
231 | #ifdef RLIMIT_FSIZE | ||
232 | limit(RLIMIT_FSIZE, limitf); | ||
233 | #else | ||
234 | if (verbose) warn("system does not support RLIMIT_FSIZE"); | ||
235 | #endif | ||
236 | } | ||
237 | if (limitc >= -1) { | ||
238 | #ifdef RLIMIT_CORE | ||
239 | limit(RLIMIT_CORE, limitc); | ||
240 | #else | ||
241 | if (verbose) warn("system does not support RLIMIT_CORE"); | ||
242 | #endif | ||
243 | } | ||
244 | if (limitr >= -1) { | ||
245 | #ifdef RLIMIT_RSS | ||
246 | limit(RLIMIT_RSS, limitr); | ||
247 | #else | ||
248 | if (verbose) warn("system does not support RLIMIT_RSS"); | ||
249 | #endif | ||
250 | } | ||
251 | if (limitt >= -1) { | ||
252 | #ifdef RLIMIT_CPU | ||
253 | limit(RLIMIT_CPU, limitt); | ||
254 | #else | ||
255 | if (verbose) warn("system does not support RLIMIT_CPU"); | ||
256 | #endif | ||
257 | } | ||
258 | } | ||
259 | |||
260 | /* argv[0] */ | ||
261 | void setuidgid(int, const char *const *); | ||
262 | void envuidgid(int, const char *const *); | ||
263 | void envdir(int, const char *const *); | ||
264 | void pgrphack(int, const char *const *); | ||
265 | void setlock(int, const char *const *); | ||
266 | void softlimit(int, const char *const *); | ||
267 | |||
268 | int main(int argc, const char **argv) { | ||
269 | int opt; | ||
270 | int i; | ||
271 | unsigned long ul; | ||
272 | |||
273 | progname =argv[0]; | ||
274 | for (i =str_len(progname); i; --i) | ||
275 | if (progname[i -1] == '/') { | ||
276 | progname +=i; | ||
277 | break; | ||
278 | } | ||
279 | if (progname[0] == 'd') ++progname; | ||
280 | |||
281 | /* argv[0] */ | ||
282 | if (str_equal(progname, "setuidgid")) setuidgid(argc, argv); | ||
283 | if (str_equal(progname, "envuidgid")) envuidgid(argc, argv); | ||
284 | if (str_equal(progname, "envdir")) envdir(argc, argv); | ||
285 | if (str_equal(progname, "pgrphack")) pgrphack(argc, argv); | ||
286 | if (str_equal(progname, "setlock")) setlock(argc, argv); | ||
287 | if (str_equal(progname, "softlimit")) softlimit(argc, argv); | ||
288 | |||
289 | while ((opt =getopt(argc, argv, "u:U:b:e:m:d:o:p:f:c:r:t:/:n:l:L:vP012V")) | ||
290 | != opteof) | ||
291 | switch(opt) { | ||
292 | case 'u': set_user =(char*)optarg; break; | ||
293 | case 'U': env_user =(char*)optarg; break; | ||
294 | case 'b': argv0 =(char*)optarg; break; | ||
295 | case 'e': env_dir =optarg; break; | ||
296 | case 'm': | ||
297 | if (optarg[scan_ulong(optarg, &ul)]) usage(); | ||
298 | limits =limitl =limita =limitd =ul; | ||
299 | break; | ||
300 | case 'd': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitd =ul; break; | ||
301 | case 'o': if (optarg[scan_ulong(optarg, &ul)]) usage(); limito =ul; break; | ||
302 | case 'p': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitp =ul; break; | ||
303 | case 'f': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitf =ul; break; | ||
304 | case 'c': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitc =ul; break; | ||
305 | case 'r': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitr =ul; break; | ||
306 | case 't': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitt =ul; break; | ||
307 | case '/': root =optarg; break; | ||
308 | case 'n': | ||
309 | switch (*optarg) { | ||
310 | case '-': | ||
311 | if (optarg[scan_ulong(++optarg, &ul)]) usage(); nicelvl =ul; | ||
312 | nicelvl *=-1; | ||
313 | break; | ||
314 | case '+': ++optarg; | ||
315 | default: | ||
316 | if (optarg[scan_ulong(optarg, &ul)]) usage(); nicelvl =ul; | ||
317 | break; | ||
318 | } | ||
319 | break; | ||
320 | case 'l': if (lock) usage(); lock =optarg; lockdelay =1; break; | ||
321 | case 'L': if (lock) usage(); lock =optarg; lockdelay =0; break; | ||
322 | case 'v': verbose =1; break; | ||
323 | case 'P': pgrp =1; break; | ||
324 | case '0': nostdin =1; break; | ||
325 | case '1': nostdout =1; break; | ||
326 | case '2': nostderr =1; break; | ||
327 | case 'V': strerr_warn1("$Id: f279d44141c981dd7535a12260efcf1ef7beed26 $", 0); | ||
328 | case '?': usage(); | ||
329 | } | ||
330 | argv +=optind; | ||
331 | if (! argv || ! *argv) usage(); | ||
332 | |||
333 | if (pgrp) setsid(); | ||
334 | if (env_dir) edir(env_dir); | ||
335 | if (root) { | ||
336 | if (chdir(root) == -1) fatal2("unable to change directory", root); | ||
337 | if (chroot(".") == -1) fatal("unable to change root directory"); | ||
338 | } | ||
339 | if (nicelvl) { | ||
340 | errno =0; | ||
341 | if (nice(nicelvl) == -1) if (errno) fatal("unable to set nice level"); | ||
342 | } | ||
343 | if (env_user) euidgid(env_user, 1); | ||
344 | if (set_user) suidgid(set_user, 1); | ||
345 | if (lock) slock(lock, lockdelay, 0); | ||
346 | if (nostdin) if (close(0) == -1) fatal("unable to close stdin"); | ||
347 | if (nostdout) if (close(1) == -1) fatal("unable to close stdout"); | ||
348 | if (nostderr) if (close(2) == -1) fatal("unable to close stderr"); | ||
349 | slimit(); | ||
350 | |||
351 | progname =*argv; | ||
352 | if (argv0) *argv =argv0; | ||
353 | pathexec_env_run(progname, argv); | ||
354 | fatal2("unable to run", *argv); | ||
355 | return(0); | ||
356 | } | ||
357 | |||
358 | /* argv[0] */ | ||
359 | #define USAGE_SETUIDGID " account child" | ||
360 | #define USAGE_ENVUIDGID " account child" | ||
361 | #define USAGE_ENVDIR " dir child" | ||
362 | #define USAGE_PGRPHACK " child" | ||
363 | #define USAGE_SETLOCK " [ -nNxX ] file program [ arg ... ]" | ||
364 | #define USAGE_SOFTLIMIT " [-a allbytes] [-c corebytes] [-d databytes] [-f filebytes] [-l lockbytes] [-m membytes] [-o openfiles] [-p processes] [-r residentbytes] [-s stackbytes] [-t cpusecs] child" | ||
365 | |||
366 | void setuidgid_usage() { | ||
367 | strerr_die4x(100, "usage: ", progname, USAGE_SETUIDGID, "\n"); | ||
368 | } | ||
369 | void setuidgid(int argc, const char *const *argv) { | ||
370 | const char *account; | ||
371 | |||
372 | if (! (account =*++argv)) setuidgid_usage(); | ||
373 | if (! *++argv) setuidgid_usage(); | ||
374 | suidgid((char*)account, 0); | ||
375 | pathexec(argv); | ||
376 | fatal2("unable to run", *argv); | ||
377 | } | ||
378 | |||
379 | void envuidgid_usage() { | ||
380 | strerr_die4x(100, "usage: ", progname, USAGE_ENVUIDGID, "\n"); | ||
381 | } | ||
382 | void envuidgid(int argc, const char *const *argv) { | ||
383 | const char *account; | ||
384 | |||
385 | if (! (account =*++argv)) envuidgid_usage(); | ||
386 | if (! *++argv) envuidgid_usage(); | ||
387 | euidgid((char*)account, 0); | ||
388 | pathexec(argv); | ||
389 | fatal2("unable to run", *argv); | ||
390 | } | ||
391 | |||
392 | void envdir_usage() { | ||
393 | strerr_die4x(100, "usage: ", progname, USAGE_ENVDIR, "\n"); | ||
394 | } | ||
395 | void envdir(int argc, const char *const *argv) { | ||
396 | const char *dir; | ||
397 | |||
398 | if (! (dir =*++argv)) envdir_usage(); | ||
399 | if (! *++argv) envdir_usage(); | ||
400 | edir(dir); | ||
401 | pathexec(argv); | ||
402 | fatal2("unable to run", *argv); | ||
403 | } | ||
404 | |||
405 | void pgrphack_usage() { | ||
406 | strerr_die4x(100, "usage: ", progname, USAGE_PGRPHACK, "\n"); | ||
407 | } | ||
408 | void pgrphack(int argc, const char *const *argv) { | ||
409 | if (! *++argv) pgrphack_usage(); | ||
410 | setsid(); | ||
411 | pathexec(argv); | ||
412 | fatal2("unable to run", *argv); | ||
413 | } | ||
414 | |||
415 | void setlock_usage() { | ||
416 | strerr_die4x(100, "usage: ", progname, USAGE_SETLOCK, "\n"); | ||
417 | } | ||
418 | void setlock(int argc, const char *const *argv) { | ||
419 | int opt; | ||
420 | unsigned int delay =0; | ||
421 | unsigned int x =0; | ||
422 | const char *fn; | ||
423 | |||
424 | while ((opt =getopt(argc, argv, "nNxX")) != opteof) | ||
425 | switch(opt) { | ||
426 | case 'n': delay =1; break; | ||
427 | case 'N': delay =0; break; | ||
428 | case 'x': x =1; break; | ||
429 | case 'X': x =0; break; | ||
430 | default: setlock_usage(); | ||
431 | } | ||
432 | argv +=optind; | ||
433 | if (! (fn =*argv)) setlock_usage(); | ||
434 | if (! *++argv) setlock_usage(); | ||
435 | |||
436 | slock(fn, delay, x); | ||
437 | pathexec(argv); | ||
438 | if (! x) fatal2("unable to run", *argv); | ||
439 | _exit(0); | ||
440 | } | ||
441 | |||
442 | void softlimit_usage() { | ||
443 | strerr_die4x(100, "usage: ", progname, USAGE_SOFTLIMIT, "\n"); | ||
444 | } | ||
445 | void getlarg(long *l) { | ||
446 | unsigned long ul; | ||
447 | |||
448 | if (str_equal(optarg, "=")) { *l =-1; return; } | ||
449 | if (optarg[scan_ulong(optarg, &ul)]) usage(); | ||
450 | *l =ul; | ||
451 | } | ||
452 | void softlimit(int argc, const char *const *argv) { | ||
453 | int opt; | ||
454 | |||
455 | while ((opt =getopt(argc,argv,"a:c:d:f:l:m:o:p:r:s:t:")) != opteof) | ||
456 | switch(opt) { | ||
457 | case '?': softlimit_usage(); | ||
458 | case 'a': getlarg(&limita); break; | ||
459 | case 'c': getlarg(&limitc); break; | ||
460 | case 'd': getlarg(&limitd); break; | ||
461 | case 'f': getlarg(&limitf); break; | ||
462 | case 'l': getlarg(&limitl); break; | ||
463 | case 'm': getlarg(&limitd); limits =limitl =limita =limitd; break; | ||
464 | case 'o': getlarg(&limito); break; | ||
465 | case 'p': getlarg(&limitp); break; | ||
466 | case 'r': getlarg(&limitr); break; | ||
467 | case 's': getlarg(&limits); break; | ||
468 | case 't': getlarg(&limitt); break; | ||
469 | } | ||
470 | argv +=optind; | ||
471 | if (!*argv) softlimit_usage(); | ||
472 | slimit(); | ||
473 | pathexec(argv); | ||
474 | fatal2("unable to run", *argv); | ||
475 | } | ||
diff --git a/direntry.h b/direntry.h new file mode 100644 index 0000000..bfd4d19 --- /dev/null +++ b/direntry.h | |||
@@ -0,0 +1,12 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef DIRENTRY_H | ||
4 | #define DIRENTRY_H | ||
5 | |||
6 | /* sysdep: +dirent */ | ||
7 | |||
8 | #include <sys/types.h> | ||
9 | #include <dirent.h> | ||
10 | #define direntry struct dirent | ||
11 | |||
12 | #endif | ||
@@ -0,0 +1,17 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "str.h" | ||
4 | #include "env.h" | ||
5 | |||
6 | extern /*@null@*/char *env_get(const char *s) | ||
7 | { | ||
8 | int i; | ||
9 | unsigned int len; | ||
10 | |||
11 | if (!s) return 0; | ||
12 | len = str_len(s); | ||
13 | for (i = 0;environ[i];++i) | ||
14 | if (str_start(environ[i],s) && (environ[i][len] == '=')) | ||
15 | return environ[i] + len + 1; | ||
16 | return 0; | ||
17 | } | ||
@@ -0,0 +1,10 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef ENV_H | ||
4 | #define ENV_H | ||
5 | |||
6 | extern char **environ; | ||
7 | |||
8 | extern /*@null@*/char *env_get(const char *); | ||
9 | |||
10 | #endif | ||
@@ -0,0 +1,132 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include <errno.h> | ||
4 | #include "error.h" | ||
5 | |||
6 | /* warning: as coverage improves here, should update error_{str,temp} */ | ||
7 | |||
8 | int error_intr = | ||
9 | #ifdef EINTR | ||
10 | EINTR; | ||
11 | #else | ||
12 | -1; | ||
13 | #endif | ||
14 | |||
15 | int error_nomem = | ||
16 | #ifdef ENOMEM | ||
17 | ENOMEM; | ||
18 | #else | ||
19 | -2; | ||
20 | #endif | ||
21 | |||
22 | int error_noent = | ||
23 | #ifdef ENOENT | ||
24 | ENOENT; | ||
25 | #else | ||
26 | -3; | ||
27 | #endif | ||
28 | |||
29 | int error_txtbsy = | ||
30 | #ifdef ETXTBSY | ||
31 | ETXTBSY; | ||
32 | #else | ||
33 | -4; | ||
34 | #endif | ||
35 | |||
36 | int error_io = | ||
37 | #ifdef EIO | ||
38 | EIO; | ||
39 | #else | ||
40 | -5; | ||
41 | #endif | ||
42 | |||
43 | int error_exist = | ||
44 | #ifdef EEXIST | ||
45 | EEXIST; | ||
46 | #else | ||
47 | -6; | ||
48 | #endif | ||
49 | |||
50 | int error_timeout = | ||
51 | #ifdef ETIMEDOUT | ||
52 | ETIMEDOUT; | ||
53 | #else | ||
54 | -7; | ||
55 | #endif | ||
56 | |||
57 | int error_inprogress = | ||
58 | #ifdef EINPROGRESS | ||
59 | EINPROGRESS; | ||
60 | #else | ||
61 | -8; | ||
62 | #endif | ||
63 | |||
64 | int error_wouldblock = | ||
65 | #ifdef EWOULDBLOCK | ||
66 | EWOULDBLOCK; | ||
67 | #else | ||
68 | -9; | ||
69 | #endif | ||
70 | |||
71 | int error_again = | ||
72 | #ifdef EAGAIN | ||
73 | EAGAIN; | ||
74 | #else | ||
75 | -10; | ||
76 | #endif | ||
77 | |||
78 | int error_pipe = | ||
79 | #ifdef EPIPE | ||
80 | EPIPE; | ||
81 | #else | ||
82 | -11; | ||
83 | #endif | ||
84 | |||
85 | int error_perm = | ||
86 | #ifdef EPERM | ||
87 | EPERM; | ||
88 | #else | ||
89 | -12; | ||
90 | #endif | ||
91 | |||
92 | int error_acces = | ||
93 | #ifdef EACCES | ||
94 | EACCES; | ||
95 | #else | ||
96 | -13; | ||
97 | #endif | ||
98 | |||
99 | int error_nodevice = | ||
100 | #ifdef ENXIO | ||
101 | ENXIO; | ||
102 | #else | ||
103 | -14; | ||
104 | #endif | ||
105 | |||
106 | int error_proto = | ||
107 | #ifdef EPROTO | ||
108 | EPROTO; | ||
109 | #else | ||
110 | -15; | ||
111 | #endif | ||
112 | |||
113 | int error_isdir = | ||
114 | #ifdef EISDIR | ||
115 | EISDIR; | ||
116 | #else | ||
117 | -16; | ||
118 | #endif | ||
119 | |||
120 | int error_connrefused = | ||
121 | #ifdef ECONNREFUSED | ||
122 | ECONNREFUSED; | ||
123 | #else | ||
124 | -17; | ||
125 | #endif | ||
126 | |||
127 | int error_notdir = | ||
128 | #ifdef ENOTDIR | ||
129 | ENOTDIR; | ||
130 | #else | ||
131 | -18; | ||
132 | #endif | ||
@@ -0,0 +1,33 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef ERROR_H | ||
4 | #define ERROR_H | ||
5 | |||
6 | /* 20030124: include <errno.h> -upcoming glibc changes */ | ||
7 | #include <errno.h> | ||
8 | |||
9 | /* extern int errno; */ | ||
10 | |||
11 | extern int error_intr; | ||
12 | extern int error_nomem; | ||
13 | extern int error_noent; | ||
14 | extern int error_txtbsy; | ||
15 | extern int error_io; | ||
16 | extern int error_exist; | ||
17 | extern int error_timeout; | ||
18 | extern int error_inprogress; | ||
19 | extern int error_wouldblock; | ||
20 | extern int error_again; | ||
21 | extern int error_pipe; | ||
22 | extern int error_perm; | ||
23 | extern int error_acces; | ||
24 | extern int error_nodevice; | ||
25 | extern int error_proto; | ||
26 | extern int error_isdir; | ||
27 | extern int error_connrefused; | ||
28 | extern int error_notdir; | ||
29 | |||
30 | extern const char *error_str(int); | ||
31 | extern int error_temp(int); | ||
32 | |||
33 | #endif | ||
diff --git a/error_str.c b/error_str.c new file mode 100644 index 0000000..e002efe --- /dev/null +++ b/error_str.c | |||
@@ -0,0 +1,267 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include <errno.h> | ||
4 | #include "error.h" | ||
5 | |||
6 | #define X(e,s) if (i == e) return s; | ||
7 | |||
8 | const char *error_str(int i) | ||
9 | { | ||
10 | X(0,"no error") | ||
11 | X(error_intr,"interrupted system call") | ||
12 | X(error_nomem,"out of memory") | ||
13 | X(error_noent,"file does not exist") | ||
14 | X(error_txtbsy,"text busy") | ||
15 | X(error_io,"input/output error") | ||
16 | X(error_exist,"file already exists") | ||
17 | X(error_timeout,"timed out") | ||
18 | X(error_inprogress,"operation in progress") | ||
19 | X(error_again,"temporary failure") | ||
20 | X(error_wouldblock,"input/output would block") | ||
21 | X(error_pipe,"broken pipe") | ||
22 | X(error_perm,"permission denied") | ||
23 | X(error_acces,"access denied") | ||
24 | X(error_nodevice,"device not configured") | ||
25 | X(error_proto,"protocol error") | ||
26 | X(error_isdir,"is a directory") | ||
27 | X(error_connrefused,"connection refused") | ||
28 | X(error_notdir,"not a directory") | ||
29 | #ifdef ESRCH | ||
30 | X(ESRCH,"no such process") | ||
31 | #endif | ||
32 | #ifdef E2BIG | ||
33 | X(E2BIG,"argument list too long") | ||
34 | #endif | ||
35 | #ifdef ENOEXEC | ||
36 | X(ENOEXEC,"exec format error") | ||
37 | #endif | ||
38 | #ifdef EBADF | ||
39 | X(EBADF,"file descriptor not open") | ||
40 | #endif | ||
41 | #ifdef ECHILD | ||
42 | X(ECHILD,"no child processes") | ||
43 | #endif | ||
44 | #ifdef EDEADLK | ||
45 | X(EDEADLK,"operation would cause deadlock") | ||
46 | #endif | ||
47 | #ifdef EFAULT | ||
48 | X(EFAULT,"bad address") | ||
49 | #endif | ||
50 | #ifdef ENOTBLK | ||
51 | X(ENOTBLK,"not a block device") | ||
52 | #endif | ||
53 | #ifdef EBUSY | ||
54 | X(EBUSY,"device busy") | ||
55 | #endif | ||
56 | #ifdef EXDEV | ||
57 | X(EXDEV,"cross-device link") | ||
58 | #endif | ||
59 | #ifdef ENODEV | ||
60 | X(ENODEV,"device does not support operation") | ||
61 | #endif | ||
62 | #ifdef EINVAL | ||
63 | X(EINVAL,"invalid argument") | ||
64 | #endif | ||
65 | #ifdef ENFILE | ||
66 | X(ENFILE,"system cannot open more files") | ||
67 | #endif | ||
68 | #ifdef EMFILE | ||
69 | X(EMFILE,"process cannot open more files") | ||
70 | #endif | ||
71 | #ifdef ENOTTY | ||
72 | X(ENOTTY,"not a tty") | ||
73 | #endif | ||
74 | #ifdef EFBIG | ||
75 | X(EFBIG,"file too big") | ||
76 | #endif | ||
77 | #ifdef ENOSPC | ||
78 | X(ENOSPC,"out of disk space") | ||
79 | #endif | ||
80 | #ifdef ESPIPE | ||
81 | X(ESPIPE,"unseekable descriptor") | ||
82 | #endif | ||
83 | #ifdef EROFS | ||
84 | X(EROFS,"read-only file system") | ||
85 | #endif | ||
86 | #ifdef EMLINK | ||
87 | X(EMLINK,"too many links") | ||
88 | #endif | ||
89 | #ifdef EDOM | ||
90 | X(EDOM,"input out of range") | ||
91 | #endif | ||
92 | #ifdef ERANGE | ||
93 | X(ERANGE,"output out of range") | ||
94 | #endif | ||
95 | #ifdef EALREADY | ||
96 | X(EALREADY,"operation already in progress") | ||
97 | #endif | ||
98 | #ifdef ENOTSOCK | ||
99 | X(ENOTSOCK,"not a socket") | ||
100 | #endif | ||
101 | #ifdef EDESTADDRREQ | ||
102 | X(EDESTADDRREQ,"destination address required") | ||
103 | #endif | ||
104 | #ifdef EMSGSIZE | ||
105 | X(EMSGSIZE,"message too long") | ||
106 | #endif | ||
107 | #ifdef EPROTOTYPE | ||
108 | X(EPROTOTYPE,"incorrect protocol type") | ||
109 | #endif | ||
110 | #ifdef ENOPROTOOPT | ||
111 | X(ENOPROTOOPT,"protocol not available") | ||
112 | #endif | ||
113 | #ifdef EPROTONOSUPPORT | ||
114 | X(EPROTONOSUPPORT,"protocol not supported") | ||
115 | #endif | ||
116 | #ifdef ESOCKTNOSUPPORT | ||
117 | X(ESOCKTNOSUPPORT,"socket type not supported") | ||
118 | #endif | ||
119 | #ifdef EOPNOTSUPP | ||
120 | X(EOPNOTSUPP,"operation not supported") | ||
121 | #endif | ||
122 | #ifdef EPFNOSUPPORT | ||
123 | X(EPFNOSUPPORT,"protocol family not supported") | ||
124 | #endif | ||
125 | #ifdef EAFNOSUPPORT | ||
126 | X(EAFNOSUPPORT,"address family not supported") | ||
127 | #endif | ||
128 | #ifdef EADDRINUSE | ||
129 | X(EADDRINUSE,"address already used") | ||
130 | #endif | ||
131 | #ifdef EADDRNOTAVAIL | ||
132 | X(EADDRNOTAVAIL,"address not available") | ||
133 | #endif | ||
134 | #ifdef ENETDOWN | ||
135 | X(ENETDOWN,"network down") | ||
136 | #endif | ||
137 | #ifdef ENETUNREACH | ||
138 | X(ENETUNREACH,"network unreachable") | ||
139 | #endif | ||
140 | #ifdef ENETRESET | ||
141 | X(ENETRESET,"network reset") | ||
142 | #endif | ||
143 | #ifdef ECONNABORTED | ||
144 | X(ECONNABORTED,"connection aborted") | ||
145 | #endif | ||
146 | #ifdef ECONNRESET | ||
147 | X(ECONNRESET,"connection reset") | ||
148 | #endif | ||
149 | #ifdef ENOBUFS | ||
150 | X(ENOBUFS,"out of buffer space") | ||
151 | #endif | ||
152 | #ifdef EISCONN | ||
153 | X(EISCONN,"already connected") | ||
154 | #endif | ||
155 | #ifdef ENOTCONN | ||
156 | X(ENOTCONN,"not connected") | ||
157 | #endif | ||
158 | #ifdef ESHUTDOWN | ||
159 | X(ESHUTDOWN,"socket shut down") | ||
160 | #endif | ||
161 | #ifdef ETOOMANYREFS | ||
162 | X(ETOOMANYREFS,"too many references") | ||
163 | #endif | ||
164 | #ifdef ELOOP | ||
165 | X(ELOOP,"symbolic link loop") | ||
166 | #endif | ||
167 | #ifdef ENAMETOOLONG | ||
168 | X(ENAMETOOLONG,"file name too long") | ||
169 | #endif | ||
170 | #ifdef EHOSTDOWN | ||
171 | X(EHOSTDOWN,"host down") | ||
172 | #endif | ||
173 | #ifdef EHOSTUNREACH | ||
174 | X(EHOSTUNREACH,"host unreachable") | ||
175 | #endif | ||
176 | #ifdef ENOTEMPTY | ||
177 | X(ENOTEMPTY,"directory not empty") | ||
178 | #endif | ||
179 | #ifdef EPROCLIM | ||
180 | X(EPROCLIM,"too many processes") | ||
181 | #endif | ||
182 | #ifdef EUSERS | ||
183 | X(EUSERS,"too many users") | ||
184 | #endif | ||
185 | #ifdef EDQUOT | ||
186 | X(EDQUOT,"disk quota exceeded") | ||
187 | #endif | ||
188 | #ifdef ESTALE | ||
189 | X(ESTALE,"stale NFS file handle") | ||
190 | #endif | ||
191 | #ifdef EREMOTE | ||
192 | X(EREMOTE,"too many levels of remote in path") | ||
193 | #endif | ||
194 | #ifdef EBADRPC | ||
195 | X(EBADRPC,"RPC structure is bad") | ||
196 | #endif | ||
197 | #ifdef ERPCMISMATCH | ||
198 | X(ERPCMISMATCH,"RPC version mismatch") | ||
199 | #endif | ||
200 | #ifdef EPROGUNAVAIL | ||
201 | X(EPROGUNAVAIL,"RPC program unavailable") | ||
202 | #endif | ||
203 | #ifdef EPROGMISMATCH | ||
204 | X(EPROGMISMATCH,"program version mismatch") | ||
205 | #endif | ||
206 | #ifdef EPROCUNAVAIL | ||
207 | X(EPROCUNAVAIL,"bad procedure for program") | ||
208 | #endif | ||
209 | #ifdef ENOLCK | ||
210 | X(ENOLCK,"no locks available") | ||
211 | #endif | ||
212 | #ifdef ENOSYS | ||
213 | X(ENOSYS,"system call not available") | ||
214 | #endif | ||
215 | #ifdef EFTYPE | ||
216 | X(EFTYPE,"bad file type") | ||
217 | #endif | ||
218 | #ifdef EAUTH | ||
219 | X(EAUTH,"authentication error") | ||
220 | #endif | ||
221 | #ifdef ENEEDAUTH | ||
222 | X(ENEEDAUTH,"not authenticated") | ||
223 | #endif | ||
224 | #ifdef ENOSTR | ||
225 | X(ENOSTR,"not a stream device") | ||
226 | #endif | ||
227 | #ifdef ETIME | ||
228 | X(ETIME,"timer expired") | ||
229 | #endif | ||
230 | #ifdef ENOSR | ||
231 | X(ENOSR,"out of stream resources") | ||
232 | #endif | ||
233 | #ifdef ENOMSG | ||
234 | X(ENOMSG,"no message of desired type") | ||
235 | #endif | ||
236 | #ifdef EBADMSG | ||
237 | X(EBADMSG,"bad message type") | ||
238 | #endif | ||
239 | #ifdef EIDRM | ||
240 | X(EIDRM,"identifier removed") | ||
241 | #endif | ||
242 | #ifdef ENONET | ||
243 | X(ENONET,"machine not on network") | ||
244 | #endif | ||
245 | #ifdef ERREMOTE | ||
246 | X(ERREMOTE,"object not local") | ||
247 | #endif | ||
248 | #ifdef ENOLINK | ||
249 | X(ENOLINK,"link severed") | ||
250 | #endif | ||
251 | #ifdef EADV | ||
252 | X(EADV,"advertise error") | ||
253 | #endif | ||
254 | #ifdef ESRMNT | ||
255 | X(ESRMNT,"srmount error") | ||
256 | #endif | ||
257 | #ifdef ECOMM | ||
258 | X(ECOMM,"communication error") | ||
259 | #endif | ||
260 | #ifdef EMULTIHOP | ||
261 | X(EMULTIHOP,"multihop attempted") | ||
262 | #endif | ||
263 | #ifdef EREMCHG | ||
264 | X(EREMCHG,"remote address changed") | ||
265 | #endif | ||
266 | return "unknown error"; | ||
267 | } | ||
@@ -0,0 +1,27 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef FMT_H | ||
4 | #define FMT_H | ||
5 | |||
6 | #define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */ | ||
7 | #define FMT_LEN ((char *) 0) /* convenient abbreviation */ | ||
8 | |||
9 | extern unsigned int fmt_uint(char *,unsigned int); | ||
10 | extern unsigned int fmt_uint0(char *,unsigned int,unsigned int); | ||
11 | extern unsigned int fmt_xint(char *,unsigned int); | ||
12 | extern unsigned int fmt_nbbint(char *,unsigned int,unsigned int,unsigned int,unsigned int); | ||
13 | extern unsigned int fmt_ushort(char *,unsigned short); | ||
14 | extern unsigned int fmt_xshort(char *,unsigned short); | ||
15 | extern unsigned int fmt_nbbshort(char *,unsigned int,unsigned int,unsigned int,unsigned short); | ||
16 | extern unsigned int fmt_ulong(char *,unsigned long); | ||
17 | extern unsigned int fmt_xlong(char *,unsigned long); | ||
18 | extern unsigned int fmt_nbblong(char *,unsigned int,unsigned int,unsigned int,unsigned long); | ||
19 | |||
20 | extern unsigned int fmt_plusminus(char *,int); | ||
21 | extern unsigned int fmt_minus(char *,int); | ||
22 | extern unsigned int fmt_0x(char *,int); | ||
23 | |||
24 | extern unsigned int fmt_str(char *,const char *); | ||
25 | extern unsigned int fmt_strn(char *,const char *,unsigned int); | ||
26 | |||
27 | #endif | ||
diff --git a/fmt_ulong.c b/fmt_ulong.c new file mode 100644 index 0000000..168572f --- /dev/null +++ b/fmt_ulong.c | |||
@@ -0,0 +1,15 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "fmt.h" | ||
4 | |||
5 | unsigned int fmt_ulong(register char *s,register unsigned long u) | ||
6 | { | ||
7 | register unsigned int len; register unsigned long q; | ||
8 | len = 1; q = u; | ||
9 | while (q > 9) { ++len; q /= 10; } | ||
10 | if (s) { | ||
11 | s += len; | ||
12 | do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */ | ||
13 | } | ||
14 | return len; | ||
15 | } | ||
diff --git a/gen_alloc.h b/gen_alloc.h new file mode 100644 index 0000000..bd55e5b --- /dev/null +++ b/gen_alloc.h | |||
@@ -0,0 +1,9 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef GEN_ALLOC_H | ||
4 | #define GEN_ALLOC_H | ||
5 | |||
6 | #define GEN_ALLOC_typedef(ta,type,field,len,a) \ | ||
7 | typedef struct ta { type *field; unsigned int len; unsigned int a; } ta; | ||
8 | |||
9 | #endif | ||
diff --git a/gen_allocdefs.h b/gen_allocdefs.h new file mode 100644 index 0000000..3afd92b --- /dev/null +++ b/gen_allocdefs.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef GEN_ALLOC_DEFS_H | ||
4 | #define GEN_ALLOC_DEFS_H | ||
5 | |||
6 | #define GEN_ALLOC_ready(ta,type,field,len,a,i,n,x,base,ta_ready) \ | ||
7 | int ta_ready(register ta *x,register unsigned int n) \ | ||
8 | { register unsigned int i; \ | ||
9 | if (x->field) { \ | ||
10 | i = x->a; \ | ||
11 | if (n > i) { \ | ||
12 | x->a = base + n + (n >> 3); \ | ||
13 | if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ | ||
14 | x->a = i; return 0; } \ | ||
15 | return 1; } \ | ||
16 | x->len = 0; \ | ||
17 | return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } | ||
18 | |||
19 | #define GEN_ALLOC_readyplus(ta,type,field,len,a,i,n,x,base,ta_rplus) \ | ||
20 | int ta_rplus(register ta *x,register unsigned int n) \ | ||
21 | { register unsigned int i; \ | ||
22 | if (x->field) { \ | ||
23 | i = x->a; n += x->len; \ | ||
24 | if (n > i) { \ | ||
25 | x->a = base + n + (n >> 3); \ | ||
26 | if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ | ||
27 | x->a = i; return 0; } \ | ||
28 | return 1; } \ | ||
29 | x->len = 0; \ | ||
30 | return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } | ||
31 | |||
32 | #define GEN_ALLOC_append(ta,type,field,len,a,i,n,x,base,ta_rplus,ta_append) \ | ||
33 | int ta_append(register ta *x,register const type *i) \ | ||
34 | { if (!ta_rplus(x,1)) return 0; x->field[x->len++] = *i; return 1; } | ||
35 | |||
36 | #endif | ||
diff --git a/hasflock.h b/hasflock.h new file mode 100644 index 0000000..1878f64 --- /dev/null +++ b/hasflock.h | |||
@@ -0,0 +1,4 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | /* sysdep: +flock */ | ||
4 | #define HASFLOCK 1 | ||
diff --git a/hasshsgr.h b/hasshsgr.h new file mode 100644 index 0000000..5624ed0 --- /dev/null +++ b/hasshsgr.h | |||
@@ -0,0 +1,4 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | /* sysdep: +shortsetgroups */ | ||
4 | #define HASSHORTSETGROUPS 1 | ||
@@ -0,0 +1,10 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef LOCK_H | ||
4 | #define LOCK_H | ||
5 | |||
6 | extern int lock_ex(int); | ||
7 | extern int lock_un(int); | ||
8 | extern int lock_exnb(int); | ||
9 | |||
10 | #endif | ||
diff --git a/lock_ex.c b/lock_ex.c new file mode 100644 index 0000000..b75a764 --- /dev/null +++ b/lock_ex.c | |||
@@ -0,0 +1,13 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include <sys/types.h> | ||
4 | #include <sys/file.h> | ||
5 | #include <fcntl.h> | ||
6 | #include "hasflock.h" | ||
7 | #include "lock.h" | ||
8 | |||
9 | #ifdef HASFLOCK | ||
10 | int lock_ex(int fd) { return flock(fd,LOCK_EX); } | ||
11 | #else | ||
12 | int lock_ex(int fd) { return lockf(fd,1,0); } | ||
13 | #endif | ||
diff --git a/lock_exnb.c b/lock_exnb.c new file mode 100644 index 0000000..9ec2b9c --- /dev/null +++ b/lock_exnb.c | |||
@@ -0,0 +1,13 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include <sys/types.h> | ||
4 | #include <sys/file.h> | ||
5 | #include <fcntl.h> | ||
6 | #include "hasflock.h" | ||
7 | #include "lock.h" | ||
8 | |||
9 | #ifdef HASFLOCK | ||
10 | int lock_exnb(int fd) { return flock(fd,LOCK_EX | LOCK_NB); } | ||
11 | #else | ||
12 | int lock_exnb(int fd) { return lockf(fd,2,0); } | ||
13 | #endif | ||
@@ -0,0 +1,12 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef OPEN_H | ||
4 | #define OPEN_H | ||
5 | |||
6 | extern int open_read(const char *); | ||
7 | extern int open_excl(const char *); | ||
8 | extern int open_append(const char *); | ||
9 | extern int open_trunc(const char *); | ||
10 | extern int open_write(const char *); | ||
11 | |||
12 | #endif | ||
diff --git a/open_append.c b/open_append.c new file mode 100644 index 0000000..d1b241b --- /dev/null +++ b/open_append.c | |||
@@ -0,0 +1,8 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include <sys/types.h> | ||
4 | #include <fcntl.h> | ||
5 | #include "open.h" | ||
6 | |||
7 | int open_append(const char *fn) | ||
8 | { return open(fn,O_WRONLY | O_NDELAY | O_APPEND | O_CREAT,0600); } | ||
diff --git a/open_read.c b/open_read.c new file mode 100644 index 0000000..99b3cd1 --- /dev/null +++ b/open_read.c | |||
@@ -0,0 +1,8 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include <sys/types.h> | ||
4 | #include <fcntl.h> | ||
5 | #include "open.h" | ||
6 | |||
7 | int open_read(const char *fn) | ||
8 | { return open(fn,O_RDONLY | O_NDELAY); } | ||
diff --git a/openreadclose.c b/openreadclose.c new file mode 100644 index 0000000..635933b --- /dev/null +++ b/openreadclose.c | |||
@@ -0,0 +1,18 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "error.h" | ||
4 | #include "open.h" | ||
5 | #include "readclose.h" | ||
6 | #include "openreadclose.h" | ||
7 | |||
8 | int openreadclose(const char *fn,stralloc *sa,unsigned int bufsize) | ||
9 | { | ||
10 | int fd; | ||
11 | fd = open_read(fn); | ||
12 | if (fd == -1) { | ||
13 | if (errno == error_noent) return 0; | ||
14 | return -1; | ||
15 | } | ||
16 | if (readclose(fd,sa,bufsize) == -1) return -1; | ||
17 | return 1; | ||
18 | } | ||
diff --git a/openreadclose.h b/openreadclose.h new file mode 100644 index 0000000..728899c --- /dev/null +++ b/openreadclose.h | |||
@@ -0,0 +1,10 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef OPENREADCLOSE_H | ||
4 | #define OPENREADCLOSE_H | ||
5 | |||
6 | #include "stralloc.h" | ||
7 | |||
8 | extern int openreadclose(const char *,stralloc *,unsigned int); | ||
9 | |||
10 | #endif | ||
diff --git a/pathexec.h b/pathexec.h new file mode 100644 index 0000000..d46ab17 --- /dev/null +++ b/pathexec.h | |||
@@ -0,0 +1,11 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef PATHEXEC_H | ||
4 | #define PATHEXEC_H | ||
5 | |||
6 | extern void pathexec_run(const char *,const char * const *,const char * const *); | ||
7 | extern int pathexec_env(const char *,const char *); | ||
8 | extern void pathexec_env_run(const char *, const char * const *); | ||
9 | extern void pathexec(const char * const *); | ||
10 | |||
11 | #endif | ||
diff --git a/pathexec_env.c b/pathexec_env.c new file mode 100644 index 0000000..1305469 --- /dev/null +++ b/pathexec_env.c | |||
@@ -0,0 +1,74 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "stralloc.h" | ||
4 | #include "alloc.h" | ||
5 | #include "str.h" | ||
6 | #include "byte.h" | ||
7 | #include "env.h" | ||
8 | #include "pathexec.h" | ||
9 | |||
10 | static stralloc plus; | ||
11 | static stralloc tmp; | ||
12 | |||
13 | int pathexec_env(const char *s,const char *t) | ||
14 | { | ||
15 | if (!s) return 1; | ||
16 | if (!stralloc_copys(&tmp,s)) return 0; | ||
17 | if (t) { | ||
18 | if (!stralloc_cats(&tmp,"=")) return 0; | ||
19 | if (!stralloc_cats(&tmp,t)) return 0; | ||
20 | } | ||
21 | if (!stralloc_0(&tmp)) return 0; | ||
22 | return stralloc_cat(&plus,&tmp); | ||
23 | } | ||
24 | |||
25 | void pathexec_env_run(const char *file, const char *const *argv) | ||
26 | { | ||
27 | const char **e; | ||
28 | unsigned int elen; | ||
29 | unsigned int i; | ||
30 | unsigned int j; | ||
31 | unsigned int split; | ||
32 | unsigned int t; | ||
33 | |||
34 | if (!stralloc_cats(&plus,"")) return; | ||
35 | |||
36 | elen = 0; | ||
37 | for (i = 0;environ[i];++i) | ||
38 | ++elen; | ||
39 | for (i = 0;i < plus.len;++i) | ||
40 | if (!plus.s[i]) | ||
41 | ++elen; | ||
42 | |||
43 | e = (const char **) alloc((elen + 1) * sizeof(char *)); | ||
44 | if (!e) return; | ||
45 | |||
46 | elen = 0; | ||
47 | for (i = 0;environ[i];++i) | ||
48 | e[elen++] = environ[i]; | ||
49 | |||
50 | j = 0; | ||
51 | for (i = 0;i < plus.len;++i) | ||
52 | if (!plus.s[i]) { | ||
53 | split = str_chr(plus.s + j,'='); | ||
54 | for (t = 0;t < elen;++t) | ||
55 | if (byte_equal(plus.s + j,split,e[t])) | ||
56 | if (e[t][split] == '=') { | ||
57 | --elen; | ||
58 | e[t] = e[elen]; | ||
59 | break; | ||
60 | } | ||
61 | if (plus.s[j + split]) | ||
62 | e[elen++] = plus.s + j; | ||
63 | j = i + 1; | ||
64 | } | ||
65 | e[elen] = 0; | ||
66 | |||
67 | pathexec_run(file,argv,e); | ||
68 | alloc_free(e); | ||
69 | } | ||
70 | |||
71 | void pathexec(const char *const *argv) | ||
72 | { | ||
73 | return pathexec_env_run(*argv, argv); | ||
74 | } | ||
diff --git a/pathexec_run.c b/pathexec_run.c new file mode 100644 index 0000000..1770ac7 --- /dev/null +++ b/pathexec_run.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "error.h" | ||
4 | #include "stralloc.h" | ||
5 | #include "str.h" | ||
6 | #include "env.h" | ||
7 | #include "pathexec.h" | ||
8 | |||
9 | static stralloc tmp; | ||
10 | |||
11 | void pathexec_run(const char *file,const char * const *argv,const char * const *envp) | ||
12 | { | ||
13 | const char *path; | ||
14 | unsigned int split; | ||
15 | int savederrno; | ||
16 | |||
17 | if (file[str_chr(file,'/')]) { | ||
18 | execve(file,argv,envp); | ||
19 | return; | ||
20 | } | ||
21 | |||
22 | path = env_get("PATH"); | ||
23 | if (!path) path = "/bin:/usr/bin"; | ||
24 | |||
25 | savederrno = 0; | ||
26 | for (;;) { | ||
27 | split = str_chr(path,':'); | ||
28 | if (!stralloc_copyb(&tmp,path,split)) return; | ||
29 | if (!split) | ||
30 | if (!stralloc_cats(&tmp,".")) return; | ||
31 | if (!stralloc_cats(&tmp,"/")) return; | ||
32 | if (!stralloc_cats(&tmp,file)) return; | ||
33 | if (!stralloc_0(&tmp)) return; | ||
34 | |||
35 | execve(tmp.s,argv,envp); | ||
36 | if (errno != error_noent) { | ||
37 | savederrno = errno; | ||
38 | if ((errno != error_acces) && (errno != error_perm) && (errno != error_isdir)) return; | ||
39 | } | ||
40 | |||
41 | if (!path[split]) { | ||
42 | if (savederrno) errno = savederrno; | ||
43 | return; | ||
44 | } | ||
45 | path += split; | ||
46 | path += 1; | ||
47 | } | ||
48 | } | ||
@@ -0,0 +1,21 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "hasshsgr.h" | ||
4 | #include "prot.h" | ||
5 | |||
6 | int prot_gid(int gid) | ||
7 | { | ||
8 | #ifdef HASSHORTSETGROUPS | ||
9 | short x[2]; | ||
10 | x[0] = gid; x[1] = 73; /* catch errors */ | ||
11 | if (setgroups(1,x) == -1) return -1; | ||
12 | #else | ||
13 | if (setgroups(1,&gid) == -1) return -1; | ||
14 | #endif | ||
15 | return setgid(gid); /* _should_ be redundant, but on some systems it isn't */ | ||
16 | } | ||
17 | |||
18 | int prot_uid(int uid) | ||
19 | { | ||
20 | return setuid(uid); | ||
21 | } | ||
@@ -0,0 +1,9 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef PROT_H | ||
4 | #define PROT_H | ||
5 | |||
6 | extern int prot_gid(int); | ||
7 | extern int prot_uid(int); | ||
8 | |||
9 | #endif | ||
diff --git a/readclose.c b/readclose.c new file mode 100644 index 0000000..9d83007 --- /dev/null +++ b/readclose.c | |||
@@ -0,0 +1,23 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include <unistd.h> | ||
4 | #include "error.h" | ||
5 | #include "readclose.h" | ||
6 | |||
7 | int readclose_append(int fd,stralloc *sa,unsigned int bufsize) | ||
8 | { | ||
9 | int r; | ||
10 | for (;;) { | ||
11 | if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; } | ||
12 | r = read(fd,sa->s + sa->len,bufsize); | ||
13 | if (r == -1) if (errno == error_intr) continue; | ||
14 | if (r <= 0) { close(fd); return r; } | ||
15 | sa->len += r; | ||
16 | } | ||
17 | } | ||
18 | |||
19 | int readclose(int fd,stralloc *sa,unsigned int bufsize) | ||
20 | { | ||
21 | if (!stralloc_copys(sa,"")) { close(fd); return -1; } | ||
22 | return readclose_append(fd,sa,bufsize); | ||
23 | } | ||
diff --git a/readclose.h b/readclose.h new file mode 100644 index 0000000..bde9889 --- /dev/null +++ b/readclose.h | |||
@@ -0,0 +1,11 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef READCLOSE_H | ||
4 | #define READCLOSE_H | ||
5 | |||
6 | #include "stralloc.h" | ||
7 | |||
8 | extern int readclose_append(int,stralloc *,unsigned int); | ||
9 | extern int readclose(int,stralloc *,unsigned int); | ||
10 | |||
11 | #endif | ||
@@ -0,0 +1,30 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef SCAN_H | ||
4 | #define SCAN_H | ||
5 | |||
6 | extern unsigned int scan_uint(const char *,unsigned int *); | ||
7 | extern unsigned int scan_xint(const char *,unsigned int *); | ||
8 | extern unsigned int scan_nbbint(const char *,unsigned int,unsigned int,unsigned int,unsigned int *); | ||
9 | extern unsigned int scan_ushort(const char *,unsigned short *); | ||
10 | extern unsigned int scan_xshort(const char *,unsigned short *); | ||
11 | extern unsigned int scan_nbbshort(const char *,unsigned int,unsigned int,unsigned int,unsigned short *); | ||
12 | extern unsigned int scan_ulong(const char *,unsigned long *); | ||
13 | extern unsigned int scan_xlong(const char *,unsigned long *); | ||
14 | extern unsigned int scan_nbblong(const char *,unsigned int,unsigned int,unsigned int,unsigned long *); | ||
15 | |||
16 | extern unsigned int scan_plusminus(const char *,int *); | ||
17 | extern unsigned int scan_0x(const char *,unsigned int *); | ||
18 | |||
19 | extern unsigned int scan_whitenskip(const char *,unsigned int); | ||
20 | extern unsigned int scan_nonwhitenskip(const char *,unsigned int); | ||
21 | extern unsigned int scan_charsetnskip(const char *,const char *,unsigned int); | ||
22 | extern unsigned int scan_noncharsetnskip(const char *,const char *,unsigned int); | ||
23 | |||
24 | extern unsigned int scan_strncmp(const char *,const char *,unsigned int); | ||
25 | extern unsigned int scan_memcmp(const char *,const char *,unsigned int); | ||
26 | |||
27 | extern unsigned int scan_long(const char *,long *); | ||
28 | extern unsigned int scan_8long(const char *,unsigned long *); | ||
29 | |||
30 | #endif | ||
diff --git a/scan_ulong.c b/scan_ulong.c new file mode 100644 index 0000000..af19701 --- /dev/null +++ b/scan_ulong.c | |||
@@ -0,0 +1,16 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "scan.h" | ||
4 | |||
5 | unsigned int scan_ulong(register const char *s,register unsigned long *u) | ||
6 | { | ||
7 | register unsigned int pos = 0; | ||
8 | register unsigned long result = 0; | ||
9 | register unsigned long c; | ||
10 | while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) { | ||
11 | result = result * 10 + c; | ||
12 | ++pos; | ||
13 | } | ||
14 | *u = result; | ||
15 | return pos; | ||
16 | } | ||
diff --git a/sgetopt.c b/sgetopt.c new file mode 100644 index 0000000..8bb608f --- /dev/null +++ b/sgetopt.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | /* sgetopt.c, sgetopt.h: (yet another) improved getopt clone, outer layer | ||
4 | D. J. Bernstein, djb@pobox.com. | ||
5 | Depends on subgetopt.h, buffer.h. | ||
6 | No system requirements. | ||
7 | 19991219: Switched to buffer.h. | ||
8 | 19970208: Cleanups. | ||
9 | 931201: Baseline. | ||
10 | No known patent problems. | ||
11 | |||
12 | Documentation in sgetopt.3. | ||
13 | */ | ||
14 | |||
15 | #include "buffer.h" | ||
16 | #define SGETOPTNOSHORT | ||
17 | #include "sgetopt.h" | ||
18 | #define SUBGETOPTNOSHORT | ||
19 | #include "subgetopt.h" | ||
20 | |||
21 | #define getopt sgetoptmine | ||
22 | #define optind subgetoptind | ||
23 | #define opterr sgetopterr | ||
24 | #define optproblem subgetoptproblem | ||
25 | #define optprogname sgetoptprogname | ||
26 | |||
27 | int opterr = 1; | ||
28 | const char *optprogname = 0; | ||
29 | |||
30 | int getopt(int argc,const char *const *argv,const char *opts) | ||
31 | { | ||
32 | int c; | ||
33 | const char *s; | ||
34 | |||
35 | if (!optprogname) { | ||
36 | optprogname = *argv; | ||
37 | if (!optprogname) optprogname = ""; | ||
38 | for (s = optprogname;*s;++s) if (*s == '/') optprogname = s + 1; | ||
39 | } | ||
40 | c = subgetopt(argc,argv,opts); | ||
41 | if (opterr) | ||
42 | if (c == '?') { | ||
43 | char chp[2]; chp[0] = optproblem; chp[1] = '\n'; | ||
44 | buffer_puts(buffer_2,optprogname); | ||
45 | if (argv[optind] && (optind < argc)) | ||
46 | buffer_puts(buffer_2,": illegal option -- "); | ||
47 | else | ||
48 | buffer_puts(buffer_2,": option requires an argument -- "); | ||
49 | buffer_put(buffer_2,chp,2); | ||
50 | buffer_flush(buffer_2); | ||
51 | } | ||
52 | return c; | ||
53 | } | ||
diff --git a/sgetopt.h b/sgetopt.h new file mode 100644 index 0000000..bf8bce6 --- /dev/null +++ b/sgetopt.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef SGETOPT_H | ||
4 | #define SGETOPT_H | ||
5 | |||
6 | #ifndef SGETOPTNOSHORT | ||
7 | #define getopt sgetoptmine | ||
8 | #define optarg subgetoptarg | ||
9 | #define optind subgetoptind | ||
10 | #define optpos subgetoptpos | ||
11 | #define opterr sgetopterr | ||
12 | #define optproblem subgetoptproblem | ||
13 | #define optprogname sgetoptprogname | ||
14 | #define opteof subgetoptdone | ||
15 | #endif | ||
16 | |||
17 | #include "subgetopt.h" | ||
18 | |||
19 | extern int sgetoptmine(int,const char *const *,const char *); | ||
20 | extern int sgetopterr; | ||
21 | extern const char *sgetoptprogname; | ||
22 | |||
23 | #endif | ||
@@ -0,0 +1,16 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef STR_H | ||
4 | #define STR_H | ||
5 | |||
6 | extern unsigned int str_copy(char *,const char *); | ||
7 | extern int str_diff(const char *,const char *); | ||
8 | extern int str_diffn(const char *,const char *,unsigned int); | ||
9 | extern unsigned int str_len(const char *); | ||
10 | extern unsigned int str_chr(const char *,int); | ||
11 | extern unsigned int str_rchr(const char *,int); | ||
12 | extern int str_start(const char *,const char *); | ||
13 | |||
14 | #define str_equal(s,t) (!str_diff((s),(t))) | ||
15 | |||
16 | #endif | ||
diff --git a/str_chr.c b/str_chr.c new file mode 100644 index 0000000..9b467eb --- /dev/null +++ b/str_chr.c | |||
@@ -0,0 +1,19 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "str.h" | ||
4 | |||
5 | unsigned int str_chr(register const char *s,int c) | ||
6 | { | ||
7 | register char ch; | ||
8 | register const char *t; | ||
9 | |||
10 | ch = c; | ||
11 | t = s; | ||
12 | for (;;) { | ||
13 | if (!*t) break; if (*t == ch) break; ++t; | ||
14 | if (!*t) break; if (*t == ch) break; ++t; | ||
15 | if (!*t) break; if (*t == ch) break; ++t; | ||
16 | if (!*t) break; if (*t == ch) break; ++t; | ||
17 | } | ||
18 | return t - s; | ||
19 | } | ||
diff --git a/str_diff.c b/str_diff.c new file mode 100644 index 0000000..47dff22 --- /dev/null +++ b/str_diff.c | |||
@@ -0,0 +1,17 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "str.h" | ||
4 | |||
5 | int str_diff(register const char *s,register const char *t) | ||
6 | { | ||
7 | register char x; | ||
8 | |||
9 | for (;;) { | ||
10 | x = *s; if (x != *t) break; if (!x) break; ++s; ++t; | ||
11 | x = *s; if (x != *t) break; if (!x) break; ++s; ++t; | ||
12 | x = *s; if (x != *t) break; if (!x) break; ++s; ++t; | ||
13 | x = *s; if (x != *t) break; if (!x) break; ++s; ++t; | ||
14 | } | ||
15 | return ((int)(unsigned int)(unsigned char) x) | ||
16 | - ((int)(unsigned int)(unsigned char) *t); | ||
17 | } | ||
diff --git a/str_len.c b/str_len.c new file mode 100644 index 0000000..dedd005 --- /dev/null +++ b/str_len.c | |||
@@ -0,0 +1,16 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "str.h" | ||
4 | |||
5 | unsigned int str_len(const char *s) | ||
6 | { | ||
7 | register const char *t; | ||
8 | |||
9 | t = s; | ||
10 | for (;;) { | ||
11 | if (!*t) return t - s; ++t; | ||
12 | if (!*t) return t - s; ++t; | ||
13 | if (!*t) return t - s; ++t; | ||
14 | if (!*t) return t - s; ++t; | ||
15 | } | ||
16 | } | ||
diff --git a/str_start.c b/str_start.c new file mode 100644 index 0000000..017efc7 --- /dev/null +++ b/str_start.c | |||
@@ -0,0 +1,15 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "str.h" | ||
4 | |||
5 | int str_start(register const char *s,register const char *t) | ||
6 | { | ||
7 | register char x; | ||
8 | |||
9 | for (;;) { | ||
10 | x = *t++; if (!x) return 1; if (x != *s++) return 0; | ||
11 | x = *t++; if (!x) return 1; if (x != *s++) return 0; | ||
12 | x = *t++; if (!x) return 1; if (x != *s++) return 0; | ||
13 | x = *t++; if (!x) return 1; if (x != *s++) return 0; | ||
14 | } | ||
15 | } | ||
diff --git a/stralloc.h b/stralloc.h new file mode 100644 index 0000000..51d61bd --- /dev/null +++ b/stralloc.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef STRALLOC_H | ||
4 | #define STRALLOC_H | ||
5 | |||
6 | #include "gen_alloc.h" | ||
7 | |||
8 | GEN_ALLOC_typedef(stralloc,char,s,len,a) | ||
9 | |||
10 | extern int stralloc_ready(stralloc *,unsigned int); | ||
11 | extern int stralloc_readyplus(stralloc *,unsigned int); | ||
12 | extern int stralloc_copy(stralloc *,const stralloc *); | ||
13 | extern int stralloc_cat(stralloc *,const stralloc *); | ||
14 | extern int stralloc_copys(stralloc *,const char *); | ||
15 | extern int stralloc_cats(stralloc *,const char *); | ||
16 | extern int stralloc_copyb(stralloc *,const char *,unsigned int); | ||
17 | extern int stralloc_catb(stralloc *,const char *,unsigned int); | ||
18 | extern int stralloc_append(stralloc *,const char *); /* beware: this takes a pointer to 1 char */ | ||
19 | extern int stralloc_starts(stralloc *,const char *); | ||
20 | |||
21 | #define stralloc_0(sa) stralloc_append(sa,"") | ||
22 | |||
23 | extern int stralloc_catulong0(stralloc *,unsigned long,unsigned int); | ||
24 | extern int stralloc_catlong0(stralloc *,long,unsigned int); | ||
25 | |||
26 | #define stralloc_catlong(sa,l) (stralloc_catlong0((sa),(l),0)) | ||
27 | #define stralloc_catuint0(sa,i,n) (stralloc_catulong0((sa),(i),(n))) | ||
28 | #define stralloc_catint0(sa,i,n) (stralloc_catlong0((sa),(i),(n))) | ||
29 | #define stralloc_catint(sa,i) (stralloc_catlong0((sa),(i),0)) | ||
30 | |||
31 | #endif | ||
diff --git a/stralloc_cat.c b/stralloc_cat.c new file mode 100644 index 0000000..2c6ad58 --- /dev/null +++ b/stralloc_cat.c | |||
@@ -0,0 +1,9 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "byte.h" | ||
4 | #include "stralloc.h" | ||
5 | |||
6 | int stralloc_cat(stralloc *sato,const stralloc *safrom) | ||
7 | { | ||
8 | return stralloc_catb(sato,safrom->s,safrom->len); | ||
9 | } | ||
diff --git a/stralloc_catb.c b/stralloc_catb.c new file mode 100644 index 0000000..8ee0af4 --- /dev/null +++ b/stralloc_catb.c | |||
@@ -0,0 +1,14 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "stralloc.h" | ||
4 | #include "byte.h" | ||
5 | |||
6 | int stralloc_catb(stralloc *sa,const char *s,unsigned int n) | ||
7 | { | ||
8 | if (!sa->s) return stralloc_copyb(sa,s,n); | ||
9 | if (!stralloc_readyplus(sa,n + 1)) return 0; | ||
10 | byte_copy(sa->s + sa->len,n,s); | ||
11 | sa->len += n; | ||
12 | sa->s[sa->len] = 'Z'; /* ``offensive programming'' */ | ||
13 | return 1; | ||
14 | } | ||
diff --git a/stralloc_cats.c b/stralloc_cats.c new file mode 100644 index 0000000..ea1e290 --- /dev/null +++ b/stralloc_cats.c | |||
@@ -0,0 +1,10 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "byte.h" | ||
4 | #include "str.h" | ||
5 | #include "stralloc.h" | ||
6 | |||
7 | int stralloc_cats(stralloc *sa,const char *s) | ||
8 | { | ||
9 | return stralloc_catb(sa,s,str_len(s)); | ||
10 | } | ||
diff --git a/stralloc_eady.c b/stralloc_eady.c new file mode 100644 index 0000000..81dbb85 --- /dev/null +++ b/stralloc_eady.c | |||
@@ -0,0 +1,8 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "alloc.h" | ||
4 | #include "stralloc.h" | ||
5 | #include "gen_allocdefs.h" | ||
6 | |||
7 | GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready) | ||
8 | GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus) | ||
diff --git a/stralloc_opyb.c b/stralloc_opyb.c new file mode 100644 index 0000000..bbcff48 --- /dev/null +++ b/stralloc_opyb.c | |||
@@ -0,0 +1,13 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "stralloc.h" | ||
4 | #include "byte.h" | ||
5 | |||
6 | int stralloc_copyb(stralloc *sa,const char *s,unsigned int n) | ||
7 | { | ||
8 | if (!stralloc_ready(sa,n + 1)) return 0; | ||
9 | byte_copy(sa->s,n,s); | ||
10 | sa->len = n; | ||
11 | sa->s[n] = 'Z'; /* ``offensive programming'' */ | ||
12 | return 1; | ||
13 | } | ||
diff --git a/stralloc_opys.c b/stralloc_opys.c new file mode 100644 index 0000000..075b6f8 --- /dev/null +++ b/stralloc_opys.c | |||
@@ -0,0 +1,10 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "byte.h" | ||
4 | #include "str.h" | ||
5 | #include "stralloc.h" | ||
6 | |||
7 | int stralloc_copys(stralloc *sa,const char *s) | ||
8 | { | ||
9 | return stralloc_copyb(sa,s,str_len(s)); | ||
10 | } | ||
diff --git a/stralloc_pend.c b/stralloc_pend.c new file mode 100644 index 0000000..70cb55c --- /dev/null +++ b/stralloc_pend.c | |||
@@ -0,0 +1,7 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "alloc.h" | ||
4 | #include "stralloc.h" | ||
5 | #include "gen_allocdefs.h" | ||
6 | |||
7 | GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append) | ||
diff --git a/strerr.h b/strerr.h new file mode 100644 index 0000000..21d812d --- /dev/null +++ b/strerr.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef STRERR_H | ||
4 | #define STRERR_H | ||
5 | |||
6 | struct strerr { | ||
7 | struct strerr *who; | ||
8 | const char *x; | ||
9 | const char *y; | ||
10 | const char *z; | ||
11 | } ; | ||
12 | |||
13 | extern struct strerr strerr_sys; | ||
14 | extern void strerr_sysinit(void); | ||
15 | |||
16 | extern const char *strerr(const struct strerr *); | ||
17 | extern void strerr_warn(const char *,const char *,const char *,const char *,const char *,const char *,const struct strerr *); | ||
18 | extern void strerr_die(int,const char *,const char *,const char *,const char *,const char *,const char *,const struct strerr *); | ||
19 | |||
20 | #define STRERR(r,se,a) \ | ||
21 | { se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; } | ||
22 | |||
23 | #define STRERR_SYS(r,se,a) \ | ||
24 | { se.who = &strerr_sys; se.x = a; se.y = 0; se.z = 0; return r; } | ||
25 | #define STRERR_SYS3(r,se,a,b,c) \ | ||
26 | { se.who = &strerr_sys; se.x = a; se.y = b; se.z = c; return r; } | ||
27 | |||
28 | #define strerr_warn6(x1,x2,x3,x4,x5,x6,se) \ | ||
29 | strerr_warn((x1),(x2),(x3),(x4),(x5),(x6),(se)) | ||
30 | #define strerr_warn5(x1,x2,x3,x4,x5,se) \ | ||
31 | strerr_warn((x1),(x2),(x3),(x4),(x5),0,(se)) | ||
32 | #define strerr_warn4(x1,x2,x3,x4,se) \ | ||
33 | strerr_warn((x1),(x2),(x3),(x4),0,0,(se)) | ||
34 | #define strerr_warn3(x1,x2,x3,se) \ | ||
35 | strerr_warn((x1),(x2),(x3),0,0,0,(se)) | ||
36 | #define strerr_warn2(x1,x2,se) \ | ||
37 | strerr_warn((x1),(x2),0,0,0,0,(se)) | ||
38 | #define strerr_warn1(x1,se) \ | ||
39 | strerr_warn((x1),0,0,0,0,0,(se)) | ||
40 | |||
41 | #define strerr_die6(e,x1,x2,x3,x4,x5,x6,se) \ | ||
42 | strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(se)) | ||
43 | #define strerr_die5(e,x1,x2,x3,x4,x5,se) \ | ||
44 | strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,(se)) | ||
45 | #define strerr_die4(e,x1,x2,x3,x4,se) \ | ||
46 | strerr_die((e),(x1),(x2),(x3),(x4),0,0,(se)) | ||
47 | #define strerr_die3(e,x1,x2,x3,se) \ | ||
48 | strerr_die((e),(x1),(x2),(x3),0,0,0,(se)) | ||
49 | #define strerr_die2(e,x1,x2,se) \ | ||
50 | strerr_die((e),(x1),(x2),0,0,0,0,(se)) | ||
51 | #define strerr_die1(e,x1,se) \ | ||
52 | strerr_die((e),(x1),0,0,0,0,0,(se)) | ||
53 | |||
54 | #define strerr_die6sys(e,x1,x2,x3,x4,x5,x6) \ | ||
55 | strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),&strerr_sys) | ||
56 | #define strerr_die5sys(e,x1,x2,x3,x4,x5) \ | ||
57 | strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,&strerr_sys) | ||
58 | #define strerr_die4sys(e,x1,x2,x3,x4) \ | ||
59 | strerr_die((e),(x1),(x2),(x3),(x4),0,0,&strerr_sys) | ||
60 | #define strerr_die3sys(e,x1,x2,x3) \ | ||
61 | strerr_die((e),(x1),(x2),(x3),0,0,0,&strerr_sys) | ||
62 | #define strerr_die2sys(e,x1,x2) \ | ||
63 | strerr_die((e),(x1),(x2),0,0,0,0,&strerr_sys) | ||
64 | #define strerr_die1sys(e,x1) \ | ||
65 | strerr_die((e),(x1),0,0,0,0,0,&strerr_sys) | ||
66 | |||
67 | #define strerr_die6x(e,x1,x2,x3,x4,x5,x6) \ | ||
68 | strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),0) | ||
69 | #define strerr_die5x(e,x1,x2,x3,x4,x5) \ | ||
70 | strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,0) | ||
71 | #define strerr_die4x(e,x1,x2,x3,x4) \ | ||
72 | strerr_die((e),(x1),(x2),(x3),(x4),0,0,0) | ||
73 | #define strerr_die3x(e,x1,x2,x3) \ | ||
74 | strerr_die((e),(x1),(x2),(x3),0,0,0,0) | ||
75 | #define strerr_die2x(e,x1,x2) \ | ||
76 | strerr_die((e),(x1),(x2),0,0,0,0,0) | ||
77 | #define strerr_die1x(e,x1) \ | ||
78 | strerr_die((e),(x1),0,0,0,0,0,0) | ||
79 | |||
80 | #endif | ||
diff --git a/strerr_die.c b/strerr_die.c new file mode 100644 index 0000000..f226b80 --- /dev/null +++ b/strerr_die.c | |||
@@ -0,0 +1,33 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include <unistd.h> | ||
4 | #include "buffer.h" | ||
5 | #include "strerr.h" | ||
6 | |||
7 | void strerr_warn(const char *x1,const char *x2,const char *x3,const char *x4,const char *x5,const char *x6,const struct strerr *se) | ||
8 | { | ||
9 | strerr_sysinit(); | ||
10 | |||
11 | if (x1) buffer_puts(buffer_2,x1); | ||
12 | if (x2) buffer_puts(buffer_2,x2); | ||
13 | if (x3) buffer_puts(buffer_2,x3); | ||
14 | if (x4) buffer_puts(buffer_2,x4); | ||
15 | if (x5) buffer_puts(buffer_2,x5); | ||
16 | if (x6) buffer_puts(buffer_2,x6); | ||
17 | |||
18 | while(se) { | ||
19 | if (se->x) buffer_puts(buffer_2,se->x); | ||
20 | if (se->y) buffer_puts(buffer_2,se->y); | ||
21 | if (se->z) buffer_puts(buffer_2,se->z); | ||
22 | se = se->who; | ||
23 | } | ||
24 | |||
25 | buffer_puts(buffer_2,"\n"); | ||
26 | buffer_flush(buffer_2); | ||
27 | } | ||
28 | |||
29 | void strerr_die(int e,const char *x1,const char *x2,const char *x3,const char *x4,const char *x5,const char *x6,const struct strerr *se) | ||
30 | { | ||
31 | strerr_warn(x1,x2,x3,x4,x5,x6,se); | ||
32 | _exit(e); | ||
33 | } | ||
diff --git a/strerr_sys.c b/strerr_sys.c new file mode 100644 index 0000000..84b302f --- /dev/null +++ b/strerr_sys.c | |||
@@ -0,0 +1,14 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "error.h" | ||
4 | #include "strerr.h" | ||
5 | |||
6 | struct strerr strerr_sys; | ||
7 | |||
8 | void strerr_sysinit(void) | ||
9 | { | ||
10 | strerr_sys.who = 0; | ||
11 | strerr_sys.x = error_str(errno); | ||
12 | strerr_sys.y = ""; | ||
13 | strerr_sys.z = ""; | ||
14 | } | ||
diff --git a/subgetopt.c b/subgetopt.c new file mode 100644 index 0000000..85ace96 --- /dev/null +++ b/subgetopt.c | |||
@@ -0,0 +1,67 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #define SUBGETOPTNOSHORT | ||
4 | #include "subgetopt.h" | ||
5 | |||
6 | #define sgopt subgetopt | ||
7 | #define optind subgetoptind | ||
8 | #define optpos subgetoptpos | ||
9 | #define optarg subgetoptarg | ||
10 | #define optproblem subgetoptproblem | ||
11 | #define optdone subgetoptdone | ||
12 | |||
13 | int optind = 1; | ||
14 | int optpos = 0; | ||
15 | const char *optarg = 0; | ||
16 | int optproblem = 0; | ||
17 | int optdone = SUBGETOPTDONE; | ||
18 | |||
19 | int sgopt(int argc,const char *const *argv,const char *opts) | ||
20 | { | ||
21 | int c; | ||
22 | const char *s; | ||
23 | |||
24 | optarg = 0; | ||
25 | if (!argv || (optind >= argc) || !argv[optind]) return optdone; | ||
26 | if (optpos && !argv[optind][optpos]) { | ||
27 | ++optind; | ||
28 | optpos = 0; | ||
29 | if ((optind >= argc) || !argv[optind]) return optdone; | ||
30 | } | ||
31 | if (!optpos) { | ||
32 | if (argv[optind][0] != '-') return optdone; | ||
33 | ++optpos; | ||
34 | c = argv[optind][1]; | ||
35 | if ((c == '-') || (c == 0)) { | ||
36 | if (c) ++optind; | ||
37 | optpos = 0; | ||
38 | return optdone; | ||
39 | } | ||
40 | /* otherwise c is reassigned below */ | ||
41 | } | ||
42 | c = argv[optind][optpos]; | ||
43 | ++optpos; | ||
44 | s = opts; | ||
45 | while (*s) { | ||
46 | if (c == *s) { | ||
47 | if (s[1] == ':') { | ||
48 | optarg = argv[optind] + optpos; | ||
49 | ++optind; | ||
50 | optpos = 0; | ||
51 | if (!*optarg) { | ||
52 | optarg = argv[optind]; | ||
53 | if ((optind >= argc) || !optarg) { /* argument past end */ | ||
54 | optproblem = c; | ||
55 | return '?'; | ||
56 | } | ||
57 | ++optind; | ||
58 | } | ||
59 | } | ||
60 | return c; | ||
61 | } | ||
62 | ++s; | ||
63 | if (*s == ':') ++s; | ||
64 | } | ||
65 | optproblem = c; | ||
66 | return '?'; | ||
67 | } | ||
diff --git a/subgetopt.h b/subgetopt.h new file mode 100644 index 0000000..41ad26a --- /dev/null +++ b/subgetopt.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #ifndef SUBGETOPT_H | ||
4 | #define SUBGETOPT_H | ||
5 | |||
6 | #ifndef SUBGETOPTNOSHORT | ||
7 | #define sgopt subgetopt | ||
8 | #define sgoptarg subgetoptarg | ||
9 | #define sgoptind subgetoptind | ||
10 | #define sgoptpos subgetoptpos | ||
11 | #define sgoptproblem subgetoptproblem | ||
12 | #define sgoptprogname subgetoptprogname | ||
13 | #define sgoptdone subgetoptdone | ||
14 | #endif | ||
15 | |||
16 | #define SUBGETOPTDONE -1 | ||
17 | |||
18 | extern int subgetopt(int,const char *const *,const char *); | ||
19 | extern const char *subgetoptarg; | ||
20 | extern int subgetoptind; | ||
21 | extern int subgetoptpos; | ||
22 | extern int subgetoptproblem; | ||
23 | extern const char *subgetoptprogname; | ||
24 | extern int subgetoptdone; | ||
25 | |||
26 | #endif | ||
diff --git a/uidgid.c b/uidgid.c new file mode 100644 index 0000000..befa754 --- /dev/null +++ b/uidgid.c | |||
@@ -0,0 +1,74 @@ | |||
1 | #include <sys/types.h> | ||
2 | #include <pwd.h> | ||
3 | #include <grp.h> | ||
4 | #include "uidgid.h" | ||
5 | #include "str.h" | ||
6 | #include "scan.h" | ||
7 | |||
8 | /* user */ | ||
9 | unsigned int uidgid_get(struct uidgid *u, char *ug) { | ||
10 | struct passwd *pwd =0; | ||
11 | |||
12 | if (! (pwd =getpwnam(ug))) return(0); | ||
13 | u->gid[0] =pwd->pw_gid; u->gids =1; | ||
14 | u->uid =pwd->pw_uid; | ||
15 | return(1); | ||
16 | } | ||
17 | |||
18 | /* uid:gid[:gid[:gid]...] */ | ||
19 | unsigned int uidgids_set(struct uidgid *u, char *ug) { | ||
20 | unsigned long id; | ||
21 | int i; | ||
22 | |||
23 | if (*(ug +=scan_ulong(ug, &id)) != ':') return(0); | ||
24 | u->uid =(uid_t)id; | ||
25 | ++ug; | ||
26 | for (i =0; i < 60; ++i, ++ug) { | ||
27 | ug +=scan_ulong(ug, &id); | ||
28 | u->gid[i] =(gid_t)id; | ||
29 | if (*ug != ':') { ++i; break; } | ||
30 | } | ||
31 | u->gid[i] =0; | ||
32 | u->gids =i; | ||
33 | if (*ug) return(0); | ||
34 | return(1); | ||
35 | } | ||
36 | |||
37 | /* [:]user[:group[:group]...] */ | ||
38 | unsigned int uidgids_get(struct uidgid *u, char *ug) { | ||
39 | char *g =0; | ||
40 | struct passwd *pwd =0; | ||
41 | struct group *gr =0; | ||
42 | int i, d =0; | ||
43 | |||
44 | if (*ug == ':') return(uidgids_set(u, ug +1)); | ||
45 | if (ug[(d =str_chr(ug, ':'))] == ':') { | ||
46 | ug[d] =0; | ||
47 | g =ug +d +1; | ||
48 | } | ||
49 | if (! (pwd =getpwnam(ug))) { if (g) ug[d] =':'; return(0); } | ||
50 | u->uid =pwd->pw_uid; | ||
51 | if (! g) { | ||
52 | u->gid[0] =pwd->pw_gid; | ||
53 | u->gids =1; | ||
54 | return(1); | ||
55 | } | ||
56 | ug[d] =':'; | ||
57 | for (i =0; i < 60; ++i) { | ||
58 | if (g[(d =str_chr(g, ':'))] == ':') { | ||
59 | g[d] =0; | ||
60 | if (! (gr =getgrnam(g))) { g[d] =':'; return(0); } | ||
61 | g[d] =':'; | ||
62 | u->gid[i] =gr->gr_gid; | ||
63 | g +=d +1; | ||
64 | } | ||
65 | else { | ||
66 | if (! (gr =getgrnam(g))) return(0); | ||
67 | u->gid[i++] =gr->gr_gid; | ||
68 | break; | ||
69 | } | ||
70 | } | ||
71 | u->gid[i] =0; | ||
72 | u->gids =i; | ||
73 | return(1); | ||
74 | } | ||
diff --git a/uidgid.h b/uidgid.h new file mode 100644 index 0000000..13cacbc --- /dev/null +++ b/uidgid.h | |||
@@ -0,0 +1,18 @@ | |||
1 | #ifndef UIDGID_H | ||
2 | #define UIDGID_H | ||
3 | |||
4 | #include <sys/types.h> | ||
5 | |||
6 | struct uidgid { | ||
7 | uid_t uid; | ||
8 | gid_t gid[61]; | ||
9 | int gids; | ||
10 | }; | ||
11 | |||
12 | /* user */ | ||
13 | extern unsigned int uidgid_get(struct uidgid *, char *); | ||
14 | |||
15 | /* [:]user[:group[:group]...] */ | ||
16 | extern unsigned int uidgids_get(struct uidgid *, char *); | ||
17 | |||
18 | #endif | ||