6 * number of predefined fd's
10 static char err[Errlen];
21 strcpy(now, ctime(time(0)));
22 cp = strchr(now, '\n');
29 * return the user id of the current user
38 fd = open("/dev/user", 0);
41 if((n=read(fd, user, sizeof(user)-1)) <= 0)
49 * return the lock name (we use one lock per directory)
58 * get the name of the lock file
61 cp = strrchr(path, '/');
63 s_nappend(lp, path, cp - path + 1);
64 s_append(lp, "L.mbox");
70 syscreatelocked(char *path, int mode, int perm)
72 return create(path, mode, DMEXCL|perm);
76 sysopenlocked(char *path, int mode)
78 /* return open(path, OEXCL|mode);/**/
79 return open(path, mode); /* until system call is fixed */
89 * try opening a lock file. If it doesn't exist try creating it.
92 openlockfile(Mlock *l)
99 fd = open(s_to_c(l->name), OREAD);
105 d = dirstat(s_to_c(l->name));
107 /* file doesn't exist */
108 /* try creating it */
109 fd = create(s_to_c(l->name), OREAD, DMEXCL|0666);
112 nd.mode = DMEXCL|0666;
113 if(dirfwstat(fd, &nd) < 0){
114 /* if we can't chmod, don't bother */
115 /* live without the lock but log it */
116 syslog(0, "mail", "lock error: %s: %r", s_to_c(l->name));
117 remove(s_to_c(l->name));
123 /* couldn't create */
124 /* do we have write access to the directory? */
125 p = strrchr(s_to_c(l->name), '/');
128 fd = access(s_to_c(l->name), 2);
131 /* live without the lock but log it */
132 syslog(0, "mail", "lock error: %s: %r", s_to_c(l->name));
138 /* live without the lock but log it */
139 syslog(0, "mail", "lock error: %s: %r", s_to_c(l->name));
146 return 1; /* try again later */
152 * Set a lock for a particular file. The lock is a file in the same directory
153 * and has L. prepended to the name of the last element of the file name.
161 l = mallocz(sizeof(Mlock), 1);
165 l->name = lockname(path);
168 * wait LSECS seconds for it to unlock
170 for(tries = 0; tries < LSECS*2; tries++){
171 switch(openlockfile(l)){
189 * like lock except don't wait
198 l = malloc(sizeof(Mlock));
202 l->name = lockname(path);
203 if(openlockfile(l) != 0){
209 /* fork process to keep lock alive */
210 switch(l->pid = rfork(RFPROC)){
217 if(pread(fd, buf, 1, 0) < 0)
226 syslockrefresh(Mlock *l)
230 pread(l->fd, buf, 1, 0);
244 postnote(PNPROC, l->pid, "time to die");
249 * Open a file. The modes are:
252 * a - set append permissions
255 * A - append only (doesn't exist in Bio)
258 sysopen(char *path, char *mode, ulong perm)
277 for(; mode && *mode; mode++)
324 * create file if we need to
328 fd = open(path, sysmode);
335 fd = create(path, sysmode, sysperm|perm);
339 nd.mode = sysperm|perm;
347 bp = (Biobuf*)malloc(sizeof(Biobuf));
352 memset(bp, 0, sizeof(Biobuf));
353 Binit(bp, fd, sysmode&~OTRUNC);
361 * close the file, etc.
378 syscreate(char *file, int mode, ulong perm)
380 return create(file, mode, perm);
387 sysmkdir(char *file, ulong perm)
391 if((fd = create(file, OREAD, DMDIR|perm)) < 0)
398 * change the group of a file
401 syschgrp(char *file, char *group)
409 return dirwstat(file, &nd);
413 sysdirreadall(int fd, Dir **d)
415 return dirreadall(fd, d);
419 * read in the system name
424 static char name[128];
428 if(cp == 0 || *cp == 0)
429 cp = alt_sysname_read();
430 if(cp == 0 || *cp == 0)
432 strecpy(name, name+sizeof name, cp);
436 alt_sysname_read(void)
438 static char name[128];
441 fd = open("/dev/sysname", OREAD);
444 n = read(fd, name, sizeof(name)-1);
466 free(csgetvalue(0, "sys", alt_sysname_read(), "dom", &t));
469 for(nt = t; nt; nt = nt->entry)
470 if(strcmp(nt->attr, "dom") == 0)
473 namev = (char**)malloc(sizeof(char *)*(n+3));
477 namev[n++] = strdup(sysname_read());
478 cp = alt_sysname_read();
480 namev[n++] = strdup(cp);
481 for(nt = t; nt; nt = nt->entry)
482 if(strcmp(nt->attr, "dom") == 0)
483 namev[n++] = strdup(nt->val);
493 * read in the domain name
496 domainname_read(void)
500 for(namev = sysnames_read(); *namev; namev++)
501 if(strchr(*namev, '.'))
507 * return true if the last error message meant file
513 rerrstr(err, sizeof(err));
514 return strcmp(err, "file does not exist") == 0;
518 * return true if the last error message meant file
524 rerrstr(err, sizeof(err));
525 return strcmp(err, "open/create -- file is locked") == 0;
529 * return the length of a file
532 sysfilelen(Biobuf *fp)
537 d = dirfstat(Bfildes(fp));
549 sysremove(char *path)
555 * rename a file, fails unless both are in the same directory
558 sysrename(char *old, char *new)
564 obase = strrchr(old, '/');
565 nbase = strrchr(new, '/');
569 if(strncmp(old, new, obase-old) != 0)
579 return dirwstat(old, &d);
583 * see if a file exists
598 * return nonzero if file is a directory
609 rv = d->mode & DMDIR;
615 * kill a process or process group
619 stomp(int pid, char *file)
624 snprint(name, sizeof(name), "/proc/%d/%s", pid, file);
628 if(write(fd, "die: yankee pig dog\n", sizeof("die: yankee pig dog\n") - 1) <= 0){
643 return stomp(pid, "note");
648 * kill a process group
653 return stomp(pid, "notepg");
659 if(rfork(RFENVG|RFNAMEG|RFNOTEG) < 0) {
660 werrstr("rfork failed");
667 * catch a write on a closed pipe
669 static int *closedflag;
671 catchpipe(void *a, char *msg)
673 static char *foo = "sys: write on closed pipe";
676 if(strncmp(msg, foo, strlen(foo)) == 0){
687 atnotify(catchpipe, 1);
692 atnotify(catchpipe, 0);
702 snprint(buf, sizeof(buf), "%d", i);
711 if(fd2path(fd, buf, sizeof buf) != 0)
714 /* might be /mnt/term/dev/cons */
715 return strlen(buf) >= 9 && strcmp(buf+strlen(buf)-9, "/dev/cons") == 0;
726 fd = open("/dev/consctl", OWRITE);
727 write(fd, "holdon", 6);
735 return open("/dev/cons", ORDWR);
741 write(fd, "holdoff", 7);
752 * expand a path relative to the user's mailbox directory
754 * if the path starts with / or ./, don't change it
758 mboxpath(char *path, char *user, String *to, int dot)
760 if (dot || *path=='/' || strncmp(path, "./", 2) == 0
761 || strncmp(path, "../", 3) == 0) {
762 to = s_append(to, path);
764 to = s_append(to, MAILROOT);
765 to = s_append(to, "/box/");
766 to = s_append(to, user);
767 to = s_append(to, "/");
768 to = s_append(to, path);
774 mboxname(char *user, String *to)
776 return mboxpath("mbox", user, to, 0);
780 deadletter(String *to) /* pass in sender??? */
787 return mboxpath("dead.letter", cp, to, 0);
794 return getenv("home");
798 readlock(String *file)
805 return mboxpath("reading", cp, file, 0);
809 username(String *from)
816 bp = Bopen("/adm/keys.who", OREAD);
818 bp = Bopen("/adm/netkeys.who", OREAD);
823 n = strlen(s_to_c(from));
825 p = Brdline(bp, '\n');
828 p[Blinelen(bp)-1] = 0;
829 if(strncmp(p, s_to_c(from), n))
832 if(*p != ' ' && *p != '\t') /* must be full match */
834 while(*p && (*p == ' ' || *p == '\t'))
839 if(('0' <= *q && *q <= '9') || *q == '<')
841 while(q > p && q[-1] != ' ' && q[-1] != '\t')
843 while(q > p && (q[-1] == ' ' || q[-1] == '\t'))
857 remoteaddr(int fd, char *dir)
863 if(fd2path(fd, buf, sizeof(buf)) != 0)
866 /* parse something of the form /net/tcp/nnnn/data */
867 p = strrchr(buf, '/');
870 strncpy(p+1, "remote", sizeof(buf)-(p-buf)-2);
872 snprint(buf, sizeof buf, "%s/remote", dir);
873 buf[sizeof(buf)-1] = 0;
875 fd = open(buf, OREAD);
878 n = read(fd, buf, sizeof(buf)-1);
882 p = strchr(buf, '!');
891 // 1) ensure the modes we asked for
892 // 2) make gid == uid
894 docreate(char *file, int perm)
901 fd = create(file, OREAD, perm);
903 fprint(2, "couldn't create %s\n", file);
908 fprint(2, "couldn't stat %s\n", file);
914 if(dirfwstat(fd, &ndir) < 0)
915 fprint(2, "couldn't chmod %s: %r\n", file);
922 creatembox(char *user, char *folder)
931 mboxname(user, mailfile);
933 snprint(buf, sizeof(buf), "%s/mbox", folder);
934 mboxpath(buf, user, mailfile, 0);
937 // don't destroy existing mailbox
938 if(access(s_to_c(mailfile), 0) == 0){
939 fprint(2, "mailbox already exists\n");
942 fprint(2, "creating new mbox: %s\n", s_to_c(mailfile));
944 // make sure preceding levels exist
945 for(p = s_to_c(mailfile); p; p++) {
946 if(*p == '/') /* skip leading or consecutive slashes */
952 if(access(s_to_c(mailfile), 0) != 0){
953 if(docreate(s_to_c(mailfile), DMDIR|0711) < 0)
960 if(docreate(s_to_c(mailfile), 0622|DMAPPEND|DMEXCL) < 0)
964 * create the lock file if it doesn't exist
966 ml = trylock(s_to_c(mailfile));