13e12c5d1SDavid du Colombier #include "common.h"
2bd389b36SDavid du Colombier #include <auth.h>
3219b2ee8SDavid du Colombier #include <ndb.h>
43e12c5d1SDavid du Colombier
53e12c5d1SDavid du Colombier /*
63e12c5d1SDavid du Colombier * number of predefined fd's
73e12c5d1SDavid du Colombier */
83e12c5d1SDavid du Colombier int nsysfile=3;
93e12c5d1SDavid du Colombier
109a747e4fSDavid du Colombier static char err[Errlen];
113e12c5d1SDavid du Colombier
123e12c5d1SDavid du Colombier /*
133e12c5d1SDavid du Colombier * return the date
143e12c5d1SDavid du Colombier */
153e12c5d1SDavid du Colombier extern char *
thedate(void)163e12c5d1SDavid du Colombier thedate(void)
173e12c5d1SDavid du Colombier {
183e12c5d1SDavid du Colombier static char now[64];
193e12c5d1SDavid du Colombier char *cp;
203e12c5d1SDavid du Colombier
213e12c5d1SDavid du Colombier strcpy(now, ctime(time(0)));
223e12c5d1SDavid du Colombier cp = strchr(now, '\n');
233e12c5d1SDavid du Colombier if(cp)
243e12c5d1SDavid du Colombier *cp = 0;
253e12c5d1SDavid du Colombier return now;
263e12c5d1SDavid du Colombier }
273e12c5d1SDavid du Colombier
283e12c5d1SDavid du Colombier /*
293e12c5d1SDavid du Colombier * return the user id of the current user
303e12c5d1SDavid du Colombier */
313e12c5d1SDavid du Colombier extern char *
getlog(void)323e12c5d1SDavid du Colombier getlog(void)
333e12c5d1SDavid du Colombier {
343e12c5d1SDavid du Colombier static char user[64];
353e12c5d1SDavid du Colombier int fd;
363e12c5d1SDavid du Colombier int n;
373e12c5d1SDavid du Colombier
383e12c5d1SDavid du Colombier fd = open("/dev/user", 0);
393e12c5d1SDavid du Colombier if(fd < 0)
407dd7cddfSDavid du Colombier return nil;
413e12c5d1SDavid du Colombier if((n=read(fd, user, sizeof(user)-1)) <= 0)
427dd7cddfSDavid du Colombier return nil;
433e12c5d1SDavid du Colombier close(fd);
443e12c5d1SDavid du Colombier user[n] = 0;
453e12c5d1SDavid du Colombier return user;
463e12c5d1SDavid du Colombier }
473e12c5d1SDavid du Colombier
483e12c5d1SDavid du Colombier /*
49ed250ae1SDavid du Colombier * return the lock name (we use one lock per directory)
503e12c5d1SDavid du Colombier */
513e12c5d1SDavid du Colombier static String *
lockname(char * path)523e12c5d1SDavid du Colombier lockname(char *path)
533e12c5d1SDavid du Colombier {
543e12c5d1SDavid du Colombier String *lp;
553e12c5d1SDavid du Colombier char *cp;
563e12c5d1SDavid du Colombier
573e12c5d1SDavid du Colombier /*
583e12c5d1SDavid du Colombier * get the name of the lock file
593e12c5d1SDavid du Colombier */
603e12c5d1SDavid du Colombier lp = s_new();
613e12c5d1SDavid du Colombier cp = strrchr(path, '/');
62ed250ae1SDavid du Colombier if(cp)
63ed250ae1SDavid du Colombier s_nappend(lp, path, cp - path + 1);
64ed250ae1SDavid du Colombier s_append(lp, "L.mbox");
653e12c5d1SDavid du Colombier
663e12c5d1SDavid du Colombier return lp;
673e12c5d1SDavid du Colombier }
683e12c5d1SDavid du Colombier
697dd7cddfSDavid du Colombier int
syscreatelocked(char * path,int mode,int perm)707dd7cddfSDavid du Colombier syscreatelocked(char *path, int mode, int perm)
717dd7cddfSDavid du Colombier {
729a747e4fSDavid du Colombier return create(path, mode, DMEXCL|perm);
737dd7cddfSDavid du Colombier }
747dd7cddfSDavid du Colombier
757dd7cddfSDavid du Colombier int
sysopenlocked(char * path,int mode)767dd7cddfSDavid du Colombier sysopenlocked(char *path, int mode)
777dd7cddfSDavid du Colombier {
787dd7cddfSDavid du Colombier /* return open(path, OEXCL|mode);/**/
797dd7cddfSDavid du Colombier return open(path, mode); /* until system call is fixed */
807dd7cddfSDavid du Colombier }
817dd7cddfSDavid du Colombier
827dd7cddfSDavid du Colombier int
sysunlockfile(int fd)837dd7cddfSDavid du Colombier sysunlockfile(int fd)
847dd7cddfSDavid du Colombier {
857dd7cddfSDavid du Colombier return close(fd);
867dd7cddfSDavid du Colombier }
877dd7cddfSDavid du Colombier
883e12c5d1SDavid du Colombier /*
893e12c5d1SDavid du Colombier * try opening a lock file. If it doesn't exist try creating it.
903e12c5d1SDavid du Colombier */
913e12c5d1SDavid du Colombier static int
openlockfile(Mlock * l)927dd7cddfSDavid du Colombier openlockfile(Mlock *l)
933e12c5d1SDavid du Colombier {
943e12c5d1SDavid du Colombier int fd;
959a747e4fSDavid du Colombier Dir *d;
96d3c05884SDavid du Colombier Dir nd;
977dd7cddfSDavid du Colombier char *p;
983e12c5d1SDavid du Colombier
999a747e4fSDavid du Colombier fd = open(s_to_c(l->name), OREAD);
1007dd7cddfSDavid du Colombier if(fd >= 0){
1017dd7cddfSDavid du Colombier l->fd = fd;
1027dd7cddfSDavid du Colombier return 0;
1037dd7cddfSDavid du Colombier }
1047dd7cddfSDavid du Colombier
1059a747e4fSDavid du Colombier d = dirstat(s_to_c(l->name));
1069a747e4fSDavid du Colombier if(d == nil){
1077dd7cddfSDavid du Colombier /* file doesn't exist */
1087dd7cddfSDavid du Colombier /* try creating it */
1099a747e4fSDavid du Colombier fd = create(s_to_c(l->name), OREAD, DMEXCL|0666);
1103e12c5d1SDavid du Colombier if(fd >= 0){
111d3c05884SDavid du Colombier nulldir(&nd);
112d3c05884SDavid du Colombier nd.mode = DMEXCL|0666;
113ed250ae1SDavid du Colombier if(dirfwstat(fd, &nd) < 0){
114ed250ae1SDavid du Colombier /* if we can't chmod, don't bother */
115ed250ae1SDavid du Colombier /* live without the lock but log it */
116ed250ae1SDavid du Colombier syslog(0, "mail", "lock error: %s: %r", s_to_c(l->name));
117ed250ae1SDavid du Colombier remove(s_to_c(l->name));
118ed250ae1SDavid du Colombier }
1197dd7cddfSDavid du Colombier l->fd = fd;
1207dd7cddfSDavid du Colombier return 0;
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier
1237dd7cddfSDavid du Colombier /* couldn't create */
1247dd7cddfSDavid du Colombier /* do we have write access to the directory? */
1257dd7cddfSDavid du Colombier p = strrchr(s_to_c(l->name), '/');
1267dd7cddfSDavid du Colombier if(p != 0){
1277dd7cddfSDavid du Colombier *p = 0;
1287dd7cddfSDavid du Colombier fd = access(s_to_c(l->name), 2);
1297dd7cddfSDavid du Colombier *p = '/';
130ed250ae1SDavid du Colombier if(fd < 0){
131ed250ae1SDavid du Colombier /* live without the lock but log it */
132ed250ae1SDavid du Colombier syslog(0, "mail", "lock error: %s: %r", s_to_c(l->name));
133ed250ae1SDavid du Colombier return 0;
134ed250ae1SDavid du Colombier }
1357dd7cddfSDavid du Colombier } else {
1367dd7cddfSDavid du Colombier fd = access(".", 2);
137ed250ae1SDavid du Colombier if(fd < 0){
138ed250ae1SDavid du Colombier /* live without the lock but log it */
139ed250ae1SDavid du Colombier syslog(0, "mail", "lock error: %s: %r", s_to_c(l->name));
140ed250ae1SDavid du Colombier return 0;
141ed250ae1SDavid du Colombier }
1423e12c5d1SDavid du Colombier }
1439a747e4fSDavid du Colombier } else
1449a747e4fSDavid du Colombier free(d);
1457dd7cddfSDavid du Colombier
1467dd7cddfSDavid du Colombier return 1; /* try again later */
1473e12c5d1SDavid du Colombier }
1483e12c5d1SDavid du Colombier
1493e12c5d1SDavid du Colombier #define LSECS 5*60
1503e12c5d1SDavid du Colombier
1513e12c5d1SDavid du Colombier /*
1523e12c5d1SDavid du Colombier * Set a lock for a particular file. The lock is a file in the same directory
1533e12c5d1SDavid du Colombier * and has L. prepended to the name of the last element of the file name.
1543e12c5d1SDavid du Colombier */
1557dd7cddfSDavid du Colombier extern Mlock *
syslock(char * path)1567dd7cddfSDavid du Colombier syslock(char *path)
1573e12c5d1SDavid du Colombier {
1587dd7cddfSDavid du Colombier Mlock *l;
1593e12c5d1SDavid du Colombier int tries;
1603e12c5d1SDavid du Colombier
1617dd7cddfSDavid du Colombier l = mallocz(sizeof(Mlock), 1);
1623e12c5d1SDavid du Colombier if(l == 0)
1637dd7cddfSDavid du Colombier return nil;
1647dd7cddfSDavid du Colombier
1657dd7cddfSDavid du Colombier l->name = lockname(path);
1663e12c5d1SDavid du Colombier
1673e12c5d1SDavid du Colombier /*
1683e12c5d1SDavid du Colombier * wait LSECS seconds for it to unlock
1693e12c5d1SDavid du Colombier */
1703e12c5d1SDavid du Colombier for(tries = 0; tries < LSECS*2; tries++){
1717dd7cddfSDavid du Colombier switch(openlockfile(l)){
1727dd7cddfSDavid du Colombier case 0:
1733e12c5d1SDavid du Colombier return l;
1747dd7cddfSDavid du Colombier case 1:
1757dd7cddfSDavid du Colombier sleep(500);
1767dd7cddfSDavid du Colombier break;
1777dd7cddfSDavid du Colombier default:
1787dd7cddfSDavid du Colombier goto noway;
1797dd7cddfSDavid du Colombier }
1803e12c5d1SDavid du Colombier }
1813e12c5d1SDavid du Colombier
1827dd7cddfSDavid du Colombier noway:
1833e12c5d1SDavid du Colombier s_free(l->name);
1843e12c5d1SDavid du Colombier free(l);
1857dd7cddfSDavid du Colombier return nil;
1863e12c5d1SDavid du Colombier }
1873e12c5d1SDavid du Colombier
1883e12c5d1SDavid du Colombier /*
1893e12c5d1SDavid du Colombier * like lock except don't wait
1903e12c5d1SDavid du Colombier */
1917dd7cddfSDavid du Colombier extern Mlock *
trylock(char * path)1923e12c5d1SDavid du Colombier trylock(char *path)
1933e12c5d1SDavid du Colombier {
1947dd7cddfSDavid du Colombier Mlock *l;
1957dd7cddfSDavid du Colombier char buf[1];
1967dd7cddfSDavid du Colombier int fd;
1973e12c5d1SDavid du Colombier
1987dd7cddfSDavid du Colombier l = malloc(sizeof(Mlock));
1993e12c5d1SDavid du Colombier if(l == 0)
2003e12c5d1SDavid du Colombier return 0;
2013e12c5d1SDavid du Colombier
2023e12c5d1SDavid du Colombier l->name = lockname(path);
2037dd7cddfSDavid du Colombier if(openlockfile(l) != 0){
2043e12c5d1SDavid du Colombier s_free(l->name);
2053e12c5d1SDavid du Colombier free(l);
2063e12c5d1SDavid du Colombier return 0;
2073e12c5d1SDavid du Colombier }
2087dd7cddfSDavid du Colombier
2097dd7cddfSDavid du Colombier /* fork process to keep lock alive */
2107dd7cddfSDavid du Colombier switch(l->pid = rfork(RFPROC)){
2117dd7cddfSDavid du Colombier default:
2127dd7cddfSDavid du Colombier break;
2137dd7cddfSDavid du Colombier case 0:
2147dd7cddfSDavid du Colombier fd = l->fd;
2157dd7cddfSDavid du Colombier for(;;){
2167dd7cddfSDavid du Colombier sleep(1000*60);
2179a747e4fSDavid du Colombier if(pread(fd, buf, 1, 0) < 0)
2187dd7cddfSDavid du Colombier break;
2197dd7cddfSDavid du Colombier }
2207dd7cddfSDavid du Colombier _exits(0);
2217dd7cddfSDavid du Colombier }
2223e12c5d1SDavid du Colombier return l;
2233e12c5d1SDavid du Colombier }
2243e12c5d1SDavid du Colombier
2253e12c5d1SDavid du Colombier extern void
syslockrefresh(Mlock * l)2267dd7cddfSDavid du Colombier syslockrefresh(Mlock *l)
2277dd7cddfSDavid du Colombier {
2287dd7cddfSDavid du Colombier char buf[1];
2297dd7cddfSDavid du Colombier
2309a747e4fSDavid du Colombier pread(l->fd, buf, 1, 0);
2317dd7cddfSDavid du Colombier }
2327dd7cddfSDavid du Colombier
2337dd7cddfSDavid du Colombier extern void
sysunlock(Mlock * l)2347dd7cddfSDavid du Colombier sysunlock(Mlock *l)
2353e12c5d1SDavid du Colombier {
2363e12c5d1SDavid du Colombier if(l == 0)
2373e12c5d1SDavid du Colombier return;
2383e12c5d1SDavid du Colombier if(l->name){
2393e12c5d1SDavid du Colombier s_free(l->name);
2403e12c5d1SDavid du Colombier }
2413e12c5d1SDavid du Colombier if(l->fd >= 0)
2423e12c5d1SDavid du Colombier close(l->fd);
2437dd7cddfSDavid du Colombier if(l->pid > 0)
2447dd7cddfSDavid du Colombier postnote(PNPROC, l->pid, "time to die");
2453e12c5d1SDavid du Colombier free(l);
2463e12c5d1SDavid du Colombier }
2473e12c5d1SDavid du Colombier
2483e12c5d1SDavid du Colombier /*
2493e12c5d1SDavid du Colombier * Open a file. The modes are:
2503e12c5d1SDavid du Colombier *
2513e12c5d1SDavid du Colombier * l - locked
2523e12c5d1SDavid du Colombier * a - set append permissions
2533e12c5d1SDavid du Colombier * r - readable
2543e12c5d1SDavid du Colombier * w - writable
2553e12c5d1SDavid du Colombier * A - append only (doesn't exist in Bio)
2563e12c5d1SDavid du Colombier */
2573e12c5d1SDavid du Colombier extern Biobuf *
sysopen(char * path,char * mode,ulong perm)2583e12c5d1SDavid du Colombier sysopen(char *path, char *mode, ulong perm)
2593e12c5d1SDavid du Colombier {
2603e12c5d1SDavid du Colombier int sysperm;
2613e12c5d1SDavid du Colombier int sysmode;
2623e12c5d1SDavid du Colombier int fd;
2633e12c5d1SDavid du Colombier int docreate;
2643e12c5d1SDavid du Colombier int append;
2657dd7cddfSDavid du Colombier int truncate;
266d3c05884SDavid du Colombier Dir *d, nd;
2673e12c5d1SDavid du Colombier Biobuf *bp;
2683e12c5d1SDavid du Colombier
2693e12c5d1SDavid du Colombier /*
2703e12c5d1SDavid du Colombier * decode the request
2713e12c5d1SDavid du Colombier */
2723e12c5d1SDavid du Colombier sysperm = 0;
2733e12c5d1SDavid du Colombier sysmode = -1;
2743e12c5d1SDavid du Colombier docreate = 0;
2753e12c5d1SDavid du Colombier append = 0;
2767dd7cddfSDavid du Colombier truncate = 0;
2773e12c5d1SDavid du Colombier for(; mode && *mode; mode++)
2783e12c5d1SDavid du Colombier switch(*mode){
2793e12c5d1SDavid du Colombier case 'A':
2803e12c5d1SDavid du Colombier sysmode = OWRITE;
2813e12c5d1SDavid du Colombier append = 1;
2823e12c5d1SDavid du Colombier break;
2833e12c5d1SDavid du Colombier case 'c':
2843e12c5d1SDavid du Colombier docreate = 1;
2853e12c5d1SDavid du Colombier break;
2863e12c5d1SDavid du Colombier case 'l':
2879a747e4fSDavid du Colombier sysperm |= DMEXCL;
2883e12c5d1SDavid du Colombier break;
2893e12c5d1SDavid du Colombier case 'a':
2909a747e4fSDavid du Colombier sysperm |= DMAPPEND;
2913e12c5d1SDavid du Colombier break;
2923e12c5d1SDavid du Colombier case 'w':
2933e12c5d1SDavid du Colombier if(sysmode == -1)
2943e12c5d1SDavid du Colombier sysmode = OWRITE;
2953e12c5d1SDavid du Colombier else
2963e12c5d1SDavid du Colombier sysmode = ORDWR;
2973e12c5d1SDavid du Colombier break;
2983e12c5d1SDavid du Colombier case 'r':
2993e12c5d1SDavid du Colombier if(sysmode == -1)
3003e12c5d1SDavid du Colombier sysmode = OREAD;
3013e12c5d1SDavid du Colombier else
3023e12c5d1SDavid du Colombier sysmode = ORDWR;
3033e12c5d1SDavid du Colombier break;
3047dd7cddfSDavid du Colombier case 't':
3057dd7cddfSDavid du Colombier truncate = 1;
3067dd7cddfSDavid du Colombier break;
3073e12c5d1SDavid du Colombier default:
3083e12c5d1SDavid du Colombier break;
3093e12c5d1SDavid du Colombier }
3103e12c5d1SDavid du Colombier switch(sysmode){
3113e12c5d1SDavid du Colombier case OREAD:
3123e12c5d1SDavid du Colombier case OWRITE:
3133e12c5d1SDavid du Colombier case ORDWR:
3143e12c5d1SDavid du Colombier break;
3153e12c5d1SDavid du Colombier default:
3169a747e4fSDavid du Colombier if(sysperm&DMAPPEND)
3173e12c5d1SDavid du Colombier sysmode = OWRITE;
3183e12c5d1SDavid du Colombier else
3193e12c5d1SDavid du Colombier sysmode = OREAD;
3203e12c5d1SDavid du Colombier break;
3213e12c5d1SDavid du Colombier }
3223e12c5d1SDavid du Colombier
3233e12c5d1SDavid du Colombier /*
3243e12c5d1SDavid du Colombier * create file if we need to
3253e12c5d1SDavid du Colombier */
3267dd7cddfSDavid du Colombier if(truncate)
3277dd7cddfSDavid du Colombier sysmode |= OTRUNC;
3283e12c5d1SDavid du Colombier fd = open(path, sysmode);
3293e12c5d1SDavid du Colombier if(fd < 0){
3309a747e4fSDavid du Colombier d = dirstat(path);
3319a747e4fSDavid du Colombier if(d == nil){
3323e12c5d1SDavid du Colombier if(docreate == 0)
3333e12c5d1SDavid du Colombier return 0;
3343e12c5d1SDavid du Colombier
3353e12c5d1SDavid du Colombier fd = create(path, sysmode, sysperm|perm);
3363e12c5d1SDavid du Colombier if(fd < 0)
3373e12c5d1SDavid du Colombier return 0;
338d3c05884SDavid du Colombier nulldir(&nd);
339d3c05884SDavid du Colombier nd.mode = sysperm|perm;
340d3c05884SDavid du Colombier dirfwstat(fd, &nd);
3419a747e4fSDavid du Colombier } else {
3429a747e4fSDavid du Colombier free(d);
3433e12c5d1SDavid du Colombier return 0;
3443e12c5d1SDavid du Colombier }
3459a747e4fSDavid du Colombier }
3463e12c5d1SDavid du Colombier
3473e12c5d1SDavid du Colombier bp = (Biobuf*)malloc(sizeof(Biobuf));
3483e12c5d1SDavid du Colombier if(bp == 0){
3493e12c5d1SDavid du Colombier close(fd);
3503e12c5d1SDavid du Colombier return 0;
3513e12c5d1SDavid du Colombier }
3527dd7cddfSDavid du Colombier memset(bp, 0, sizeof(Biobuf));
3537dd7cddfSDavid du Colombier Binit(bp, fd, sysmode&~OTRUNC);
3543e12c5d1SDavid du Colombier
3553e12c5d1SDavid du Colombier if(append)
3563e12c5d1SDavid du Colombier Bseek(bp, 0, 2);
3573e12c5d1SDavid du Colombier return bp;
3583e12c5d1SDavid du Colombier }
3593e12c5d1SDavid du Colombier
3603e12c5d1SDavid du Colombier /*
3613e12c5d1SDavid du Colombier * close the file, etc.
3623e12c5d1SDavid du Colombier */
3633e12c5d1SDavid du Colombier int
sysclose(Biobuf * bp)3643e12c5d1SDavid du Colombier sysclose(Biobuf *bp)
3653e12c5d1SDavid du Colombier {
3663e12c5d1SDavid du Colombier int rv;
3673e12c5d1SDavid du Colombier
368219b2ee8SDavid du Colombier rv = Bterm(bp);
3693e12c5d1SDavid du Colombier close(Bfildes(bp));
3703e12c5d1SDavid du Colombier free(bp);
3713e12c5d1SDavid du Colombier return rv;
3723e12c5d1SDavid du Colombier }
3733e12c5d1SDavid du Colombier
3743e12c5d1SDavid du Colombier /*
3753e12c5d1SDavid du Colombier * create a file
3763e12c5d1SDavid du Colombier */
3773e12c5d1SDavid du Colombier int
syscreate(char * file,int mode,ulong perm)3787dd7cddfSDavid du Colombier syscreate(char *file, int mode, ulong perm)
3793e12c5d1SDavid du Colombier {
3807dd7cddfSDavid du Colombier return create(file, mode, perm);
3813e12c5d1SDavid du Colombier }
3823e12c5d1SDavid du Colombier
3833e12c5d1SDavid du Colombier /*
3843e12c5d1SDavid du Colombier * make a directory
3853e12c5d1SDavid du Colombier */
3863e12c5d1SDavid du Colombier int
sysmkdir(char * file,ulong perm)3873e12c5d1SDavid du Colombier sysmkdir(char *file, ulong perm)
3883e12c5d1SDavid du Colombier {
3893e12c5d1SDavid du Colombier int fd;
3903e12c5d1SDavid du Colombier
3919a747e4fSDavid du Colombier if((fd = create(file, OREAD, DMDIR|perm)) < 0)
3923e12c5d1SDavid du Colombier return -1;
3933e12c5d1SDavid du Colombier close(fd);
3943e12c5d1SDavid du Colombier return 0;
3953e12c5d1SDavid du Colombier }
3963e12c5d1SDavid du Colombier
3973e12c5d1SDavid du Colombier /*
3983e12c5d1SDavid du Colombier * change the group of a file
3993e12c5d1SDavid du Colombier */
4003e12c5d1SDavid du Colombier int
syschgrp(char * file,char * group)4013e12c5d1SDavid du Colombier syschgrp(char *file, char *group)
4023e12c5d1SDavid du Colombier {
403d3c05884SDavid du Colombier Dir nd;
4043e12c5d1SDavid du Colombier
4057dd7cddfSDavid du Colombier if(group == 0)
4067dd7cddfSDavid du Colombier return -1;
407d3c05884SDavid du Colombier nulldir(&nd);
408d3c05884SDavid du Colombier nd.gid = group;
409d3c05884SDavid du Colombier return dirwstat(file, &nd);
4103e12c5d1SDavid du Colombier }
4113e12c5d1SDavid du Colombier
4127dd7cddfSDavid du Colombier extern int
sysdirreadall(int fd,Dir ** d)4139a747e4fSDavid du Colombier sysdirreadall(int fd, Dir **d)
4147dd7cddfSDavid du Colombier {
4159a747e4fSDavid du Colombier return dirreadall(fd, d);
4167dd7cddfSDavid du Colombier }
4177dd7cddfSDavid du Colombier
4183e12c5d1SDavid du Colombier /*
4193e12c5d1SDavid du Colombier * read in the system name
4203e12c5d1SDavid du Colombier */
4213e12c5d1SDavid du Colombier extern char *
sysname_read(void)4223e12c5d1SDavid du Colombier sysname_read(void)
4233e12c5d1SDavid du Colombier {
4243e12c5d1SDavid du Colombier static char name[128];
4253e12c5d1SDavid du Colombier char *cp;
4263e12c5d1SDavid du Colombier
4273e12c5d1SDavid du Colombier cp = getenv("site");
4287dd7cddfSDavid du Colombier if(cp == 0 || *cp == 0)
429219b2ee8SDavid du Colombier cp = alt_sysname_read();
4307dd7cddfSDavid du Colombier if(cp == 0 || *cp == 0)
4313e12c5d1SDavid du Colombier cp = "kremvax";
432*4d44ba9bSDavid du Colombier strecpy(name, name+sizeof name, cp);
4333e12c5d1SDavid du Colombier return name;
4343e12c5d1SDavid du Colombier }
435219b2ee8SDavid du Colombier extern char *
alt_sysname_read(void)436219b2ee8SDavid du Colombier alt_sysname_read(void)
437219b2ee8SDavid du Colombier {
438219b2ee8SDavid du Colombier static char name[128];
439219b2ee8SDavid du Colombier int n, fd;
440219b2ee8SDavid du Colombier
441219b2ee8SDavid du Colombier fd = open("/dev/sysname", OREAD);
442219b2ee8SDavid du Colombier if(fd < 0)
443219b2ee8SDavid du Colombier return 0;
444219b2ee8SDavid du Colombier n = read(fd, name, sizeof(name)-1);
445219b2ee8SDavid du Colombier close(fd);
446219b2ee8SDavid du Colombier if(n <= 0)
447219b2ee8SDavid du Colombier return 0;
448219b2ee8SDavid du Colombier name[n] = 0;
449219b2ee8SDavid du Colombier return name;
450219b2ee8SDavid du Colombier }
451219b2ee8SDavid du Colombier
452219b2ee8SDavid du Colombier /*
4537dd7cddfSDavid du Colombier * get all names
4547dd7cddfSDavid du Colombier */
4557dd7cddfSDavid du Colombier extern char**
sysnames_read(void)4567dd7cddfSDavid du Colombier sysnames_read(void)
4577dd7cddfSDavid du Colombier {
4587dd7cddfSDavid du Colombier static char **namev;
4597dd7cddfSDavid du Colombier Ndbtuple *t, *nt;
4607dd7cddfSDavid du Colombier int n;
4617dd7cddfSDavid du Colombier char *cp;
4627dd7cddfSDavid du Colombier
4637dd7cddfSDavid du Colombier if(namev)
4647dd7cddfSDavid du Colombier return namev;
4657dd7cddfSDavid du Colombier
46657837e0bSDavid du Colombier free(csgetvalue(0, "sys", alt_sysname_read(), "dom", &t));
46757837e0bSDavid du Colombier
4687dd7cddfSDavid du Colombier n = 0;
4697dd7cddfSDavid du Colombier for(nt = t; nt; nt = nt->entry)
4707dd7cddfSDavid du Colombier if(strcmp(nt->attr, "dom") == 0)
4717dd7cddfSDavid du Colombier n++;
4727dd7cddfSDavid du Colombier
4737dd7cddfSDavid du Colombier namev = (char**)malloc(sizeof(char *)*(n+3));
4747dd7cddfSDavid du Colombier
4757dd7cddfSDavid du Colombier if(namev){
4767dd7cddfSDavid du Colombier n = 0;
4777dd7cddfSDavid du Colombier namev[n++] = strdup(sysname_read());
4787dd7cddfSDavid du Colombier cp = alt_sysname_read();
4797dd7cddfSDavid du Colombier if(cp)
4807dd7cddfSDavid du Colombier namev[n++] = strdup(cp);
4817dd7cddfSDavid du Colombier for(nt = t; nt; nt = nt->entry)
4827dd7cddfSDavid du Colombier if(strcmp(nt->attr, "dom") == 0)
4837dd7cddfSDavid du Colombier namev[n++] = strdup(nt->val);
4847dd7cddfSDavid du Colombier namev[n] = 0;
4857dd7cddfSDavid du Colombier }
4867dd7cddfSDavid du Colombier if(t)
4877dd7cddfSDavid du Colombier ndbfree(t);
4887dd7cddfSDavid du Colombier
4897dd7cddfSDavid du Colombier return namev;
4907dd7cddfSDavid du Colombier }
4917dd7cddfSDavid du Colombier
4927dd7cddfSDavid du Colombier /*
4937dd7cddfSDavid du Colombier * read in the domain name
494219b2ee8SDavid du Colombier */
495219b2ee8SDavid du Colombier extern char *
domainname_read(void)496219b2ee8SDavid du Colombier domainname_read(void)
497219b2ee8SDavid du Colombier {
4987dd7cddfSDavid du Colombier char **namev;
499219b2ee8SDavid du Colombier
5007dd7cddfSDavid du Colombier for(namev = sysnames_read(); *namev; namev++)
5017dd7cddfSDavid du Colombier if(strchr(*namev, '.'))
5027dd7cddfSDavid du Colombier return *namev;
5037dd7cddfSDavid du Colombier return 0;
504219b2ee8SDavid du Colombier }
5053e12c5d1SDavid du Colombier
5063e12c5d1SDavid du Colombier /*
5073e12c5d1SDavid du Colombier * return true if the last error message meant file
5083e12c5d1SDavid du Colombier * did not exist.
5093e12c5d1SDavid du Colombier */
5103e12c5d1SDavid du Colombier extern int
e_nonexistent(void)5117dd7cddfSDavid du Colombier e_nonexistent(void)
5123e12c5d1SDavid du Colombier {
5139a747e4fSDavid du Colombier rerrstr(err, sizeof(err));
5143e12c5d1SDavid du Colombier return strcmp(err, "file does not exist") == 0;
5153e12c5d1SDavid du Colombier }
5163e12c5d1SDavid du Colombier
5173e12c5d1SDavid du Colombier /*
5183e12c5d1SDavid du Colombier * return true if the last error message meant file
5193e12c5d1SDavid du Colombier * was locked.
5203e12c5d1SDavid du Colombier */
5213e12c5d1SDavid du Colombier extern int
e_locked(void)5223e12c5d1SDavid du Colombier e_locked(void)
5233e12c5d1SDavid du Colombier {
5249a747e4fSDavid du Colombier rerrstr(err, sizeof(err));
5253e12c5d1SDavid du Colombier return strcmp(err, "open/create -- file is locked") == 0;
5263e12c5d1SDavid du Colombier }
5273e12c5d1SDavid du Colombier
5283e12c5d1SDavid du Colombier /*
5293e12c5d1SDavid du Colombier * return the length of a file
5303e12c5d1SDavid du Colombier */
5317dd7cddfSDavid du Colombier extern long
sysfilelen(Biobuf * fp)5323e12c5d1SDavid du Colombier sysfilelen(Biobuf *fp)
5333e12c5d1SDavid du Colombier {
5349a747e4fSDavid du Colombier Dir *d;
5359a747e4fSDavid du Colombier long rv;
5363e12c5d1SDavid du Colombier
5379a747e4fSDavid du Colombier d = dirfstat(Bfildes(fp));
5389a747e4fSDavid du Colombier if(d == nil)
5393e12c5d1SDavid du Colombier return -1;
5409a747e4fSDavid du Colombier rv = d->length;
5419a747e4fSDavid du Colombier free(d);
5429a747e4fSDavid du Colombier return rv;
5433e12c5d1SDavid du Colombier }
5443e12c5d1SDavid du Colombier
5453e12c5d1SDavid du Colombier /*
5463e12c5d1SDavid du Colombier * remove a file
5473e12c5d1SDavid du Colombier */
5483e12c5d1SDavid du Colombier extern int
sysremove(char * path)5493e12c5d1SDavid du Colombier sysremove(char *path)
5503e12c5d1SDavid du Colombier {
5513e12c5d1SDavid du Colombier return remove(path);
5523e12c5d1SDavid du Colombier }
5533e12c5d1SDavid du Colombier
5543e12c5d1SDavid du Colombier /*
5553e12c5d1SDavid du Colombier * rename a file, fails unless both are in the same directory
5563e12c5d1SDavid du Colombier */
5573e12c5d1SDavid du Colombier extern int
sysrename(char * old,char * new)5583e12c5d1SDavid du Colombier sysrename(char *old, char *new)
5593e12c5d1SDavid du Colombier {
560d3c05884SDavid du Colombier Dir d;
5613e12c5d1SDavid du Colombier char *obase;
5623e12c5d1SDavid du Colombier char *nbase;
5633e12c5d1SDavid du Colombier
5643e12c5d1SDavid du Colombier obase = strrchr(old, '/');
5653e12c5d1SDavid du Colombier nbase = strrchr(new, '/');
5663e12c5d1SDavid du Colombier if(obase){
5673e12c5d1SDavid du Colombier if(nbase == 0)
5683e12c5d1SDavid du Colombier return -1;
5693e12c5d1SDavid du Colombier if(strncmp(old, new, obase-old) != 0)
5703e12c5d1SDavid du Colombier return -1;
5713e12c5d1SDavid du Colombier nbase++;
5723e12c5d1SDavid du Colombier } else {
5733e12c5d1SDavid du Colombier if(nbase)
5743e12c5d1SDavid du Colombier return -1;
5753e12c5d1SDavid du Colombier nbase = new;
5763e12c5d1SDavid du Colombier }
577d3c05884SDavid du Colombier nulldir(&d);
578d3c05884SDavid du Colombier d.name = nbase;
579d3c05884SDavid du Colombier return dirwstat(old, &d);
5803e12c5d1SDavid du Colombier }
5813e12c5d1SDavid du Colombier
5823e12c5d1SDavid du Colombier /*
5833e12c5d1SDavid du Colombier * see if a file exists
5843e12c5d1SDavid du Colombier */
5853e12c5d1SDavid du Colombier extern int
sysexist(char * file)5863e12c5d1SDavid du Colombier sysexist(char *file)
5873e12c5d1SDavid du Colombier {
5889a747e4fSDavid du Colombier Dir *d;
5893e12c5d1SDavid du Colombier
5909a747e4fSDavid du Colombier d = dirstat(file);
5919a747e4fSDavid du Colombier if(d == nil)
5929a747e4fSDavid du Colombier return 0;
5939a747e4fSDavid du Colombier free(d);
5949a747e4fSDavid du Colombier return 1;
5953e12c5d1SDavid du Colombier }
5963e12c5d1SDavid du Colombier
5973e12c5d1SDavid du Colombier /*
598dc5a79c1SDavid du Colombier * return nonzero if file is a directory
599dc5a79c1SDavid du Colombier */
600dc5a79c1SDavid du Colombier extern int
sysisdir(char * file)601dc5a79c1SDavid du Colombier sysisdir(char *file)
602dc5a79c1SDavid du Colombier {
603dc5a79c1SDavid du Colombier Dir *d;
604dc5a79c1SDavid du Colombier int rv;
605dc5a79c1SDavid du Colombier
606dc5a79c1SDavid du Colombier d = dirstat(file);
607dc5a79c1SDavid du Colombier if(d == nil)
608dc5a79c1SDavid du Colombier return 0;
609dc5a79c1SDavid du Colombier rv = d->mode & DMDIR;
610dc5a79c1SDavid du Colombier free(d);
611dc5a79c1SDavid du Colombier return rv;
612dc5a79c1SDavid du Colombier }
613dc5a79c1SDavid du Colombier
614dc5a79c1SDavid du Colombier /*
6157dd7cddfSDavid du Colombier * kill a process or process group
6163e12c5d1SDavid du Colombier */
6177dd7cddfSDavid du Colombier
6187dd7cddfSDavid du Colombier static int
stomp(int pid,char * file)6197dd7cddfSDavid du Colombier stomp(int pid, char *file)
6203e12c5d1SDavid du Colombier {
6213e12c5d1SDavid du Colombier char name[64];
6223e12c5d1SDavid du Colombier int fd;
6233e12c5d1SDavid du Colombier
6247dd7cddfSDavid du Colombier snprint(name, sizeof(name), "/proc/%d/%s", pid, file);
6253e12c5d1SDavid du Colombier fd = open(name, 1);
6263e12c5d1SDavid du Colombier if(fd < 0)
6273e12c5d1SDavid du Colombier return -1;
6283e12c5d1SDavid du Colombier if(write(fd, "die: yankee pig dog\n", sizeof("die: yankee pig dog\n") - 1) <= 0){
6293e12c5d1SDavid du Colombier close(fd);
6303e12c5d1SDavid du Colombier return -1;
6313e12c5d1SDavid du Colombier }
6323e12c5d1SDavid du Colombier close(fd);
6333e12c5d1SDavid du Colombier return 0;
6343e12c5d1SDavid du Colombier
6353e12c5d1SDavid du Colombier }
6363e12c5d1SDavid du Colombier
6373e12c5d1SDavid du Colombier /*
6387dd7cddfSDavid du Colombier * kill a process
6397dd7cddfSDavid du Colombier */
6407dd7cddfSDavid du Colombier extern int
syskill(int pid)6417dd7cddfSDavid du Colombier syskill(int pid)
6427dd7cddfSDavid du Colombier {
6437dd7cddfSDavid du Colombier return stomp(pid, "note");
6447dd7cddfSDavid du Colombier
6457dd7cddfSDavid du Colombier }
6467dd7cddfSDavid du Colombier
6477dd7cddfSDavid du Colombier /*
6487dd7cddfSDavid du Colombier * kill a process group
6497dd7cddfSDavid du Colombier */
6507dd7cddfSDavid du Colombier extern int
syskillpg(int pid)6517dd7cddfSDavid du Colombier syskillpg(int pid)
6527dd7cddfSDavid du Colombier {
6537dd7cddfSDavid du Colombier return stomp(pid, "notepg");
6547dd7cddfSDavid du Colombier }
6557dd7cddfSDavid du Colombier
6567dd7cddfSDavid du Colombier extern int
sysdetach(void)6577dd7cddfSDavid du Colombier sysdetach(void)
6587dd7cddfSDavid du Colombier {
6597dd7cddfSDavid du Colombier if(rfork(RFENVG|RFNAMEG|RFNOTEG) < 0) {
6607dd7cddfSDavid du Colombier werrstr("rfork failed");
6617dd7cddfSDavid du Colombier return -1;
6627dd7cddfSDavid du Colombier }
6637dd7cddfSDavid du Colombier return 0;
6647dd7cddfSDavid du Colombier }
6657dd7cddfSDavid du Colombier
6667dd7cddfSDavid du Colombier /*
6673e12c5d1SDavid du Colombier * catch a write on a closed pipe
6683e12c5d1SDavid du Colombier */
6693e12c5d1SDavid du Colombier static int *closedflag;
6703e12c5d1SDavid du Colombier static int
catchpipe(void * a,char * msg)6713e12c5d1SDavid du Colombier catchpipe(void *a, char *msg)
6723e12c5d1SDavid du Colombier {
6733e12c5d1SDavid du Colombier static char *foo = "sys: write on closed pipe";
6743e12c5d1SDavid du Colombier
6753e12c5d1SDavid du Colombier USED(a);
6763e12c5d1SDavid du Colombier if(strncmp(msg, foo, strlen(foo)) == 0){
6777dd7cddfSDavid du Colombier if(closedflag)
6783e12c5d1SDavid du Colombier *closedflag = 1;
6793e12c5d1SDavid du Colombier return 1;
6803e12c5d1SDavid du Colombier }
6813e12c5d1SDavid du Colombier return 0;
6823e12c5d1SDavid du Colombier }
6833e12c5d1SDavid du Colombier void
pipesig(int * flagp)6843e12c5d1SDavid du Colombier pipesig(int *flagp)
6853e12c5d1SDavid du Colombier {
6863e12c5d1SDavid du Colombier closedflag = flagp;
6873e12c5d1SDavid du Colombier atnotify(catchpipe, 1);
6883e12c5d1SDavid du Colombier }
6893e12c5d1SDavid du Colombier void
pipesigoff(void)6903e12c5d1SDavid du Colombier pipesigoff(void)
6913e12c5d1SDavid du Colombier {
6923e12c5d1SDavid du Colombier atnotify(catchpipe, 0);
6933e12c5d1SDavid du Colombier }
6943e12c5d1SDavid du Colombier
6953e12c5d1SDavid du Colombier void
exit(int i)6963e12c5d1SDavid du Colombier exit(int i)
6973e12c5d1SDavid du Colombier {
6983e12c5d1SDavid du Colombier char buf[32];
6993e12c5d1SDavid du Colombier
7003e12c5d1SDavid du Colombier if(i == 0)
7013e12c5d1SDavid du Colombier exits(0);
7027dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%d", i);
7033e12c5d1SDavid du Colombier exits(buf);
7043e12c5d1SDavid du Colombier }
7053e12c5d1SDavid du Colombier
7067dd7cddfSDavid du Colombier static int
islikeatty(int fd)707219b2ee8SDavid du Colombier islikeatty(int fd)
708219b2ee8SDavid du Colombier {
7094f281771SDavid du Colombier char buf[64];
710219b2ee8SDavid du Colombier
7114f281771SDavid du Colombier if(fd2path(fd, buf, sizeof buf) != 0)
712219b2ee8SDavid du Colombier return 0;
7134f281771SDavid du Colombier
7144f281771SDavid du Colombier /* might be /mnt/term/dev/cons */
7154f281771SDavid du Colombier return strlen(buf) >= 9 && strcmp(buf+strlen(buf)-9, "/dev/cons") == 0;
716219b2ee8SDavid du Colombier }
717219b2ee8SDavid du Colombier
718219b2ee8SDavid du Colombier extern int
holdon(void)719219b2ee8SDavid du Colombier holdon(void)
720219b2ee8SDavid du Colombier {
721219b2ee8SDavid du Colombier int fd;
722219b2ee8SDavid du Colombier
723219b2ee8SDavid du Colombier if(!islikeatty(0))
724219b2ee8SDavid du Colombier return -1;
725219b2ee8SDavid du Colombier
726219b2ee8SDavid du Colombier fd = open("/dev/consctl", OWRITE);
727219b2ee8SDavid du Colombier write(fd, "holdon", 6);
728219b2ee8SDavid du Colombier
729219b2ee8SDavid du Colombier return fd;
730219b2ee8SDavid du Colombier }
731219b2ee8SDavid du Colombier
7327dd7cddfSDavid du Colombier extern int
sysopentty(void)7337dd7cddfSDavid du Colombier sysopentty(void)
7347dd7cddfSDavid du Colombier {
7357dd7cddfSDavid du Colombier return open("/dev/cons", ORDWR);
7367dd7cddfSDavid du Colombier }
7377dd7cddfSDavid du Colombier
738219b2ee8SDavid du Colombier extern void
holdoff(int fd)739219b2ee8SDavid du Colombier holdoff(int fd)
740219b2ee8SDavid du Colombier {
741219b2ee8SDavid du Colombier write(fd, "holdoff", 7);
742219b2ee8SDavid du Colombier close(fd);
743219b2ee8SDavid du Colombier }
7447dd7cddfSDavid du Colombier
7457dd7cddfSDavid du Colombier extern int
sysfiles(void)7467dd7cddfSDavid du Colombier sysfiles(void)
7477dd7cddfSDavid du Colombier {
7487dd7cddfSDavid du Colombier return 128;
7497dd7cddfSDavid du Colombier }
7507dd7cddfSDavid du Colombier
7517dd7cddfSDavid du Colombier /*
7527dd7cddfSDavid du Colombier * expand a path relative to the user's mailbox directory
7537dd7cddfSDavid du Colombier *
7547dd7cddfSDavid du Colombier * if the path starts with / or ./, don't change it
7557dd7cddfSDavid du Colombier *
7567dd7cddfSDavid du Colombier */
7577dd7cddfSDavid du Colombier extern String *
mboxpath(char * path,char * user,String * to,int dot)7587dd7cddfSDavid du Colombier mboxpath(char *path, char *user, String *to, int dot)
7597dd7cddfSDavid du Colombier {
7607dd7cddfSDavid du Colombier if (dot || *path=='/' || strncmp(path, "./", 2) == 0
7617dd7cddfSDavid du Colombier || strncmp(path, "../", 3) == 0) {
7627dd7cddfSDavid du Colombier to = s_append(to, path);
7637dd7cddfSDavid du Colombier } else {
7647dd7cddfSDavid du Colombier to = s_append(to, MAILROOT);
7657dd7cddfSDavid du Colombier to = s_append(to, "/box/");
7667dd7cddfSDavid du Colombier to = s_append(to, user);
7677dd7cddfSDavid du Colombier to = s_append(to, "/");
7687dd7cddfSDavid du Colombier to = s_append(to, path);
7697dd7cddfSDavid du Colombier }
7707dd7cddfSDavid du Colombier return to;
7717dd7cddfSDavid du Colombier }
7727dd7cddfSDavid du Colombier
7737dd7cddfSDavid du Colombier extern String *
mboxname(char * user,String * to)7747dd7cddfSDavid du Colombier mboxname(char *user, String *to)
7757dd7cddfSDavid du Colombier {
7767dd7cddfSDavid du Colombier return mboxpath("mbox", user, to, 0);
7777dd7cddfSDavid du Colombier }
7787dd7cddfSDavid du Colombier
7797dd7cddfSDavid du Colombier extern String *
deadletter(String * to)7807dd7cddfSDavid du Colombier deadletter(String *to) /* pass in sender??? */
7817dd7cddfSDavid du Colombier {
7827dd7cddfSDavid du Colombier char *cp;
7837dd7cddfSDavid du Colombier
7847dd7cddfSDavid du Colombier cp = getlog();
7857dd7cddfSDavid du Colombier if(cp == 0)
7867dd7cddfSDavid du Colombier return 0;
7877dd7cddfSDavid du Colombier return mboxpath("dead.letter", cp, to, 0);
7887dd7cddfSDavid du Colombier }
7897dd7cddfSDavid du Colombier
7907dd7cddfSDavid du Colombier char *
homedir(char * user)7917dd7cddfSDavid du Colombier homedir(char *user)
7927dd7cddfSDavid du Colombier {
7937dd7cddfSDavid du Colombier USED(user);
7947dd7cddfSDavid du Colombier return getenv("home");
7957dd7cddfSDavid du Colombier }
7967dd7cddfSDavid du Colombier
7977dd7cddfSDavid du Colombier String *
readlock(String * file)7987dd7cddfSDavid du Colombier readlock(String *file)
7997dd7cddfSDavid du Colombier {
8007dd7cddfSDavid du Colombier char *cp;
8017dd7cddfSDavid du Colombier
8027dd7cddfSDavid du Colombier cp = getlog();
8037dd7cddfSDavid du Colombier if(cp == 0)
8047dd7cddfSDavid du Colombier return 0;
8057dd7cddfSDavid du Colombier return mboxpath("reading", cp, file, 0);
8067dd7cddfSDavid du Colombier }
8077dd7cddfSDavid du Colombier
8087dd7cddfSDavid du Colombier String *
username(String * from)8097dd7cddfSDavid du Colombier username(String *from)
8107dd7cddfSDavid du Colombier {
8117dd7cddfSDavid du Colombier int n;
8127dd7cddfSDavid du Colombier Biobuf *bp;
8137dd7cddfSDavid du Colombier char *p, *q;
8147dd7cddfSDavid du Colombier String *s;
8157dd7cddfSDavid du Colombier
8167dd7cddfSDavid du Colombier bp = Bopen("/adm/keys.who", OREAD);
8177dd7cddfSDavid du Colombier if(bp == 0)
8187dd7cddfSDavid du Colombier bp = Bopen("/adm/netkeys.who", OREAD);
8197dd7cddfSDavid du Colombier if(bp == 0)
8207dd7cddfSDavid du Colombier return 0;
8217dd7cddfSDavid du Colombier
8227dd7cddfSDavid du Colombier s = 0;
8237dd7cddfSDavid du Colombier n = strlen(s_to_c(from));
8247dd7cddfSDavid du Colombier for(;;) {
8257dd7cddfSDavid du Colombier p = Brdline(bp, '\n');
8267dd7cddfSDavid du Colombier if(p == 0)
8277dd7cddfSDavid du Colombier break;
8287dd7cddfSDavid du Colombier p[Blinelen(bp)-1] = 0;
8297dd7cddfSDavid du Colombier if(strncmp(p, s_to_c(from), n))
8307dd7cddfSDavid du Colombier continue;
8317dd7cddfSDavid du Colombier p += n;
8327dd7cddfSDavid du Colombier if(*p != ' ' && *p != '\t') /* must be full match */
8337dd7cddfSDavid du Colombier continue;
8347dd7cddfSDavid du Colombier while(*p && (*p == ' ' || *p == '\t'))
8357dd7cddfSDavid du Colombier p++;
8367dd7cddfSDavid du Colombier if(*p == 0)
8377dd7cddfSDavid du Colombier continue;
8387dd7cddfSDavid du Colombier for(q = p; *q; q++)
8397dd7cddfSDavid du Colombier if(('0' <= *q && *q <= '9') || *q == '<')
8407dd7cddfSDavid du Colombier break;
8417dd7cddfSDavid du Colombier while(q > p && q[-1] != ' ' && q[-1] != '\t')
8427dd7cddfSDavid du Colombier q--;
8437dd7cddfSDavid du Colombier while(q > p && (q[-1] == ' ' || q[-1] == '\t'))
8447dd7cddfSDavid du Colombier q--;
8457dd7cddfSDavid du Colombier *q = 0;
8467dd7cddfSDavid du Colombier s = s_new();
8477dd7cddfSDavid du Colombier s_append(s, "\"");
8487dd7cddfSDavid du Colombier s_append(s, p);
8497dd7cddfSDavid du Colombier s_append(s, "\"");
8507dd7cddfSDavid du Colombier break;
8517dd7cddfSDavid du Colombier }
8527dd7cddfSDavid du Colombier Bterm(bp);
8537dd7cddfSDavid du Colombier return s;
8547dd7cddfSDavid du Colombier }
8557dd7cddfSDavid du Colombier
8567dd7cddfSDavid du Colombier char *
remoteaddr(int fd,char * dir)8577dd7cddfSDavid du Colombier remoteaddr(int fd, char *dir)
8587dd7cddfSDavid du Colombier {
8597dd7cddfSDavid du Colombier char buf[128], *p;
8607dd7cddfSDavid du Colombier int n;
8617dd7cddfSDavid du Colombier
8627dd7cddfSDavid du Colombier if(dir == 0){
86380ee5cbfSDavid du Colombier if(fd2path(fd, buf, sizeof(buf)) != 0)
86480ee5cbfSDavid du Colombier return "";
86580ee5cbfSDavid du Colombier
8667dd7cddfSDavid du Colombier /* parse something of the form /net/tcp/nnnn/data */
8677dd7cddfSDavid du Colombier p = strrchr(buf, '/');
8687dd7cddfSDavid du Colombier if(p == 0)
8697dd7cddfSDavid du Colombier return "";
8707dd7cddfSDavid du Colombier strncpy(p+1, "remote", sizeof(buf)-(p-buf)-2);
8717dd7cddfSDavid du Colombier } else
8727dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/remote", dir);
8737dd7cddfSDavid du Colombier buf[sizeof(buf)-1] = 0;
87480ee5cbfSDavid du Colombier
8757dd7cddfSDavid du Colombier fd = open(buf, OREAD);
8767dd7cddfSDavid du Colombier if(fd < 0)
8777dd7cddfSDavid du Colombier return "";
87880ee5cbfSDavid du Colombier n = read(fd, buf, sizeof(buf)-1);
8797dd7cddfSDavid du Colombier close(fd);
8807dd7cddfSDavid du Colombier if(n > 0){
8817dd7cddfSDavid du Colombier buf[n] = 0;
8827dd7cddfSDavid du Colombier p = strchr(buf, '!');
8837dd7cddfSDavid du Colombier if(p)
8847dd7cddfSDavid du Colombier *p = 0;
8857dd7cddfSDavid du Colombier return strdup(buf);
8867dd7cddfSDavid du Colombier }
8877dd7cddfSDavid du Colombier return "";
8887dd7cddfSDavid du Colombier }
8897dd7cddfSDavid du Colombier
89040ef9009SDavid du Colombier // create a file and
89140ef9009SDavid du Colombier // 1) ensure the modes we asked for
89240ef9009SDavid du Colombier // 2) make gid == uid
89340ef9009SDavid du Colombier static int
docreate(char * file,int perm)89440ef9009SDavid du Colombier docreate(char *file, int perm)
89540ef9009SDavid du Colombier {
89640ef9009SDavid du Colombier int fd;
89740ef9009SDavid du Colombier Dir ndir;
89840ef9009SDavid du Colombier Dir *d;
89940ef9009SDavid du Colombier
90040ef9009SDavid du Colombier // create the mbox
90140ef9009SDavid du Colombier fd = create(file, OREAD, perm);
90240ef9009SDavid du Colombier if(fd < 0){
90340ef9009SDavid du Colombier fprint(2, "couldn't create %s\n", file);
90440ef9009SDavid du Colombier return -1;
90540ef9009SDavid du Colombier }
90640ef9009SDavid du Colombier d = dirfstat(fd);
90740ef9009SDavid du Colombier if(d == nil){
90840ef9009SDavid du Colombier fprint(2, "couldn't stat %s\n", file);
90940ef9009SDavid du Colombier return -1;
91040ef9009SDavid du Colombier }
91140ef9009SDavid du Colombier nulldir(&ndir);
91240ef9009SDavid du Colombier ndir.mode = perm;
91340ef9009SDavid du Colombier ndir.gid = d->uid;
91440ef9009SDavid du Colombier if(dirfwstat(fd, &ndir) < 0)
91540ef9009SDavid du Colombier fprint(2, "couldn't chmod %s: %r\n", file);
91640ef9009SDavid du Colombier close(fd);
91740ef9009SDavid du Colombier return 0;
91840ef9009SDavid du Colombier }
91940ef9009SDavid du Colombier
9209a747e4fSDavid du Colombier // create a mailbox
9217dd7cddfSDavid du Colombier int
creatembox(char * user,char * folder)9229a747e4fSDavid du Colombier creatembox(char *user, char *folder)
9237dd7cddfSDavid du Colombier {
9249a747e4fSDavid du Colombier char *p;
9259a747e4fSDavid du Colombier String *mailfile;
9269a747e4fSDavid du Colombier char buf[512];
9279a747e4fSDavid du Colombier Mlock *ml;
9287dd7cddfSDavid du Colombier
9299a747e4fSDavid du Colombier mailfile = s_new();
9309a747e4fSDavid du Colombier if(folder == 0)
9319a747e4fSDavid du Colombier mboxname(user, mailfile);
9329a747e4fSDavid du Colombier else {
9339a747e4fSDavid du Colombier snprint(buf, sizeof(buf), "%s/mbox", folder);
9349a747e4fSDavid du Colombier mboxpath(buf, user, mailfile, 0);
9359a747e4fSDavid du Colombier }
9369a747e4fSDavid du Colombier
9379a747e4fSDavid du Colombier // don't destroy existing mailbox
9389a747e4fSDavid du Colombier if(access(s_to_c(mailfile), 0) == 0){
9399a747e4fSDavid du Colombier fprint(2, "mailbox already exists\n");
9409a747e4fSDavid du Colombier return -1;
9419a747e4fSDavid du Colombier }
9429a747e4fSDavid du Colombier fprint(2, "creating new mbox: %s\n", s_to_c(mailfile));
9439a747e4fSDavid du Colombier
9449a747e4fSDavid du Colombier // make sure preceding levels exist
9459a747e4fSDavid du Colombier for(p = s_to_c(mailfile); p; p++) {
9469a747e4fSDavid du Colombier if(*p == '/') /* skip leading or consecutive slashes */
9479a747e4fSDavid du Colombier continue;
9489a747e4fSDavid du Colombier p = strchr(p, '/');
9499a747e4fSDavid du Colombier if(p == 0)
9509a747e4fSDavid du Colombier break;
9519a747e4fSDavid du Colombier *p = 0;
9529a747e4fSDavid du Colombier if(access(s_to_c(mailfile), 0) != 0){
95340ef9009SDavid du Colombier if(docreate(s_to_c(mailfile), DMDIR|0711) < 0)
9549a747e4fSDavid du Colombier return -1;
9559a747e4fSDavid du Colombier }
9569a747e4fSDavid du Colombier *p = '/';
9579a747e4fSDavid du Colombier }
9589a747e4fSDavid du Colombier
9599a747e4fSDavid du Colombier // create the mbox
96040ef9009SDavid du Colombier if(docreate(s_to_c(mailfile), 0622|DMAPPEND|DMEXCL) < 0)
9619a747e4fSDavid du Colombier return -1;
9629a747e4fSDavid du Colombier
9639a747e4fSDavid du Colombier /*
9649a747e4fSDavid du Colombier * create the lock file if it doesn't exist
9659a747e4fSDavid du Colombier */
9669a747e4fSDavid du Colombier ml = trylock(s_to_c(mailfile));
9679a747e4fSDavid du Colombier if(ml != nil)
9689a747e4fSDavid du Colombier sysunlock(ml);
9699a747e4fSDavid du Colombier
9709a747e4fSDavid du Colombier return 0;
9717dd7cddfSDavid du Colombier }
972