114465Ssam #ifndef lint 2*33608Sbostic static char sccsid[] = "@(#)mail.local.c 4.33 (Berkeley) 02/27/88"; 314465Ssam #endif 414465Ssam 529763Skarels #include <sys/param.h> 616731Sralph #include <sys/stat.h> 716731Sralph #include <sys/file.h> 816731Sralph 9579Sroot #include <ctype.h> 10579Sroot #include <stdio.h> 11579Sroot #include <pwd.h> 12579Sroot #include <utmp.h> 13579Sroot #include <signal.h> 14579Sroot #include <setjmp.h> 15579Sroot #include <sysexits.h> 16579Sroot 179978Seric #define SENDMAIL "/usr/lib/sendmail" 18579Sroot 1916731Sralph /* copylet flags */ 2016731Sralph #define REMOTE 1 /* remote mail, add rmtmsg */ 2116731Sralph #define ORDINARY 2 2216731Sralph #define ZAP 3 /* zap header and trailing empty line */ 2316731Sralph #define FORWARD 4 24579Sroot 2516731Sralph #define LSIZE 256 2616731Sralph #define MAXLET 300 /* maximum number of letters */ 2716731Sralph #define MAILMODE 0600 /* mode of created mail */ 28579Sroot 29579Sroot char line[LSIZE]; 30579Sroot char resp[LSIZE]; 31579Sroot struct let { 32579Sroot long adr; 33579Sroot char change; 34579Sroot } let[MAXLET]; 35579Sroot int nlet = 0; 36579Sroot char lfil[50]; 37579Sroot long iop, time(); 38579Sroot char *getenv(); 39579Sroot char *index(); 40579Sroot char lettmp[] = "/tmp/maXXXXX"; 41579Sroot char maildir[] = "/usr/spool/mail/"; 42579Sroot char mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; 43579Sroot char dead[] = "dead.letter"; 44579Sroot char forwmsg[] = " forwarded\n"; 45579Sroot FILE *tmpf; 46579Sroot FILE *malf; 4729763Skarels char my_name[60]; 48579Sroot char *getlogin(); 49579Sroot int error; 50579Sroot int changed; 51579Sroot int forward; 52579Sroot char from[] = "From "; 53579Sroot long ftell(); 5416731Sralph int delex(); 55579Sroot char *ctime(); 56579Sroot int flgf; 57579Sroot int flgp; 58579Sroot int delflg = 1; 59579Sroot int hseqno; 60579Sroot jmp_buf sjbuf; 61579Sroot int rmail; 62579Sroot 63579Sroot main(argc, argv) 64579Sroot char **argv; 65579Sroot { 6633341Sbostic register int i; 6729763Skarels char *name; 6819868Smiriam struct passwd *pwent; 69579Sroot 7033341Sbostic if (!(name = getlogin()) || !*name || !(pwent = getpwnam(name)) || 7133341Sbostic getuid() != pwent->pw_uid) 72579Sroot pwent = getpwuid(getuid()); 7333341Sbostic strncpy(my_name, pwent ? pwent->pw_name : "???", sizeof(my_name)-1); 7416731Sralph if (setjmp(sjbuf)) 7516731Sralph done(); 7614912Sralph for (i=SIGHUP; i<=SIGTERM; i++) 7716731Sralph setsig(i, delex); 7817533Sralph i = mkstemp(lettmp); 7917533Sralph tmpf = fdopen(i, "r+w"); 8017533Sralph if (i < 0 || tmpf == NULL) 8116731Sralph panic("mail: %s: cannot open for writing", lettmp); 8216731Sralph /* 8316731Sralph * This protects against others reading mail from temp file and 8416731Sralph * if we exit, the file will be deleted already. 8516731Sralph */ 8616731Sralph unlink(lettmp); 87579Sroot if (argv[0][0] == 'r') 88579Sroot rmail++; 89579Sroot if (argv[0][0] != 'r' && /* no favors for rmail*/ 90579Sroot (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd"))) 91579Sroot printmail(argc, argv); 92579Sroot else 936015Swnj bulkmail(argc, argv); 94579Sroot done(); 95579Sroot } 96579Sroot 97579Sroot setsig(i, f) 98579Sroot int i; 99579Sroot int (*f)(); 100579Sroot { 10116731Sralph if (signal(i, SIG_IGN) != SIG_IGN) 102579Sroot signal(i, f); 103579Sroot } 104579Sroot 105579Sroot any(c, str) 106579Sroot register int c; 107579Sroot register char *str; 108579Sroot { 109579Sroot 110579Sroot while (*str) 111579Sroot if (c == *str++) 112579Sroot return(1); 113579Sroot return(0); 114579Sroot } 115579Sroot 116579Sroot printmail(argc, argv) 11716731Sralph char **argv; 118579Sroot { 119579Sroot int flg, i, j, print; 120579Sroot char *p, *getarg(); 121579Sroot struct stat statb; 122579Sroot 123579Sroot setuid(getuid()); 124579Sroot cat(mailfile, maildir, my_name); 12516731Sralph #ifdef notdef 126579Sroot if (stat(mailfile, &statb) >= 0 127579Sroot && (statb.st_mode & S_IFMT) == S_IFDIR) { 128579Sroot strcat(mailfile, "/"); 129579Sroot strcat(mailfile, my_name); 130579Sroot } 13116731Sralph #endif 13216731Sralph for (; argc > 1; argv++, argc--) { 13316731Sralph if (argv[1][0] != '-') 13416731Sralph break; 13516731Sralph switch (argv[1][1]) { 13616731Sralph 13716731Sralph case 'p': 13816731Sralph flgp++; 13916731Sralph /* fall thru... */ 14016731Sralph case 'q': 14116731Sralph delflg = 0; 14216731Sralph break; 14316731Sralph 14416731Sralph case 'f': 14516731Sralph if (argc >= 3) { 14616731Sralph strcpy(mailfile, argv[2]); 14716731Sralph argv++, argc--; 148579Sroot } 149579Sroot break; 15016731Sralph 15116731Sralph case 'b': 15216731Sralph forward = 1; 15316731Sralph break; 15416731Sralph 15516731Sralph default: 15616731Sralph panic("unknown option %c", argv[1][1]); 15716731Sralph /*NOTREACHED*/ 15816731Sralph } 159579Sroot } 160579Sroot malf = fopen(mailfile, "r"); 161579Sroot if (malf == NULL) { 16216731Sralph printf("No mail.\n"); 163579Sroot return; 164579Sroot } 16516731Sralph flock(fileno(malf), LOCK_SH); 166579Sroot copymt(malf, tmpf); 16716731Sralph fclose(malf); /* implicit unlock */ 16833607Sbostic fseek(tmpf, 0L, L_SET); 169579Sroot 170579Sroot changed = 0; 171579Sroot print = 1; 172579Sroot for (i = 0; i < nlet; ) { 173579Sroot j = forward ? i : nlet - i - 1; 17416731Sralph if (setjmp(sjbuf)) { 17516731Sralph print = 0; 176579Sroot } else { 177579Sroot if (print) 178579Sroot copylet(j, stdout, ORDINARY); 179579Sroot print = 1; 180579Sroot } 181579Sroot if (flgp) { 182579Sroot i++; 183579Sroot continue; 184579Sroot } 185579Sroot setjmp(sjbuf); 18616731Sralph fputs("? ", stdout); 187579Sroot fflush(stdout); 188579Sroot if (fgets(resp, LSIZE, stdin) == NULL) 189579Sroot break; 190579Sroot switch (resp[0]) { 191579Sroot 192579Sroot default: 19316731Sralph printf("usage\n"); 194579Sroot case '?': 195579Sroot print = 0; 19616731Sralph printf("q\tquit\n"); 19716731Sralph printf("x\texit without changing mail\n"); 19816731Sralph printf("p\tprint\n"); 19916731Sralph printf("s[file]\tsave (default mbox)\n"); 20016731Sralph printf("w[file]\tsame without header\n"); 20116731Sralph printf("-\tprint previous\n"); 20216731Sralph printf("d\tdelete\n"); 20316731Sralph printf("+\tnext (no delete)\n"); 20416731Sralph printf("m user\tmail to user\n"); 20516731Sralph printf("! cmd\texecute cmd\n"); 206579Sroot break; 207579Sroot 208579Sroot case '+': 209579Sroot case 'n': 210579Sroot case '\n': 211579Sroot i++; 212579Sroot break; 213579Sroot case 'x': 214579Sroot changed = 0; 215579Sroot case 'q': 216579Sroot goto donep; 217579Sroot case 'p': 218579Sroot break; 219579Sroot case '^': 220579Sroot case '-': 221579Sroot if (--i < 0) 222579Sroot i = 0; 223579Sroot break; 224579Sroot case 'y': 225579Sroot case 'w': 226579Sroot case 's': 227579Sroot flg = 0; 228579Sroot if (resp[1] != '\n' && resp[1] != ' ') { 229579Sroot printf("illegal\n"); 230579Sroot flg++; 231579Sroot print = 0; 232579Sroot continue; 233579Sroot } 234579Sroot if (resp[1] == '\n' || resp[1] == '\0') { 235579Sroot p = getenv("HOME"); 23616731Sralph if (p != 0) 237579Sroot cat(resp+1, p, "/mbox"); 238579Sroot else 239579Sroot cat(resp+1, "", "mbox"); 240579Sroot } 241579Sroot for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) { 242579Sroot malf = fopen(lfil, "a"); 243579Sroot if (malf == NULL) { 24416731Sralph printf("mail: %s: cannot append\n", 24516731Sralph lfil); 246579Sroot flg++; 247579Sroot continue; 248579Sroot } 249579Sroot copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY); 250579Sroot fclose(malf); 251579Sroot } 252579Sroot if (flg) 253579Sroot print = 0; 254579Sroot else { 255579Sroot let[j].change = 'd'; 256579Sroot changed++; 257579Sroot i++; 258579Sroot } 259579Sroot break; 260579Sroot case 'm': 261579Sroot flg = 0; 262579Sroot if (resp[1] == '\n' || resp[1] == '\0') { 263579Sroot i++; 264579Sroot continue; 265579Sroot } 266579Sroot if (resp[1] != ' ') { 267579Sroot printf("invalid command\n"); 268579Sroot flg++; 269579Sroot print = 0; 270579Sroot continue; 271579Sroot } 272579Sroot for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) 27317019Sralph if (!sendmail(j, lfil, my_name)) 274579Sroot flg++; 275579Sroot if (flg) 276579Sroot print = 0; 277579Sroot else { 278579Sroot let[j].change = 'd'; 279579Sroot changed++; 280579Sroot i++; 281579Sroot } 282579Sroot break; 283579Sroot case '!': 284579Sroot system(resp+1); 285579Sroot printf("!\n"); 286579Sroot print = 0; 287579Sroot break; 288579Sroot case 'd': 289579Sroot let[j].change = 'd'; 290579Sroot changed++; 291579Sroot i++; 292579Sroot if (resp[1] == 'q') 293579Sroot goto donep; 294579Sroot break; 295579Sroot } 296579Sroot } 297579Sroot donep: 298579Sroot if (changed) 299579Sroot copyback(); 300579Sroot } 301579Sroot 30216731Sralph /* copy temp or whatever back to /usr/spool/mail */ 30316731Sralph copyback() 304579Sroot { 30533607Sbostic register int i, c; 30633607Sbostic long oldmask; 30733607Sbostic int fd, new = 0; 308579Sroot struct stat stbuf; 309579Sroot 31033607Sbostic oldmask = sigblock(sigmask(SIGINT)|sigmask(SIGHUP)|sigmask(SIGQUIT)); 31116731Sralph fd = open(mailfile, O_RDWR | O_CREAT, MAILMODE); 31216731Sralph if (fd >= 0) { 31316731Sralph flock(fd, LOCK_EX); 31416731Sralph malf = fdopen(fd, "r+w"); 31516731Sralph } 31616731Sralph if (fd < 0 || malf == NULL) 31716731Sralph panic("can't rewrite %s", lfil); 31816731Sralph fstat(fd, &stbuf); 319579Sroot if (stbuf.st_size != let[nlet].adr) { /* new mail has arrived */ 32016731Sralph fseek(malf, let[nlet].adr, L_SET); 32116731Sralph fseek(tmpf, let[nlet].adr, L_SET); 32216731Sralph while ((c = getc(malf)) != EOF) 32316731Sralph putc(c, tmpf); 324579Sroot let[++nlet].adr = stbuf.st_size; 325579Sroot new = 1; 32633607Sbostic fseek(malf, 0L, L_SET); 327579Sroot } 32833607Sbostic ftruncate(fd, 0L); 329579Sroot for (i = 0; i < nlet; i++) 33016731Sralph if (let[i].change != 'd') 331579Sroot copylet(i, malf, ORDINARY); 33216731Sralph fclose(malf); /* implict unlock */ 333579Sroot if (new) 33416731Sralph printf("New mail has arrived.\n"); 33516731Sralph sigsetmask(oldmask); 336579Sroot } 337579Sroot 33816731Sralph /* copy mail (f1) to temp (f2) */ 33916731Sralph copymt(f1, f2) 34016731Sralph FILE *f1, *f2; 341579Sroot { 342579Sroot long nextadr; 343579Sroot 344579Sroot nlet = nextadr = 0; 345579Sroot let[0].adr = 0; 346579Sroot while (fgets(line, LSIZE, f1) != NULL) { 347579Sroot if (isfrom(line)) 348579Sroot let[nlet++].adr = nextadr; 349579Sroot nextadr += strlen(line); 350579Sroot fputs(line, f2); 351579Sroot } 352579Sroot let[nlet].adr = nextadr; /* last plus 1 */ 353579Sroot } 354579Sroot 35511893Seric copylet(n, f, type) 35611893Seric FILE *f; 35711893Seric { 35811893Seric int ch; 35911893Seric long k; 36029763Skarels char hostname[MAXHOSTNAMELEN]; 36111893Seric 36216731Sralph fseek(tmpf, let[n].adr, L_SET); 363579Sroot k = let[n+1].adr - let[n].adr; 36416731Sralph while (k-- > 1 && (ch = getc(tmpf)) != '\n') 36516731Sralph if (type != ZAP) 36616731Sralph putc(ch, f); 36716731Sralph switch (type) { 36816731Sralph 36916731Sralph case REMOTE: 3706199Sroot gethostname(hostname, sizeof (hostname)); 3716199Sroot fprintf(f, " remote from %s\n", hostname); 37216731Sralph break; 37316731Sralph 37416731Sralph case FORWARD: 375579Sroot fprintf(f, forwmsg); 37616731Sralph break; 37716731Sralph 37816731Sralph case ORDINARY: 37916731Sralph putc(ch, f); 38016731Sralph break; 38116731Sralph 38217019Sralph case ZAP: 38317019Sralph break; 38417019Sralph 38516731Sralph default: 38616731Sralph panic("Bad letter type %d to copylet.", type); 38716731Sralph } 38816731Sralph while (k-- > 1) { 38916731Sralph ch = getc(tmpf); 39016731Sralph putc(ch, f); 39116731Sralph } 39216731Sralph if (type != ZAP || ch != '\n') 39316731Sralph putc(getc(tmpf), f); 394579Sroot } 395579Sroot 396579Sroot isfrom(lp) 397579Sroot register char *lp; 398579Sroot { 399579Sroot register char *p; 400579Sroot 401579Sroot for (p = from; *p; ) 402579Sroot if (*lp++ != *p++) 403579Sroot return(0); 404579Sroot return(1); 405579Sroot } 406579Sroot 4076015Swnj bulkmail(argc, argv) 408579Sroot char **argv; 409579Sroot { 41029763Skarels char *truename; 411579Sroot int first; 412579Sroot register char *cp; 413579Sroot char *newargv[1000]; 414579Sroot register char **ap; 415579Sroot register char **vp; 416579Sroot int dflag; 417579Sroot 418579Sroot dflag = 0; 41929763Skarels delflg = 0; 42016731Sralph if (argc < 1) { 421579Sroot fprintf(stderr, "puke\n"); 42216731Sralph return; 42316731Sralph } 424579Sroot for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++) 425579Sroot if (ap[0][0] == '-' && ap[0][1] == 'd') 426579Sroot dflag++; 42716731Sralph if (!dflag) { 4289978Seric /* give it to sendmail, rah rah! */ 429579Sroot unlink(lettmp); 430579Sroot ap = newargv+1; 431579Sroot if (rmail) 432579Sroot *ap-- = "-s"; 4339978Seric *ap = "-sendmail"; 4344461Sroot setuid(getuid()); 4359978Seric execv(SENDMAIL, ap); 4369978Seric perror(SENDMAIL); 437579Sroot exit(EX_UNAVAILABLE); 438579Sroot } 439579Sroot 44029763Skarels truename = 0; 441579Sroot line[0] = '\0'; 442579Sroot 443579Sroot /* 444579Sroot * When we fall out of this, argv[1] should be first name, 445579Sroot * argc should be number of names + 1. 446579Sroot */ 447579Sroot 448579Sroot while (argc > 1 && *argv[1] == '-') { 449579Sroot cp = *++argv; 450579Sroot argc--; 451579Sroot switch (cp[1]) { 452579Sroot case 'r': 45316731Sralph if (argc <= 1) 454579Sroot usage(); 45529763Skarels truename = argv[1]; 45615346Skarels fgets(line, LSIZE, stdin); 45715346Skarels if (strcmpn("From", line, 4) == 0) 45815346Skarels line[0] = '\0'; 459579Sroot argv++; 460579Sroot argc--; 461579Sroot break; 462579Sroot 463579Sroot case 'h': 46416731Sralph if (argc <= 1) 465579Sroot usage(); 466579Sroot hseqno = atoi(argv[1]); 467579Sroot argv++; 468579Sroot argc--; 469579Sroot break; 470579Sroot 471579Sroot case 'd': 472579Sroot break; 473579Sroot 474579Sroot default: 475579Sroot usage(); 476579Sroot } 477579Sroot } 47816731Sralph if (argc <= 1) 479579Sroot usage(); 48029763Skarels if (truename == 0) 48129763Skarels truename = my_name; 482579Sroot time(&iop); 483579Sroot fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop)); 484579Sroot iop = ftell(tmpf); 48516731Sralph flgf = first = 1; 48616731Sralph for (;;) { 48716731Sralph if (first) { 48816731Sralph first = 0; 48916731Sralph if (*line == '\0' && fgets(line, LSIZE, stdin) == NULL) 49016731Sralph break; 49116731Sralph } else { 49216731Sralph if (fgets(line, LSIZE, stdin) == NULL) 49316731Sralph break; 49416731Sralph } 49516731Sralph if (*line == '.' && line[1] == '\n' && isatty(fileno(stdin))) 496579Sroot break; 497579Sroot if (isfrom(line)) 49816731Sralph putc('>', tmpf); 499579Sroot fputs(line, tmpf); 500579Sroot flgf = 0; 501579Sroot } 50216731Sralph putc('\n', tmpf); 503579Sroot nlet = 1; 504579Sroot let[0].adr = 0; 505579Sroot let[1].adr = ftell(tmpf); 506579Sroot if (flgf) 507579Sroot return; 50816731Sralph while (--argc > 0) 5096015Swnj if (!sendmail(0, *++argv, truename)) 510579Sroot error++; 51110644Seric if (error && safefile(dead)) { 512579Sroot setuid(getuid()); 513579Sroot malf = fopen(dead, "w"); 514579Sroot if (malf == NULL) { 51516731Sralph printf("mail: cannot open %s\n", dead); 516579Sroot fclose(tmpf); 517579Sroot return; 518579Sroot } 519579Sroot copylet(0, malf, ZAP); 520579Sroot fclose(malf); 52116731Sralph printf("Mail saved in %s\n", dead); 522579Sroot } 523579Sroot fclose(tmpf); 524579Sroot } 525579Sroot 52617019Sralph sendrmt(n, name) 527579Sroot char *name; 528579Sroot { 529579Sroot FILE *rmf, *popen(); 530579Sroot register char *p; 531579Sroot char rsys[64], cmd[64]; 53217019Sralph register pid; 533579Sroot int sts; 534579Sroot 53517019Sralph #ifdef notdef 53617019Sralph if (any('^', name)) { 537579Sroot while (p = index(name, '^')) 538579Sroot *p = '!'; 539579Sroot if (strncmp(name, "researc", 7)) { 540579Sroot strcpy(rsys, "research"); 541579Sroot if (*name != '!') 542579Sroot --name; 543579Sroot goto skip; 544579Sroot } 545579Sroot } 54617019Sralph #endif 54717019Sralph for (p=rsys; *name!='!'; *p++ = *name++) 54817019Sralph if (*name=='\0') 54917019Sralph return(0); /* local address, no '!' */ 550579Sroot *p = '\0'; 55117019Sralph if (name[1]=='\0') { 55216731Sralph printf("null name\n"); 553579Sroot return(0); 554579Sroot } 555579Sroot skip: 556579Sroot if ((pid = fork()) == -1) { 557579Sroot fprintf(stderr, "mail: can't create proc for remote\n"); 558579Sroot return(0); 559579Sroot } 560579Sroot if (pid) { 561579Sroot while (wait(&sts) != pid) { 562579Sroot if (wait(&sts)==-1) 563579Sroot return(0); 564579Sroot } 565579Sroot return(!sts); 566579Sroot } 567579Sroot setuid(getuid()); 56817019Sralph if (any('!', name+1)) 56932414Sbostic (void)sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); 57017019Sralph else 57132414Sbostic (void)sprintf(cmd, "uux - %s!rmail %s", rsys, name+1); 572579Sroot if ((rmf=popen(cmd, "w")) == NULL) 573579Sroot exit(1); 57417019Sralph copylet(n, rmf, REMOTE); 57510783Seric exit(pclose(rmf) != 0); 576579Sroot } 577579Sroot 578579Sroot usage() 579579Sroot { 580579Sroot 581579Sroot fprintf(stderr, "Usage: mail [ -f ] people . . .\n"); 58215299Skarels error = EX_USAGE; 58316731Sralph done(); 584579Sroot } 585579Sroot 5866015Swnj #include <sys/socket.h> 5879226Ssam #include <netinet/in.h> 58810227Ssam #include <netdb.h> 5896015Swnj 59016731Sralph notifybiff(msg) 59116731Sralph char *msg; 59216731Sralph { 59316731Sralph static struct sockaddr_in addr; 59416731Sralph static int f = -1; 59516731Sralph 59616731Sralph if (addr.sin_family == 0) { 59716731Sralph struct hostent *hp = gethostbyname("localhost"); 59816731Sralph struct servent *sp = getservbyname("biff", "udp"); 59916731Sralph 60016731Sralph if (hp && sp) { 60116731Sralph addr.sin_family = hp->h_addrtype; 60216731Sralph bcopy(hp->h_addr, &addr.sin_addr, hp->h_length); 60316731Sralph addr.sin_port = sp->s_port; 60416731Sralph } 60516731Sralph } 60616731Sralph if (addr.sin_family) { 60716731Sralph if (f < 0) 60816731Sralph f = socket(AF_INET, SOCK_DGRAM, 0); 60931237Sbostic if (f >= 0) 61031237Sbostic sendto(f, msg, strlen(msg)+1, 0, &addr, sizeof (addr)); 61116731Sralph } 61216731Sralph } 61316731Sralph 6146015Swnj sendmail(n, name, fromaddr) 61516731Sralph int n; 61616731Sralph char *name, *fromaddr; 617579Sroot { 61816731Sralph char file[256]; 61916731Sralph int mask, fd; 62016731Sralph struct passwd *pw; 62116731Sralph #ifdef notdef 622579Sroot struct stat statb; 62316731Sralph #endif 6243666Swnj char buf[128]; 625579Sroot 62617019Sralph if (*name=='!') 62717019Sralph name++; 62817019Sralph if (any('!', name)) 62917019Sralph return (sendrmt(n, name)); 630579Sroot if ((pw = getpwnam(name)) == NULL) { 63116731Sralph printf("mail: can't send to %s\n", name); 632579Sroot return(0); 633579Sroot } 634579Sroot cat(file, maildir, name); 63516731Sralph #ifdef notdef 636579Sroot if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { 637579Sroot strcat(file, "/"); 638579Sroot strcat(file, name); 639579Sroot } 64016731Sralph #endif 64110644Seric if (!safefile(file)) 6424458Sroot return(0); 64316731Sralph fd = open(file, O_WRONLY | O_CREAT, MAILMODE); 64416731Sralph if (fd >= 0) { 64516731Sralph flock(fd, LOCK_EX); 64616731Sralph malf = fdopen(fd, "a"); 64716731Sralph } 64816731Sralph if (fd < 0 || malf == NULL) { 64916731Sralph close(fd); 65016731Sralph printf("mail: %s: cannot append\n", file); 651579Sroot return(0); 652579Sroot } 65316731Sralph fchown(fd, pw->pw_uid, pw->pw_gid); 65433607Sbostic (void)sprintf(buf, "%s@%ld\n", name, ftell(malf)); 655579Sroot copylet(n, malf, ORDINARY); 6566015Swnj fclose(malf); 65716731Sralph notifybiff(buf); 658579Sroot return(1); 659579Sroot } 660579Sroot 66116731Sralph delex(i) 662579Sroot { 66329763Skarels if (i != SIGINT) { 66429763Skarels setsig(i, SIG_DFL); 665*33608Sbostic sigsetmask(sigblock(0L) &~ sigmask(i)); 66629763Skarels } 66716731Sralph putc('\n', stderr); 66816731Sralph if (delflg) 669579Sroot longjmp(sjbuf, 1); 67029763Skarels if (error == 0) 67129763Skarels error = i; 672579Sroot done(); 673579Sroot } 674579Sroot 67516731Sralph done() 676579Sroot { 677579Sroot 678579Sroot unlink(lettmp); 679579Sroot exit(error); 680579Sroot } 681579Sroot 682579Sroot cat(to, from1, from2) 68316731Sralph char *to, *from1, *from2; 684579Sroot { 68516731Sralph register char *cp, *dp; 686579Sroot 68716731Sralph cp = to; 68816731Sralph for (dp = from1; *cp = *dp++; cp++) 68916731Sralph ; 69016731Sralph for (dp = from2; *cp++ = *dp++; ) 69116731Sralph ; 692579Sroot } 693579Sroot 69416731Sralph /* copy p... into s, update p */ 69516731Sralph char * 69616731Sralph getarg(s, p) 69716731Sralph register char *s, *p; 698579Sroot { 699579Sroot while (*p == ' ' || *p == '\t') 700579Sroot p++; 701579Sroot if (*p == '\n' || *p == '\0') 702579Sroot return(NULL); 703579Sroot while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 704579Sroot *s++ = *p++; 705579Sroot *s = '\0'; 706579Sroot return(p); 707579Sroot } 70810644Seric 70910644Seric safefile(f) 71010644Seric char *f; 71110644Seric { 71210644Seric struct stat statb; 71310644Seric 71410644Seric if (lstat(f, &statb) < 0) 71510644Seric return (1); 71610644Seric if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) { 71716731Sralph fprintf(stderr, 71816731Sralph "mail: %s has more than one link or is a symbolic link\n", 71916731Sralph f); 72010644Seric return (0); 72110644Seric } 72210644Seric return (1); 72310644Seric } 72416731Sralph 72516731Sralph panic(msg, a1, a2, a3) 72616731Sralph char *msg; 72716731Sralph { 72816731Sralph 72916731Sralph fprintf(stderr, "mail: "); 73016731Sralph fprintf(stderr, msg, a1, a2, a3); 73116731Sralph fprintf(stderr, "\n"); 73216731Sralph done(); 73316731Sralph } 734