114465Ssam #ifndef lint 2*33341Sbostic static char sccsid[] = "@(#)mail.local.c 4.31 (Berkeley) 01/12/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 { 66*33341Sbostic register int i; 6729763Skarels char *name; 6819868Smiriam struct passwd *pwent; 69579Sroot 70*33341Sbostic if (!(name = getlogin()) || !*name || !(pwent = getpwnam(name)) || 71*33341Sbostic getuid() != pwent->pw_uid) 72579Sroot pwent = getpwuid(getuid()); 73*33341Sbostic 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 */ 16816731Sralph fseek(tmpf, 0, 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 { 30516731Sralph register i, c; 30616731Sralph int fd, new = 0, oldmask; 307579Sroot struct stat stbuf; 308579Sroot 30916731Sralph #define mask(s) (1 << ((s) - 1)) 31016731Sralph oldmask = sigblock(mask(SIGINT)|mask(SIGHUP)|mask(SIGQUIT)); 31116731Sralph #undef mask 31216731Sralph fd = open(mailfile, O_RDWR | O_CREAT, MAILMODE); 31316731Sralph if (fd >= 0) { 31416731Sralph flock(fd, LOCK_EX); 31516731Sralph malf = fdopen(fd, "r+w"); 31616731Sralph } 31716731Sralph if (fd < 0 || malf == NULL) 31816731Sralph panic("can't rewrite %s", lfil); 31916731Sralph fstat(fd, &stbuf); 320579Sroot if (stbuf.st_size != let[nlet].adr) { /* new mail has arrived */ 32116731Sralph fseek(malf, let[nlet].adr, L_SET); 32216731Sralph fseek(tmpf, let[nlet].adr, L_SET); 32316731Sralph while ((c = getc(malf)) != EOF) 32416731Sralph putc(c, tmpf); 325579Sroot let[++nlet].adr = stbuf.st_size; 326579Sroot new = 1; 32716731Sralph fseek(malf, 0, L_SET); 328579Sroot } 32916731Sralph ftruncate(fd, 0); 330579Sroot for (i = 0; i < nlet; i++) 33116731Sralph if (let[i].change != 'd') 332579Sroot copylet(i, malf, ORDINARY); 33316731Sralph fclose(malf); /* implict unlock */ 334579Sroot if (new) 33516731Sralph printf("New mail has arrived.\n"); 33616731Sralph sigsetmask(oldmask); 337579Sroot } 338579Sroot 33916731Sralph /* copy mail (f1) to temp (f2) */ 34016731Sralph copymt(f1, f2) 34116731Sralph FILE *f1, *f2; 342579Sroot { 343579Sroot long nextadr; 344579Sroot 345579Sroot nlet = nextadr = 0; 346579Sroot let[0].adr = 0; 347579Sroot while (fgets(line, LSIZE, f1) != NULL) { 348579Sroot if (isfrom(line)) 349579Sroot let[nlet++].adr = nextadr; 350579Sroot nextadr += strlen(line); 351579Sroot fputs(line, f2); 352579Sroot } 353579Sroot let[nlet].adr = nextadr; /* last plus 1 */ 354579Sroot } 355579Sroot 35611893Seric copylet(n, f, type) 35711893Seric FILE *f; 35811893Seric { 35911893Seric int ch; 36011893Seric long k; 36129763Skarels char hostname[MAXHOSTNAMELEN]; 36211893Seric 36316731Sralph fseek(tmpf, let[n].adr, L_SET); 364579Sroot k = let[n+1].adr - let[n].adr; 36516731Sralph while (k-- > 1 && (ch = getc(tmpf)) != '\n') 36616731Sralph if (type != ZAP) 36716731Sralph putc(ch, f); 36816731Sralph switch (type) { 36916731Sralph 37016731Sralph case REMOTE: 3716199Sroot gethostname(hostname, sizeof (hostname)); 3726199Sroot fprintf(f, " remote from %s\n", hostname); 37316731Sralph break; 37416731Sralph 37516731Sralph case FORWARD: 376579Sroot fprintf(f, forwmsg); 37716731Sralph break; 37816731Sralph 37916731Sralph case ORDINARY: 38016731Sralph putc(ch, f); 38116731Sralph break; 38216731Sralph 38317019Sralph case ZAP: 38417019Sralph break; 38517019Sralph 38616731Sralph default: 38716731Sralph panic("Bad letter type %d to copylet.", type); 38816731Sralph } 38916731Sralph while (k-- > 1) { 39016731Sralph ch = getc(tmpf); 39116731Sralph putc(ch, f); 39216731Sralph } 39316731Sralph if (type != ZAP || ch != '\n') 39416731Sralph putc(getc(tmpf), f); 395579Sroot } 396579Sroot 397579Sroot isfrom(lp) 398579Sroot register char *lp; 399579Sroot { 400579Sroot register char *p; 401579Sroot 402579Sroot for (p = from; *p; ) 403579Sroot if (*lp++ != *p++) 404579Sroot return(0); 405579Sroot return(1); 406579Sroot } 407579Sroot 4086015Swnj bulkmail(argc, argv) 409579Sroot char **argv; 410579Sroot { 41129763Skarels char *truename; 412579Sroot int first; 413579Sroot register char *cp; 414579Sroot char *newargv[1000]; 415579Sroot register char **ap; 416579Sroot register char **vp; 417579Sroot int dflag; 418579Sroot 419579Sroot dflag = 0; 42029763Skarels delflg = 0; 42116731Sralph if (argc < 1) { 422579Sroot fprintf(stderr, "puke\n"); 42316731Sralph return; 42416731Sralph } 425579Sroot for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++) 426579Sroot if (ap[0][0] == '-' && ap[0][1] == 'd') 427579Sroot dflag++; 42816731Sralph if (!dflag) { 4299978Seric /* give it to sendmail, rah rah! */ 430579Sroot unlink(lettmp); 431579Sroot ap = newargv+1; 432579Sroot if (rmail) 433579Sroot *ap-- = "-s"; 4349978Seric *ap = "-sendmail"; 4354461Sroot setuid(getuid()); 4369978Seric execv(SENDMAIL, ap); 4379978Seric perror(SENDMAIL); 438579Sroot exit(EX_UNAVAILABLE); 439579Sroot } 440579Sroot 44129763Skarels truename = 0; 442579Sroot line[0] = '\0'; 443579Sroot 444579Sroot /* 445579Sroot * When we fall out of this, argv[1] should be first name, 446579Sroot * argc should be number of names + 1. 447579Sroot */ 448579Sroot 449579Sroot while (argc > 1 && *argv[1] == '-') { 450579Sroot cp = *++argv; 451579Sroot argc--; 452579Sroot switch (cp[1]) { 453579Sroot case 'r': 45416731Sralph if (argc <= 1) 455579Sroot usage(); 45629763Skarels truename = argv[1]; 45715346Skarels fgets(line, LSIZE, stdin); 45815346Skarels if (strcmpn("From", line, 4) == 0) 45915346Skarels line[0] = '\0'; 460579Sroot argv++; 461579Sroot argc--; 462579Sroot break; 463579Sroot 464579Sroot case 'h': 46516731Sralph if (argc <= 1) 466579Sroot usage(); 467579Sroot hseqno = atoi(argv[1]); 468579Sroot argv++; 469579Sroot argc--; 470579Sroot break; 471579Sroot 472579Sroot case 'd': 473579Sroot break; 474579Sroot 475579Sroot default: 476579Sroot usage(); 477579Sroot } 478579Sroot } 47916731Sralph if (argc <= 1) 480579Sroot usage(); 48129763Skarels if (truename == 0) 48229763Skarels truename = my_name; 483579Sroot time(&iop); 484579Sroot fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop)); 485579Sroot iop = ftell(tmpf); 48616731Sralph flgf = first = 1; 48716731Sralph for (;;) { 48816731Sralph if (first) { 48916731Sralph first = 0; 49016731Sralph if (*line == '\0' && fgets(line, LSIZE, stdin) == NULL) 49116731Sralph break; 49216731Sralph } else { 49316731Sralph if (fgets(line, LSIZE, stdin) == NULL) 49416731Sralph break; 49516731Sralph } 49616731Sralph if (*line == '.' && line[1] == '\n' && isatty(fileno(stdin))) 497579Sroot break; 498579Sroot if (isfrom(line)) 49916731Sralph putc('>', tmpf); 500579Sroot fputs(line, tmpf); 501579Sroot flgf = 0; 502579Sroot } 50316731Sralph putc('\n', tmpf); 504579Sroot nlet = 1; 505579Sroot let[0].adr = 0; 506579Sroot let[1].adr = ftell(tmpf); 507579Sroot if (flgf) 508579Sroot return; 50916731Sralph while (--argc > 0) 5106015Swnj if (!sendmail(0, *++argv, truename)) 511579Sroot error++; 51210644Seric if (error && safefile(dead)) { 513579Sroot setuid(getuid()); 514579Sroot malf = fopen(dead, "w"); 515579Sroot if (malf == NULL) { 51616731Sralph printf("mail: cannot open %s\n", dead); 517579Sroot fclose(tmpf); 518579Sroot return; 519579Sroot } 520579Sroot copylet(0, malf, ZAP); 521579Sroot fclose(malf); 52216731Sralph printf("Mail saved in %s\n", dead); 523579Sroot } 524579Sroot fclose(tmpf); 525579Sroot } 526579Sroot 52717019Sralph sendrmt(n, name) 528579Sroot char *name; 529579Sroot { 530579Sroot FILE *rmf, *popen(); 531579Sroot register char *p; 532579Sroot char rsys[64], cmd[64]; 53317019Sralph register pid; 534579Sroot int sts; 535579Sroot 53617019Sralph #ifdef notdef 53717019Sralph if (any('^', name)) { 538579Sroot while (p = index(name, '^')) 539579Sroot *p = '!'; 540579Sroot if (strncmp(name, "researc", 7)) { 541579Sroot strcpy(rsys, "research"); 542579Sroot if (*name != '!') 543579Sroot --name; 544579Sroot goto skip; 545579Sroot } 546579Sroot } 54717019Sralph #endif 54817019Sralph for (p=rsys; *name!='!'; *p++ = *name++) 54917019Sralph if (*name=='\0') 55017019Sralph return(0); /* local address, no '!' */ 551579Sroot *p = '\0'; 55217019Sralph if (name[1]=='\0') { 55316731Sralph printf("null name\n"); 554579Sroot return(0); 555579Sroot } 556579Sroot skip: 557579Sroot if ((pid = fork()) == -1) { 558579Sroot fprintf(stderr, "mail: can't create proc for remote\n"); 559579Sroot return(0); 560579Sroot } 561579Sroot if (pid) { 562579Sroot while (wait(&sts) != pid) { 563579Sroot if (wait(&sts)==-1) 564579Sroot return(0); 565579Sroot } 566579Sroot return(!sts); 567579Sroot } 568579Sroot setuid(getuid()); 56917019Sralph if (any('!', name+1)) 57032414Sbostic (void)sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); 57117019Sralph else 57232414Sbostic (void)sprintf(cmd, "uux - %s!rmail %s", rsys, name+1); 573579Sroot if ((rmf=popen(cmd, "w")) == NULL) 574579Sroot exit(1); 57517019Sralph copylet(n, rmf, REMOTE); 57610783Seric exit(pclose(rmf) != 0); 577579Sroot } 578579Sroot 579579Sroot usage() 580579Sroot { 581579Sroot 582579Sroot fprintf(stderr, "Usage: mail [ -f ] people . . .\n"); 58315299Skarels error = EX_USAGE; 58416731Sralph done(); 585579Sroot } 586579Sroot 5876015Swnj #include <sys/socket.h> 5889226Ssam #include <netinet/in.h> 58910227Ssam #include <netdb.h> 5906015Swnj 59116731Sralph notifybiff(msg) 59216731Sralph char *msg; 59316731Sralph { 59416731Sralph static struct sockaddr_in addr; 59516731Sralph static int f = -1; 59616731Sralph 59716731Sralph if (addr.sin_family == 0) { 59816731Sralph struct hostent *hp = gethostbyname("localhost"); 59916731Sralph struct servent *sp = getservbyname("biff", "udp"); 60016731Sralph 60116731Sralph if (hp && sp) { 60216731Sralph addr.sin_family = hp->h_addrtype; 60316731Sralph bcopy(hp->h_addr, &addr.sin_addr, hp->h_length); 60416731Sralph addr.sin_port = sp->s_port; 60516731Sralph } 60616731Sralph } 60716731Sralph if (addr.sin_family) { 60816731Sralph if (f < 0) 60916731Sralph f = socket(AF_INET, SOCK_DGRAM, 0); 61031237Sbostic if (f >= 0) 61131237Sbostic sendto(f, msg, strlen(msg)+1, 0, &addr, sizeof (addr)); 61216731Sralph } 61316731Sralph } 61416731Sralph 6156015Swnj sendmail(n, name, fromaddr) 61616731Sralph int n; 61716731Sralph char *name, *fromaddr; 618579Sroot { 61916731Sralph char file[256]; 62016731Sralph int mask, fd; 62116731Sralph struct passwd *pw; 62216731Sralph #ifdef notdef 623579Sroot struct stat statb; 62416731Sralph #endif 6253666Swnj char buf[128]; 626579Sroot 62717019Sralph if (*name=='!') 62817019Sralph name++; 62917019Sralph if (any('!', name)) 63017019Sralph return (sendrmt(n, name)); 631579Sroot if ((pw = getpwnam(name)) == NULL) { 63216731Sralph printf("mail: can't send to %s\n", name); 633579Sroot return(0); 634579Sroot } 635579Sroot cat(file, maildir, name); 63616731Sralph #ifdef notdef 637579Sroot if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { 638579Sroot strcat(file, "/"); 639579Sroot strcat(file, name); 640579Sroot } 64116731Sralph #endif 64210644Seric if (!safefile(file)) 6434458Sroot return(0); 64416731Sralph fd = open(file, O_WRONLY | O_CREAT, MAILMODE); 64516731Sralph if (fd >= 0) { 64616731Sralph flock(fd, LOCK_EX); 64716731Sralph malf = fdopen(fd, "a"); 64816731Sralph } 64916731Sralph if (fd < 0 || malf == NULL) { 65016731Sralph close(fd); 65116731Sralph printf("mail: %s: cannot append\n", file); 652579Sroot return(0); 653579Sroot } 65416731Sralph fchown(fd, pw->pw_uid, pw->pw_gid); 65532414Sbostic (void)sprintf(buf, "%s@%d\n", name, ftell(malf)); 656579Sroot copylet(n, malf, ORDINARY); 6576015Swnj fclose(malf); 65816731Sralph notifybiff(buf); 659579Sroot return(1); 660579Sroot } 661579Sroot 66216731Sralph delex(i) 663579Sroot { 66429763Skarels if (i != SIGINT) { 66529763Skarels setsig(i, SIG_DFL); 66629763Skarels sigsetmask(sigblock(0) &~ sigmask(i)); 66729763Skarels } 66816731Sralph putc('\n', stderr); 66916731Sralph if (delflg) 670579Sroot longjmp(sjbuf, 1); 67129763Skarels if (error == 0) 67229763Skarels error = i; 673579Sroot done(); 674579Sroot } 675579Sroot 67616731Sralph done() 677579Sroot { 678579Sroot 679579Sroot unlink(lettmp); 680579Sroot exit(error); 681579Sroot } 682579Sroot 683579Sroot cat(to, from1, from2) 68416731Sralph char *to, *from1, *from2; 685579Sroot { 68616731Sralph register char *cp, *dp; 687579Sroot 68816731Sralph cp = to; 68916731Sralph for (dp = from1; *cp = *dp++; cp++) 69016731Sralph ; 69116731Sralph for (dp = from2; *cp++ = *dp++; ) 69216731Sralph ; 693579Sroot } 694579Sroot 69516731Sralph /* copy p... into s, update p */ 69616731Sralph char * 69716731Sralph getarg(s, p) 69816731Sralph register char *s, *p; 699579Sroot { 700579Sroot while (*p == ' ' || *p == '\t') 701579Sroot p++; 702579Sroot if (*p == '\n' || *p == '\0') 703579Sroot return(NULL); 704579Sroot while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 705579Sroot *s++ = *p++; 706579Sroot *s = '\0'; 707579Sroot return(p); 708579Sroot } 70910644Seric 71010644Seric safefile(f) 71110644Seric char *f; 71210644Seric { 71310644Seric struct stat statb; 71410644Seric 71510644Seric if (lstat(f, &statb) < 0) 71610644Seric return (1); 71710644Seric if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) { 71816731Sralph fprintf(stderr, 71916731Sralph "mail: %s has more than one link or is a symbolic link\n", 72016731Sralph f); 72110644Seric return (0); 72210644Seric } 72310644Seric return (1); 72410644Seric } 72516731Sralph 72616731Sralph panic(msg, a1, a2, a3) 72716731Sralph char *msg; 72816731Sralph { 72916731Sralph 73016731Sralph fprintf(stderr, "mail: "); 73116731Sralph fprintf(stderr, msg, a1, a2, a3); 73216731Sralph fprintf(stderr, "\n"); 73316731Sralph done(); 73416731Sralph } 735