X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/999bd51d0391db752924eda0b40d594f6044a273..7e678a4a5c94f9003ee0fe0958c977582ac2e24d:/usr/src/cmd/mail.c diff --git a/usr/src/cmd/mail.c b/usr/src/cmd/mail.c index 41bdafaf03..5dce570105 100644 --- a/usr/src/cmd/mail.c +++ b/usr/src/cmd/mail.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,6 +6,7 @@ #include #include #include +#include /*copylet flags */ /*remote mail, add rmtmsg */ @@ -16,6 +18,11 @@ #define LSIZE 256 #define MAXLET 300 /* maximum number of letters */ #define MAILMODE (~0644) /* mode of created mail */ +#define RMAIL "/usr/net/bin/sendberkmail" +#define LOCNAM1 "csvax" +#define LOCNAM2 "ucbvax" +#define LOCNAM3 "vax" +#define LOCNAM4 "v" char line[LSIZE]; char resp[LSIZE]; @@ -26,22 +33,21 @@ struct let { int nlet = 0; char lfil[50]; long iop, time(); +char *getenv(); +char *index(); char lettmp[] = "/tmp/maXXXXX"; char maildir[] = "/usr/spool/mail/"; char mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxx"; char dead[] = "dead.letter"; -char *rmtmsg = " remote from vax135\n"; /*LOCAL*/ -char *thissys = "vax135"; /*LOCAL*/ +char *thissys = sysname; +char *netname = "vax"; char forwmsg[] = " forwarded\n"; -char *curlock; -int lockerror; FILE *tmpf; FILE *malf; char *my_name; char *getlogin(); struct passwd *getpwuid(); int error; -int locked; int changed; int forward; char from[] = "From "; @@ -51,6 +57,7 @@ char *ctime(); int flgf; int flgp; int delflg = 1; +int hseqno; jmp_buf sjbuf; main(argc, argv) @@ -63,7 +70,7 @@ char **argv; mktemp(lettmp); unlink(lettmp); my_name = getlogin(); - if (my_name == NULL) { + if (my_name == NULL || strlen(my_name) == 0) { struct passwd *pwent; pwent = getpwuid(getuid()); if (pwent==NULL) @@ -80,7 +87,7 @@ char **argv; done(); } if (argv[0][0] != 'r' && /* no favors for rmail*/ - (argc == 1 || argv[1][0] == '-')) + (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rh"))) printmail(argc, argv); else sendmail(argc, argv); @@ -95,6 +102,17 @@ int (*f)(); signal(i, f); } +any(c, str) + register int c; + register char *str; +{ + + while (*str) + if (c == *str++) + return(1); + return(0); +} + printmail(argc, argv) char **argv; { @@ -118,6 +136,8 @@ char **argv; } } else if (argv[1][1]=='r') { forward = 1; + } else if (argv[1][1]=='h') { + forward = 1; } else { fprintf(stderr, "mail: unknown option %c\n", argv[1][1]); done(); @@ -201,8 +221,13 @@ char **argv; print = 0; continue; } - if (resp[1] == '\n' || resp[1] == '\0') - cat(resp+1, "mbox", ""); + if (resp[1] == '\n' || resp[1] == '\0') { + p = getenv("HOME"); + if(p != 0) + cat(resp+1, p, "/mbox"); + else + cat(resp+1, "", "mbox"); + } for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) { malf = fopen(lfil, "a"); if (malf == NULL) { @@ -234,7 +259,7 @@ char **argv; continue; } for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) - if (!sendrmt(j, lfil)) /* couldn't send it */ + if (!sendrmt(j, lfil, "/bin/mail")) /* couldn't send it */ flg++; if (flg) print = 0; @@ -332,7 +357,7 @@ copylet(n, f, type) FILE *f; while(k-- > 1 && (ch=fgetc(tmpf))!='\n') if(type!=ZAP) fputc(ch,f); if(type==REMOTE) - fprintf(f, rmtmsg); + fprintf(f, " remote from %s\n", thissys); else if (type==FORWARD) fprintf(f, forwmsg); else if(type==ORDINARY) @@ -357,13 +382,79 @@ register char *lp; sendmail(argc, argv) char **argv; { + char truename[100]; + int first; + register char *cp; + int gaver = 0; + + truename[0] = 0; + line[0] = '\0'; + /* + * When we fall out of this, argv[1] should be first name, + * argc should be number of names + 1. + */ + + while (argc > 1 && *argv[1] == '-') { + cp = *++argv; + argc--; + switch (cp[1]) { + case 'r': + if (argc <= 0) { + usage(); + done(); + } + gaver++; + strcpy(truename, argv[1]); + fgets(line, LSIZE, stdin); + if (strcmpn("From", line, 4) == 0) + line[0] = '\0'; + argv++; + argc--; + break; + + case 'h': + if (argc <= 0) { + usage(); + done(); + } + hseqno = atoi(argv[1]); + argv++; + argc--; + break; + + default: + usage(); + done(); + } + } + if (argc <= 1) { + usage(); + done(); + } + if (gaver == 0) + strcpy(truename, my_name); + /* + if (argc > 4 && strcmp(argv[1], "-r") == 0) { + strcpy(truename, argv[2]); + argc -= 2; + argv += 2; + fgets(line, LSIZE, stdin); + if (strcmpn("From", line, 4) == 0) + line[0] = '\0'; + } else + strcpy(truename, my_name); + */ time(&iop); - fprintf(tmpf, "%s%s %s", from, my_name, ctime(&iop)); + fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop)); iop = ftell(tmpf); flgf = 1; - while (fgets(line, LSIZE, stdin) != NULL) { - if (line[0] == '.' && line[1] == '\n') + for (first = 1;; first = 0) { + if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL) + break; + if (!first && fgets(line, LSIZE, stdin) == NULL) + break; + if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin))) break; if (isfrom(line)) fputs(">", tmpf); @@ -383,7 +474,7 @@ char **argv; return; } while (--argc > 0) - if (!send(0, *++argv)) /* couldn't send to him */ + if (!send(0, *++argv, truename)) error++; if (error) { setuid(getuid()); @@ -400,8 +491,9 @@ char **argv; fclose(tmpf); } -sendrmt(n, name) +sendrmt(n, name, rcmd) char *name; +char *rcmd; { FILE *rmf, *popen(); register char *p; @@ -410,6 +502,16 @@ char *name; int sts; local = 0; + if (index(name, '^')) { + while (p = index(name, '^')) + *p = '!'; + if (strncmp(name, "researc", 7)) { + strcpy(rsys, "research"); + if (*name != '!') + --name; + goto skip; + } + } if (*name=='!') name++; for(p=rsys; *name!='!'; *p++ = *name++) @@ -422,6 +524,7 @@ char *name; fprintf(stdout, "null name\n"); return(0); } +skip: if ((pid = fork()) == -1) { fprintf(stderr, "mail: can't create proc for remote\n"); return(0); @@ -435,7 +538,7 @@ char *name; } setuid(getuid()); if (local) - sprintf(cmd, "mail %s", rsys); + sprintf(cmd, "%s %s", rcmd, rsys); else { if (index(name+1, '!')) sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); @@ -444,24 +547,63 @@ char *name; } if ((rmf=popen(cmd, "w")) == NULL) exit(1); - copylet(n, rmf, local? FORWARD: REMOTE); + copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE); pclose(rmf); exit(0); } -send(n, name) /* send letter n to name */ +/* + * Send mail on the Berkeley network. + * Sorry Bill, sendrmt() is so awful we just gave up. + */ + +sendberkmail(n, name, fromaddr) + char name[]; + char fromaddr[]; +{ + char cmd[200]; + register FILE *cmdf; + + sprintf(cmd, "%s -h %d -f %s -t %s", RMAIL, hseqno, fromaddr, name); + if ((cmdf = popen(cmd, "w")) == NULL) { + perror(RMAIL); + return(0); + } + copylet(n, cmdf, ORDINARY); + pclose(cmdf); + return(9); +} + +usage() +{ + + fprintf(stderr, "Usage: mail [ -f ] people . . .\n"); +} + +send(n, name, fromaddr) int n; char *name; +char *fromaddr; { char file[50]; register char *p; register mask; struct passwd *pw, *getpwnam(); - for(p=name; *p!='!' &&*p!='\0'; p++) + stripfx(LOCNAM1, &name); + stripfx(LOCNAM2, &name); + stripfx(LOCNAM3, &name); + stripfx(LOCNAM4, &name); + if(*name == ':')name++; /* skip colon in to-name */ + for(p=name; *p!=':' &&*p!='\0'; p++); + /* if(*p == ':') return(sendrmt(n, name, RMAIL)); */ + if (*p == ':') + return(sendberkmail(n, name, fromaddr)); + else if (strcmp(name, "msgs") == 0) return(sendrmt(n, "-s", "/usr/ucb/msgs")); + for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++) ; - if (*p == '!') - return(sendrmt(n, name)); + if (*p == '!'|| *p=='^') + return(sendrmt(n, name, 0)); if ((pw = getpwnam(name)) == NULL) { fprintf(stdout, "mail: can't send to %s\n", name); return(0); @@ -491,42 +633,102 @@ delete(i) done(); } -done() -{ - if(!lockerror) - unlock(); - unlink(lettmp); - exit(error+lockerror); -} +/* + * Lock the specified mail file by setting the file mailfile.lock. + * We must, of course, be careful to unlink the lock file by a call + * to unlock before we stop. The algorithm used here is to see if + * the lock exists, and if it does, to check its modify time. If it + * is older than 30 seconds, we assume error and set our own file. + * Otherwise, we wait for 5 seconds and try again. + */ + +char *maillock = ".lock"; /* Lock suffix for mailname */ +char *lockname = "/usr/spool/mail/tmXXXXXX"; +char locktmp[30]; /* Usable lock temporary */ +char curlock[50]; /* Last used name of lock */ +int locked; /* To note that we locked it */ lock(file) char *file; { - struct stat stbuf; + register int f; + struct stat sbuf; + long curtime; + int statfailed; if (locked || flgf) - return; - if (stat(file, &stbuf)<0) - return; - if (stbuf.st_mode&01) { /* user x bit is the lock */ - if (stbuf.st_ctime+60 >= time((long *)0)) { - fprintf(stderr, "%s busy; try again in a minute\n", file); - lockerror++; - done(); + return(0); + strcpy(curlock, file); + strcat(curlock, maillock); + strcpy(locktmp, lockname); + mktemp(locktmp); + unlink(locktmp); + statfailed = 0; + for (;;) { + f = lock1(locktmp, curlock); + if (f == 0) { + locked = 1; + return(0); } + if (stat(curlock, &sbuf) < 0) { + if (statfailed++ > 5) + return(-1); + sleep(5); + continue; + } + statfailed = 0; + time(&curtime); + if (curtime < sbuf.st_ctime + 30) { + sleep(5); + continue; + } + unlink(curlock); } - locked = stbuf.st_mode & ~01; - curlock = file; - chmod(file, stbuf.st_mode|01); } +/* + * Remove the mail lock, and note that we no longer + * have it locked. + */ + unlock() { - if (locked) - chmod(curlock, locked); + + unlink(curlock); locked = 0; } +/* + * Attempt to set the lock by creating the temporary file, + * then doing a link/unlink. If it fails, return -1 else 0 + */ + +lock1(tempfile, name) + char tempfile[], name[]; +{ + register int fd; + + fd = creat(tempfile, 0); + if (fd < 0) + return(-1); + close(fd); + if (link(tempfile, name) < 0) { + unlink(tempfile); + return(-1); + } + unlink(tempfile); + return(0); +} + +done() +{ + if(locked) + unlock(); + unlink(lettmp); + unlink(locktmp); + exit(error); +} + cat(to, from1, from2) char *to, *from1, *from2; { @@ -552,3 +754,21 @@ register char *s, *p; *s = '\0'; return(p); } +/* + stripfx(prefix string, pointer to string) + + takes a ptr to string and compares it to prefix string. + may be called multiple times +*/ +stripfx(pfx, name) + char *pfx; + char **name; +{ + register char *cp = *name; + + while (*pfx && (*cp == *pfx || *cp == toupper(*pfx))) + cp++, pfx++; + if (*cp != ':' || *pfx != 0) + return; + *name = cp; +}