diff options
Diffstat (limited to 'src/cmd/upas/common')
-rw-r--r-- | src/cmd/upas/common/libsys.c | 1001 | ||||
-rw-r--r-- | src/cmd/upas/common/mail.c | 57 | ||||
-rw-r--r-- | src/cmd/upas/common/makefile | 18 | ||||
-rw-r--r-- | src/cmd/upas/common/mkfile | 20 | ||||
-rw-r--r-- | src/cmd/upas/common/process.c | 175 | ||||
-rw-r--r-- | src/cmd/upas/common/sys.h | 85 |
6 files changed, 1356 insertions, 0 deletions
diff --git a/src/cmd/upas/common/libsys.c b/src/cmd/upas/common/libsys.c new file mode 100644 index 00000000..67f36798 --- /dev/null +++ b/src/cmd/upas/common/libsys.c @@ -0,0 +1,1001 @@ +#include "common.h" +#include <auth.h> +#include <ndb.h> + +/* + * number of predefined fd's + */ +int nsysfile=3; + +static char err[Errlen]; + +/* + * return the date + */ +extern char * +thedate(void) +{ + static char now[64]; + char *cp; + + strcpy(now, ctime(time(0))); + cp = strchr(now, '\n'); + if(cp) + *cp = 0; + return now; +} + +/* + * return the user id of the current user + */ +extern char * +getlog(void) +{ + return getuser(); +} +#if 0 /* jpc */ +extern char * +getlog(void) +{ + static char user[64]; + int fd; + int n; + + fd = open("/dev/user", 0); + if(fd < 0) + return nil; + if((n=read(fd, user, sizeof(user)-1)) <= 0) + return nil; + close(fd); + user[n] = 0; + return user; +} +#endif /* jpc */ +/* + * return the lock name (we use one lock per directory) + */ +static String * +lockname(char *path) +{ + String *lp; + char *cp; + + /* + * get the name of the lock file + */ + lp = s_new(); + cp = strrchr(path, '/'); + if(cp) + s_nappend(lp, path, cp - path + 1); + s_append(lp, "L.mbox"); + + return lp; +} + +int +syscreatelocked(char *path, int mode, int perm) +{ + return create(path, mode, DMEXCL|perm); +} + +int +sysopenlocked(char *path, int mode) +{ +/* return open(path, OEXCL|mode);/**/ + return open(path, mode); /* until system call is fixed */ +} + +int +sysunlockfile(int fd) +{ + return close(fd); +} + +/* + * try opening a lock file. If it doesn't exist try creating it. + */ +static int +openlockfile(Mlock *l) +{ + int fd; + Dir *d; + Dir nd; + char *p; + + fd = open(s_to_c(l->name), OREAD); + if(fd >= 0){ + l->fd = fd; + return 0; + } + + d = dirstat(s_to_c(l->name)); + if(d == nil){ + /* file doesn't exist */ + /* try creating it */ + fd = create(s_to_c(l->name), OREAD, DMEXCL|0666); + if(fd >= 0){ + nulldir(&nd); + nd.mode = DMEXCL|0666; + if(dirfwstat(fd, &nd) < 0){ + /* if we can't chmod, don't bother */ + /* live without the lock but log it */ + syslog(0, "mail", "lock error: %s: %r", s_to_c(l->name)); + remove(s_to_c(l->name)); + } + l->fd = fd; + return 0; + } + + /* couldn't create */ + /* do we have write access to the directory? */ + p = strrchr(s_to_c(l->name), '/'); + if(p != 0){ + *p = 0; + fd = access(s_to_c(l->name), 2); + *p = '/'; + if(fd < 0){ + /* live without the lock but log it */ + syslog(0, "mail", "lock error: %s: %r", s_to_c(l->name)); + return 0; + } + } else { + fd = access(".", 2); + if(fd < 0){ + /* live without the lock but log it */ + syslog(0, "mail", "lock error: %s: %r", s_to_c(l->name)); + return 0; + } + } + } else + free(d); + + return 1; /* try again later */ +} + +#define LSECS 5*60 + +/* + * Set a lock for a particular file. The lock is a file in the same directory + * and has L. prepended to the name of the last element of the file name. + */ +extern Mlock * +syslock(char *path) +{ + Mlock *l; + int tries; + + l = mallocz(sizeof(Mlock), 1); + if(l == 0) + return nil; + + l->name = lockname(path); + + /* + * wait LSECS seconds for it to unlock + */ + for(tries = 0; tries < LSECS*2; tries++){ + switch(openlockfile(l)){ + case 0: + return l; + case 1: + sleep(500); + break; + default: + goto noway; + } + } + +noway: + s_free(l->name); + free(l); + return nil; +} + +/* + * like lock except don't wait + */ +extern Mlock * +trylock(char *path) +{ + Mlock *l; + char buf[1]; + int fd; + + l = malloc(sizeof(Mlock)); + if(l == 0) + return 0; + + l->name = lockname(path); + if(openlockfile(l) != 0){ + s_free(l->name); + free(l); + return 0; + } + + /* fork process to keep lock alive */ + switch(l->pid = rfork(RFPROC)){ + default: + break; + case 0: + fd = l->fd; + for(;;){ + sleep(1000*60); + if(pread(fd, buf, 1, 0) < 0) + break; + } + _exits(0); + } + return l; +} + +extern void +syslockrefresh(Mlock *l) +{ + char buf[1]; + + pread(l->fd, buf, 1, 0); +} + +extern void +sysunlock(Mlock *l) +{ + if(l == 0) + return; + if(l->name){ + s_free(l->name); + } + if(l->fd >= 0) + close(l->fd); + if(l->pid > 0) + postnote(PNPROC, l->pid, "time to die"); + free(l); +} + +/* + * Open a file. The modes are: + * + * l - locked + * a - set append permissions + * r - readable + * w - writable + * A - append only (doesn't exist in Bio) + */ +extern Biobuf * +sysopen(char *path, char *mode, ulong perm) +{ + int sysperm; + int sysmode; + int fd; + int docreate; + int append; + int truncate; + Dir *d, nd; + Biobuf *bp; + + /* + * decode the request + */ + sysperm = 0; + sysmode = -1; + docreate = 0; + append = 0; + truncate = 0; + for(; mode && *mode; mode++) + switch(*mode){ + case 'A': + sysmode = OWRITE; + append = 1; + break; + case 'c': + docreate = 1; + break; + case 'l': + sysperm |= DMEXCL; + break; + case 'a': + sysperm |= DMAPPEND; + break; + case 'w': + if(sysmode == -1) + sysmode = OWRITE; + else + sysmode = ORDWR; + break; + case 'r': + if(sysmode == -1) + sysmode = OREAD; + else + sysmode = ORDWR; + break; + case 't': + truncate = 1; + break; + default: + break; + } + switch(sysmode){ + case OREAD: + case OWRITE: + case ORDWR: + break; + default: + if(sysperm&DMAPPEND) + sysmode = OWRITE; + else + sysmode = OREAD; + break; + } + + /* + * create file if we need to + */ + if(truncate) + sysmode |= OTRUNC; + fd = open(path, sysmode); + if(fd < 0){ + d = dirstat(path); + if(d == nil){ + if(docreate == 0) + return 0; + + fd = create(path, sysmode, sysperm|perm); + if(fd < 0) + return 0; + nulldir(&nd); + nd.mode = sysperm|perm; + dirfwstat(fd, &nd); + } else { + free(d); + return 0; + } + } + + bp = (Biobuf*)malloc(sizeof(Biobuf)); + if(bp == 0){ + close(fd); + return 0; + } + memset(bp, 0, sizeof(Biobuf)); + Binit(bp, fd, sysmode&~OTRUNC); + + if(append) + Bseek(bp, 0, 2); + return bp; +} + +/* + * close the file, etc. + */ +int +sysclose(Biobuf *bp) +{ + int rv; + + rv = Bterm(bp); + close(Bfildes(bp)); + free(bp); + return rv; +} + +/* + * create a file + */ +int +syscreate(char *file, int mode, ulong perm) +{ + return create(file, mode, perm); +} + +/* + * make a directory + */ +int +sysmkdir(char *file, ulong perm) +{ + int fd; + + if((fd = create(file, OREAD, DMDIR|perm)) < 0) + return -1; + close(fd); + return 0; +} + +/* + * change the group of a file + */ +int +syschgrp(char *file, char *group) +{ + Dir nd; + + if(group == 0) + return -1; + nulldir(&nd); + nd.gid = group; + return dirwstat(file, &nd); +} + +extern int +sysdirreadall(int fd, Dir **d) +{ + return dirreadall(fd, d); +} + +/* + * read in the system name + */ +extern char * +sysname_read(void) +{ + static char name[128]; + char *cp; + + cp = getenv("site"); + if(cp == 0 || *cp == 0) + cp = alt_sysname_read(); + if(cp == 0 || *cp == 0) + cp = "kremvax"; + strecpy(name, name+sizeof name, cp); + return name; +} +extern char * +alt_sysname_read(void) +{ + static char name[128]; + int n, fd; + + fd = open("/dev/sysname", OREAD); + if(fd < 0) + return 0; + n = read(fd, name, sizeof(name)-1); + close(fd); + if(n <= 0) + return 0; + name[n] = 0; + return name; +} + +/* + * get all names + */ +extern char** +sysnames_read(void) +{ + static char **namev; + Ndbtuple *t, *nt; + Ndb* db; + Ndbs s; + int n; + char *cp; + + if(namev) + return namev; + + /* free(csgetvalue(0, "sys", alt_sysname_read(), "dom", &t)); jpc */ + db = ndbopen(unsharp("#9/ndb/local")); + free(ndbgetvalue(db, &s, "sys", sysname(),"dom", &t)); + /* t = nil; /* jpc */ + /* fprint(2,"csgetvalue called: fixme"); /* jpc */ + + n = 0; + for(nt = t; nt; nt = nt->entry) + if(strcmp(nt->attr, "dom") == 0) + n++; + + namev = (char**)malloc(sizeof(char *)*(n+3)); + + if(namev){ + n = 0; + namev[n++] = strdup(sysname_read()); + cp = alt_sysname_read(); + if(cp) + namev[n++] = strdup(cp); + for(nt = t; nt; nt = nt->entry) + if(strcmp(nt->attr, "dom") == 0) + namev[n++] = strdup(nt->val); + namev[n] = 0; + } + if(t) + ndbfree(t); + + return namev; +} + +/* + * read in the domain name + */ +extern char * +domainname_read(void) +{ + char **namev; + + for(namev = sysnames_read(); *namev; namev++) + if(strchr(*namev, '.')) + return *namev; + return 0; +} + +/* + * return true if the last error message meant file + * did not exist. + */ +extern int +e_nonexistent(void) +{ + rerrstr(err, sizeof(err)); + return strcmp(err, "file does not exist") == 0; +} + +/* + * return true if the last error message meant file + * was locked. + */ +extern int +e_locked(void) +{ + rerrstr(err, sizeof(err)); + return strcmp(err, "open/create -- file is locked") == 0; +} + +/* + * return the length of a file + */ +extern long +sysfilelen(Biobuf *fp) +{ + Dir *d; + long rv; + + d = dirfstat(Bfildes(fp)); + if(d == nil) + return -1; + rv = d->length; + free(d); + return rv; +} + +/* + * remove a file + */ +extern int +sysremove(char *path) +{ + return remove(path); +} + +/* + * rename a file, fails unless both are in the same directory + */ +extern int +sysrename(char *old, char *new) +{ + Dir d; + char *obase; + char *nbase; + + obase = strrchr(old, '/'); + nbase = strrchr(new, '/'); + if(obase){ + if(nbase == 0) + return -1; + if(strncmp(old, new, obase-old) != 0) + return -1; + nbase++; + } else { + if(nbase) + return -1; + nbase = new; + } + nulldir(&d); + d.name = nbase; + return dirwstat(old, &d); +} + +/* + * see if a file exists + */ +extern int +sysexist(char *file) +{ + Dir *d; + + d = dirstat(file); + if(d == nil) + return 0; + free(d); + return 1; +} + +/* + * return nonzero if file is a directory + */ +extern int +sysisdir(char *file) +{ + Dir *d; + int rv; + + d = dirstat(file); + if(d == nil) + return 0; + rv = d->mode & DMDIR; + free(d); + return rv; +} + +/* + * kill a process or process group + */ + +static int +stomp(int pid, char *file) +{ + char name[64]; + int fd; + + snprint(name, sizeof(name), "/proc/%d/%s", pid, file); + fd = open(name, 1); + if(fd < 0) + return -1; + if(write(fd, "die: yankee pig dog\n", sizeof("die: yankee pig dog\n") - 1) <= 0){ + close(fd); + return -1; + } + close(fd); + return 0; + +} + +/* + * kill a process + */ +extern int +syskill(int pid) +{ + return stomp(pid, "note"); + +} + +/* + * kill a process group + */ +extern int +syskillpg(int pid) +{ + return stomp(pid, "notepg"); +} + +extern int +sysdetach(void) +{ + if(rfork(RFENVG|RFNAMEG|RFNOTEG) < 0) { + werrstr("rfork failed"); + return -1; + } + return 0; +} + +/* + * catch a write on a closed pipe + */ +static int *closedflag; +static int +catchpipe(void *a, char *msg) +{ + static char *foo = "sys: write on closed pipe"; + + USED(a); + if(strncmp(msg, foo, strlen(foo)) == 0){ + if(closedflag) + *closedflag = 1; + return 1; + } + return 0; +} +void +pipesig(int *flagp) +{ + closedflag = flagp; + atnotify(catchpipe, 1); +} +void +pipesigoff(void) +{ + atnotify(catchpipe, 0); +} + +void +exit9(int i) +{ + char buf[32]; + + if(i == 0) + exits(0); + snprint(buf, sizeof(buf), "%d", i); + exits(buf); +} + +static int +islikeatty(int fd) +{ + Dir *d; + int rv; + + d = dirfstat(fd); + if(d == nil) + return 0; + rv = strcmp(d->name, "cons") == 0; + free(d); + return rv; +} + +#if 0 +/* jpc */ +static int +islikeatty(int fd) +{ + char buf[64]; + + if(fd2path(fd, buf, sizeof buf) != 0) + return 0; + + /* might be /mnt/term/dev/cons */ + return strlen(buf) >= 9 && strcmp(buf+strlen(buf)-9, "/dev/cons") == 0; +} +#endif + +extern int +holdon(void) +{ + int fd; + + if(!islikeatty(0)) + return -1; + + fd = open("/dev/consctl", OWRITE); + write(fd, "holdon", 6); + + return fd; +} + +extern int +sysopentty(void) +{ + return open("/dev/cons", ORDWR); +} + +extern void +holdoff(int fd) +{ + write(fd, "holdoff", 7); + close(fd); +} + +extern int +sysfiles(void) +{ + return 128; +} + +/* + * expand a path relative to the user's mailbox directory + * + * if the path starts with / or ./, don't change it + * + */ +extern String * +mboxpath(char *path, char *user, String *to, int dot) +{ + if (dot || *path=='/' || strncmp(path, "./", 2) == 0 + || strncmp(path, "../", 3) == 0) { + to = s_append(to, path); + } else { + to = s_append(to, unsharp(MAILROOT)); + to = s_append(to, "/box/"); + to = s_append(to, user); + to = s_append(to, "/"); + to = s_append(to, path); + } + return to; +} + +extern String * +mboxname(char *user, String *to) +{ + return mboxpath("mbox", user, to, 0); +} + +extern String * +deadletter(String *to) /* pass in sender??? */ +{ + char *cp; + + cp = getlog(); + if(cp == 0) + return 0; + return mboxpath("dead.letter", cp, to, 0); +} + +char * +homedir(char *user) +{ + USED(user); + return getenv("home"); +} + +String * +readlock(String *file) +{ + char *cp; + + cp = getlog(); + if(cp == 0) + return 0; + return mboxpath("reading", cp, file, 0); +} + +String * +username(String *from) +{ + int n; + Biobuf *bp; + char *p, *q; + String *s; + + bp = Bopen("/adm/keys.who", OREAD); + if(bp == 0) + bp = Bopen("/adm/netkeys.who", OREAD); + if(bp == 0) + return 0; + + s = 0; + n = strlen(s_to_c(from)); + for(;;) { + p = Brdline(bp, '\n'); + if(p == 0) + break; + p[Blinelen(bp)-1] = 0; + if(strncmp(p, s_to_c(from), n)) + continue; + p += n; + if(*p != ' ' && *p != '\t') /* must be full match */ + continue; + while(*p && (*p == ' ' || *p == '\t')) + p++; + if(*p == 0) + continue; + for(q = p; *q; q++) + if(('0' <= *q && *q <= '9') || *q == '<') + break; + while(q > p && q[-1] != ' ' && q[-1] != '\t') + q--; + while(q > p && (q[-1] == ' ' || q[-1] == '\t')) + q--; + *q = 0; + s = s_new(); + s_append(s, "\""); + s_append(s, p); + s_append(s, "\""); + break; + } + Bterm(bp); + return s; +} + +char * +remoteaddr(int fd, char *dir) +{ + char buf[128], *p; + int n; + + if(dir == 0){ + fprint(2,"remoteaddr: called fd2path: fixme\n"); /* jpc + if(fd2path(fd, buf, sizeof(buf)) != 0) + return ""; */ + + /* parse something of the form /net/tcp/nnnn/data */ + p = strrchr(buf, '/'); + if(p == 0) + return ""; + strncpy(p+1, "remote", sizeof(buf)-(p-buf)-2); + } else + snprint(buf, sizeof buf, "%s/remote", dir); + buf[sizeof(buf)-1] = 0; + + fd = open(buf, OREAD); + if(fd < 0) + return ""; + n = read(fd, buf, sizeof(buf)-1); + close(fd); + if(n > 0){ + buf[n] = 0; + p = strchr(buf, '!'); + if(p) + *p = 0; + return strdup(buf); + } + return ""; +} + +// create a file and +// 1) ensure the modes we asked for +// 2) make gid == uid +static int +docreate(char *file, int perm) +{ + int fd; + Dir ndir; + Dir *d; + + // create the mbox + fd = create(file, OREAD, perm); + if(fd < 0){ + fprint(2, "couldn't create %s\n", file); + return -1; + } + d = dirfstat(fd); + if(d == nil){ + fprint(2, "couldn't stat %s\n", file); + return -1; + } + nulldir(&ndir); + ndir.mode = perm; + ndir.gid = d->uid; + if(dirfwstat(fd, &ndir) < 0) + fprint(2, "couldn't chmod %s: %r\n", file); + close(fd); + return 0; +} + +// create a mailbox +int +creatembox(char *user, char *folder) +{ + char *p; + String *mailfile; + char buf[512]; + Mlock *ml; + + mailfile = s_new(); + if(folder == 0) + mboxname(user, mailfile); + else { + snprint(buf, sizeof(buf), "%s/mbox", folder); + mboxpath(buf, user, mailfile, 0); + } + + // don't destroy existing mailbox + if(access(s_to_c(mailfile), 0) == 0){ + fprint(2, "mailbox already exists\n"); + return -1; + } + fprint(2, "creating new mbox: %s\n", s_to_c(mailfile)); + + // make sure preceding levels exist + for(p = s_to_c(mailfile); p; p++) { + if(*p == '/') /* skip leading or consecutive slashes */ + continue; + p = strchr(p, '/'); + if(p == 0) + break; + *p = 0; + if(access(s_to_c(mailfile), 0) != 0){ + if(docreate(s_to_c(mailfile), DMDIR|0711) < 0) + return -1; + } + *p = '/'; + } + + // create the mbox + if(docreate(s_to_c(mailfile), 0622|DMAPPEND|DMEXCL) < 0) + return -1; + + /* + * create the lock file if it doesn't exist + */ + ml = trylock(s_to_c(mailfile)); + if(ml != nil) + sysunlock(ml); + + return 0; +} diff --git a/src/cmd/upas/common/mail.c b/src/cmd/upas/common/mail.c new file mode 100644 index 00000000..5347c655 --- /dev/null +++ b/src/cmd/upas/common/mail.c @@ -0,0 +1,57 @@ +#include "common.h" + +/* format of REMOTE FROM lines */ +char *REMFROMRE = + "^>?From[ \t]+((\".*\")?[^\" \t]+?(\".*\")?[^\" \t]+?)[ \t]+(.+)[ \t]+remote[ \t]+from[ \t]+(.*)\n$"; +int REMSENDERMATCH = 1; +int REMDATEMATCH = 4; +int REMSYSMATCH = 5; + +/* format of LOCAL FROM lines */ +char *FROMRE = + "^>?From[ \t]+((\".*\")?[^\" \t]+?(\".*\")?[^\" \t]+?)[ \t]+(.+)\n$"; +int SENDERMATCH = 1; +int DATEMATCH = 4; + +/* output a unix style local header */ +int +print_header(Biobuf *fp, char *sender, char *date) +{ + return Bprint(fp, "From %s %s\n", sender, date); +} + +/* output a unix style remote header */ +int +print_remote_header(Biobuf *fp, char *sender, char *date, char *system) +{ + return Bprint(fp, "From %s %s remote from %s\n", sender, date, system); +} + +/* parse a mailbox style header */ +int +parse_header(char *line, String *sender, String *date) +{ + if (!IS_HEADER(line)) + return -1; + line += sizeof("From ") - 1; + s_restart(sender); + while(*line==' '||*line=='\t') + line++; + if(*line == '"'){ + s_putc(sender, *line++); + while(*line && *line != '"') + s_putc(sender, *line++); + s_putc(sender, *line++); + } else { + while(*line && *line != ' ' && *line != '\t') + s_putc(sender, *line++); + } + s_terminate(sender); + s_restart(date); + while(*line==' '||*line=='\t') + line++; + while(*line) + s_putc(date, *line++); + s_terminate(date); + return 0; +} diff --git a/src/cmd/upas/common/makefile b/src/cmd/upas/common/makefile new file mode 100644 index 00000000..c7beae81 --- /dev/null +++ b/src/cmd/upas/common/makefile @@ -0,0 +1,18 @@ +CFLAGS=${UNIX} -g -I. -I../libc -I../common -I/usr/include ${SCFLAGS} +OBJS=mail.o aux.o string.o ${SYSOBJ} +AR=ar +.c.o: ; ${CC} -c ${CFLAGS} $*.c + +common.a: ${OBJS} + ${AR} cr common.a ${OBJS} + -ranlib common.a + +aux.o: aux.h string.h mail.h +string.o: string.h mail.h +mail.o: mail.h +syslog.o: sys.h +mail.h: sys.h + +clean: + -rm -f *.[oO] core a.out *.a *.sL common.a + diff --git a/src/cmd/upas/common/mkfile b/src/cmd/upas/common/mkfile new file mode 100644 index 00000000..8cfaf267 --- /dev/null +++ b/src/cmd/upas/common/mkfile @@ -0,0 +1,20 @@ +<$PLAN9/src/mkhdr + +LIB=libcommon.a + +OFILES=aux.$O\ + become.$O\ + mail.$O\ + process.$O\ + libsys.$O\ + config.$O\ + appendfiletombox.$O\ + +HFILES=common.h\ + sys.h\ + +<$PLAN9/src/mklib + +nuke:V: + mk clean + rm -f libcommon.a diff --git a/src/cmd/upas/common/process.c b/src/cmd/upas/common/process.c new file mode 100644 index 00000000..16b21aef --- /dev/null +++ b/src/cmd/upas/common/process.c @@ -0,0 +1,175 @@ +#include "common.h" + +/* make a stream to a child process */ +extern stream * +instream(void) +{ + stream *rv; + int pfd[2]; + + if ((rv = (stream *)malloc(sizeof(stream))) == 0) + return 0; + memset(rv, 0, sizeof(stream)); + if (pipe(pfd) < 0) + return 0; + if(Binit(&rv->bb, pfd[1], OWRITE) < 0){ + close(pfd[0]); + close(pfd[1]); + return 0; + } + rv->fp = &rv->bb; + rv->fd = pfd[0]; + return rv; +} + +/* make a stream from a child process */ +extern stream * +outstream(void) +{ + stream *rv; + int pfd[2]; + + if ((rv = (stream *)malloc(sizeof(stream))) == 0) + return 0; + memset(rv, 0, sizeof(stream)); + if (pipe(pfd) < 0) + return 0; + if (Binit(&rv->bb, pfd[0], OREAD) < 0){ + close(pfd[0]); + close(pfd[1]); + return 0; + } + rv->fp = &rv->bb; + rv->fd = pfd[1]; + return rv; +} + +extern void +stream_free(stream *sp) +{ + int fd; + + close(sp->fd); + fd = Bfildes(sp->fp); + Bterm(sp->fp); + close(fd); + free((char *)sp); +} + +/* start a new process */ +extern process * +noshell_proc_start(char **av, stream *inp, stream *outp, stream *errp, int newpg, char *who) +{ + process *pp; + int i, n; + + if ((pp = (process *)malloc(sizeof(process))) == 0) { + if (inp != 0) + stream_free(inp); + if (outp != 0) + stream_free(outp); + if (errp != 0) + stream_free(errp); + return 0; + } + pp->std[0] = inp; + pp->std[1] = outp; + pp->std[2] = errp; + switch (pp->pid = fork()) { + case -1: + proc_free(pp); + return 0; + case 0: + if(newpg) + sysdetach(); + for (i=0; i<3; i++) + if (pp->std[i] != 0){ + close(Bfildes(pp->std[i]->fp)); + while(pp->std[i]->fd < 3) + pp->std[i]->fd = dup(pp->std[i]->fd, -1); + } + for (i=0; i<3; i++) + if (pp->std[i] != 0) + dup(pp->std[i]->fd, i); + for (n = sysfiles(); i < n; i++) + close(i); + if(who) { + fprint(2,"process.c: trying to become(%s,%s)\n",av,who); + // jpc become(av, who); + } + exec(av[0], av); + perror("proc_start"); + exits("proc_start"); + default: + for (i=0; i<3; i++) + if (pp->std[i] != 0) { + close(pp->std[i]->fd); + pp->std[i]->fd = -1; + } + return pp; + } +} + +/* start a new process under a shell */ +extern process * +proc_start(char *cmd, stream *inp, stream *outp, stream *errp, int newpg, char *who) +{ + char *av[4]; + + av[0] = unsharp(SHELL); + av[1] = "-c"; + av[2] = cmd; + av[3] = 0; + return noshell_proc_start(av, inp, outp, errp, newpg, who); +} + +/* wait for a process to stop */ +extern int +proc_wait(process *pp) +{ + Waitmsg *status; + char err[Errlen]; + + for(;;){ + status = wait(); + if(status == nil){ + errstr(err, sizeof(err)); + if(strstr(err, "interrupt") == 0) + break; + } + if (status->pid==pp->pid) + break; + } + pp->pid = -1; + if(status == nil) + pp->status = -1; + else + pp->status = status->msg[0]; + pp->waitmsg = status; + return pp->status; +} + +/* free a process */ +extern int +proc_free(process *pp) +{ + int i; + + if(pp->std[1] == pp->std[2]) + pp->std[2] = 0; /* avoid freeing it twice */ + for (i = 0; i < 3; i++) + if (pp->std[i]) + stream_free(pp->std[i]); + if (pp->pid >= 0) + proc_wait(pp); + free(pp->waitmsg); + free((char *)pp); + return 0; +} + +/* kill a process */ +extern int +proc_kill(process *pp) +{ + return syskill(pp->pid); +} diff --git a/src/cmd/upas/common/sys.h b/src/cmd/upas/common/sys.h new file mode 100644 index 00000000..960aebb3 --- /dev/null +++ b/src/cmd/upas/common/sys.h @@ -0,0 +1,85 @@ +/* + * System dependent header files for research + */ + +#include <u.h> +#include <libc.h> +#include <regexp.h> +#include <bio.h> +#include "libString.h" /* jpc String.h -> libString.h */ + +/* + * for the lock routines in libsys.c + */ +typedef struct Mlock Mlock; +struct Mlock { + int fd; + int pid; + String *name; +}; + +/* + * from config.c + */ +extern char *MAILROOT; /* root of mail system */ +extern char *UPASLOG; /* log directory */ +extern char *UPASLIB; /* upas library directory */ +extern char *UPASBIN; /* upas binary directory */ +extern char *UPASTMP; /* temporary directory */ +extern char *SHELL; /* path name of shell */ +extern char *POST; /* path name of post server addresses */ +extern int MBOXMODE; /* default mailbox protection mode */ + +/* + * files in libsys.c + */ +extern char *sysname_read(void); +extern char *alt_sysname_read(void); +extern char *domainname_read(void); +extern char **sysnames_read(void); +extern char *getlog(void); +extern char *thedate(void); +extern Biobuf *sysopen(char*, char*, ulong); +extern int sysopentty(void); +extern int sysclose(Biobuf*); +extern int sysmkdir(char*, ulong); +extern int syschgrp(char*, char*); +extern Mlock *syslock(char *); +extern void sysunlock(Mlock *); +extern void syslockrefresh(Mlock *); +extern int e_nonexistent(void); +extern int e_locked(void); +extern long sysfilelen(Biobuf*); +extern int sysremove(char*); +extern int sysrename(char*, char*); +extern int sysexist(char*); +extern int sysisdir(char*); +extern int syskill(int); +extern int syskillpg(int); +extern int syscreate(char*, int, ulong); +extern Mlock *trylock(char *); +extern void exit9(int); +extern void pipesig(int*); +extern void pipesigoff(void); +extern int holdon(void); +extern void holdoff(int); +extern int syscreatelocked(char*, int, int); +extern int sysopenlocked(char*, int); +extern int sysunlockfile(int); +extern int sysfiles(void); +extern int become(char**, char*); +extern int sysdetach(void); +extern int sysdirreadall(int, Dir**); +extern String *username(String*); +extern char* remoteaddr(int, char*); +extern int creatembox(char*, char*); + +extern String *readlock(String*); +extern char *homedir(char*); +extern String *mboxname(char*, String*); +extern String *deadletter(String*); + +/* + * maximum size for a file path + */ +#define MAXPATHLEN 128 |