114465Ssam #ifndef lint 2*37465Sbostic static char sccsid[] = "@(#)mail.local.c 4.36 (Berkeley) 04/21/89"; 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> 16*37465Sbostic #include "pathnames.h" 17579Sroot 1816731Sralph /* copylet flags */ 1916731Sralph #define REMOTE 1 /* remote mail, add rmtmsg */ 2016731Sralph #define ORDINARY 2 2116731Sralph #define ZAP 3 /* zap header and trailing empty line */ 2216731Sralph #define FORWARD 4 23579Sroot 2416731Sralph #define LSIZE 256 2516731Sralph #define MAXLET 300 /* maximum number of letters */ 2616731Sralph #define MAILMODE 0600 /* mode of created mail */ 27579Sroot 28579Sroot char line[LSIZE]; 29579Sroot char resp[LSIZE]; 30579Sroot struct let { 31579Sroot long adr; 32579Sroot char change; 33579Sroot } let[MAXLET]; 34579Sroot int nlet = 0; 35579Sroot char lfil[50]; 36579Sroot long iop, time(); 37579Sroot char *getenv(); 38579Sroot char *index(); 39*37465Sbostic char lettmp[] = _PATH_TMP; 40*37465Sbostic char maildir[] = _PATH_MAILDIR; 41579Sroot char mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; 42579Sroot char dead[] = "dead.letter"; 43579Sroot char forwmsg[] = " forwarded\n"; 44579Sroot FILE *tmpf; 45579Sroot FILE *malf; 4629763Skarels char my_name[60]; 47579Sroot char *getlogin(); 48579Sroot int error; 49579Sroot int changed; 50579Sroot int forward; 51579Sroot char from[] = "From "; 52579Sroot long ftell(); 5316731Sralph int delex(); 54579Sroot char *ctime(); 55579Sroot int flgf; 56579Sroot int flgp; 57579Sroot int delflg = 1; 58579Sroot int hseqno; 59579Sroot jmp_buf sjbuf; 60579Sroot int rmail; 61579Sroot 62579Sroot main(argc, argv) 63579Sroot char **argv; 64579Sroot { 6533341Sbostic register int i; 6629763Skarels char *name; 6719868Smiriam struct passwd *pwent; 68579Sroot 6933341Sbostic if (!(name = getlogin()) || !*name || !(pwent = getpwnam(name)) || 7033341Sbostic getuid() != pwent->pw_uid) 71579Sroot pwent = getpwuid(getuid()); 7233341Sbostic strncpy(my_name, pwent ? pwent->pw_name : "???", sizeof(my_name)-1); 7316731Sralph if (setjmp(sjbuf)) 7416731Sralph done(); 7514912Sralph for (i=SIGHUP; i<=SIGTERM; i++) 7616731Sralph setsig(i, delex); 7717533Sralph i = mkstemp(lettmp); 7836487Sbostic tmpf = fdopen(i, "r+"); 7917533Sralph if (i < 0 || tmpf == NULL) 8016731Sralph panic("mail: %s: cannot open for writing", lettmp); 8116731Sralph /* 8216731Sralph * This protects against others reading mail from temp file and 8316731Sralph * if we exit, the file will be deleted already. 8416731Sralph */ 8516731Sralph unlink(lettmp); 86579Sroot if (argv[0][0] == 'r') 87579Sroot rmail++; 88579Sroot if (argv[0][0] != 'r' && /* no favors for rmail*/ 89579Sroot (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd"))) 90579Sroot printmail(argc, argv); 91579Sroot else 926015Swnj bulkmail(argc, argv); 93579Sroot done(); 94579Sroot } 95579Sroot 96579Sroot setsig(i, f) 97579Sroot int i; 98579Sroot int (*f)(); 99579Sroot { 10016731Sralph if (signal(i, SIG_IGN) != SIG_IGN) 101579Sroot signal(i, f); 102579Sroot } 103579Sroot 104579Sroot any(c, str) 105579Sroot register int c; 106579Sroot register char *str; 107579Sroot { 108579Sroot 109579Sroot while (*str) 110579Sroot if (c == *str++) 111579Sroot return(1); 112579Sroot return(0); 113579Sroot } 114579Sroot 115579Sroot printmail(argc, argv) 11616731Sralph char **argv; 117579Sroot { 118579Sroot int flg, i, j, print; 119579Sroot char *p, *getarg(); 120579Sroot struct stat statb; 121579Sroot 122579Sroot setuid(getuid()); 123579Sroot cat(mailfile, maildir, my_name); 12416731Sralph #ifdef notdef 125579Sroot if (stat(mailfile, &statb) >= 0 126579Sroot && (statb.st_mode & S_IFMT) == S_IFDIR) { 127579Sroot strcat(mailfile, "/"); 128579Sroot strcat(mailfile, my_name); 129579Sroot } 13016731Sralph #endif 13116731Sralph for (; argc > 1; argv++, argc--) { 13216731Sralph if (argv[1][0] != '-') 13316731Sralph break; 13416731Sralph switch (argv[1][1]) { 13516731Sralph 13616731Sralph case 'p': 13716731Sralph flgp++; 13816731Sralph /* fall thru... */ 13916731Sralph case 'q': 14016731Sralph delflg = 0; 14116731Sralph break; 14216731Sralph 14316731Sralph case 'f': 14416731Sralph if (argc >= 3) { 14516731Sralph strcpy(mailfile, argv[2]); 14616731Sralph argv++, argc--; 147579Sroot } 148579Sroot break; 14916731Sralph 15016731Sralph case 'b': 15116731Sralph forward = 1; 15216731Sralph break; 15316731Sralph 15416731Sralph default: 15516731Sralph panic("unknown option %c", argv[1][1]); 15616731Sralph /*NOTREACHED*/ 15716731Sralph } 158579Sroot } 159579Sroot malf = fopen(mailfile, "r"); 160579Sroot if (malf == NULL) { 16116731Sralph printf("No mail.\n"); 162579Sroot return; 163579Sroot } 16416731Sralph flock(fileno(malf), LOCK_SH); 165579Sroot copymt(malf, tmpf); 16616731Sralph fclose(malf); /* implicit unlock */ 16733607Sbostic fseek(tmpf, 0L, L_SET); 168579Sroot 169579Sroot changed = 0; 170579Sroot print = 1; 171579Sroot for (i = 0; i < nlet; ) { 172579Sroot j = forward ? i : nlet - i - 1; 17316731Sralph if (setjmp(sjbuf)) { 17416731Sralph print = 0; 175579Sroot } else { 176579Sroot if (print) 177579Sroot copylet(j, stdout, ORDINARY); 178579Sroot print = 1; 179579Sroot } 180579Sroot if (flgp) { 181579Sroot i++; 182579Sroot continue; 183579Sroot } 184579Sroot setjmp(sjbuf); 18516731Sralph fputs("? ", stdout); 186579Sroot fflush(stdout); 187579Sroot if (fgets(resp, LSIZE, stdin) == NULL) 188579Sroot break; 189579Sroot switch (resp[0]) { 190579Sroot 191579Sroot default: 19216731Sralph printf("usage\n"); 193579Sroot case '?': 194579Sroot print = 0; 19516731Sralph printf("q\tquit\n"); 19616731Sralph printf("x\texit without changing mail\n"); 19716731Sralph printf("p\tprint\n"); 19816731Sralph printf("s[file]\tsave (default mbox)\n"); 19916731Sralph printf("w[file]\tsame without header\n"); 20016731Sralph printf("-\tprint previous\n"); 20116731Sralph printf("d\tdelete\n"); 20216731Sralph printf("+\tnext (no delete)\n"); 20316731Sralph printf("m user\tmail to user\n"); 20416731Sralph printf("! cmd\texecute cmd\n"); 205579Sroot break; 206579Sroot 207579Sroot case '+': 208579Sroot case 'n': 209579Sroot case '\n': 210579Sroot i++; 211579Sroot break; 212579Sroot case 'x': 213579Sroot changed = 0; 214579Sroot case 'q': 215579Sroot goto donep; 216579Sroot case 'p': 217579Sroot break; 218579Sroot case '^': 219579Sroot case '-': 220579Sroot if (--i < 0) 221579Sroot i = 0; 222579Sroot break; 223579Sroot case 'y': 224579Sroot case 'w': 225579Sroot case 's': 226579Sroot flg = 0; 227579Sroot if (resp[1] != '\n' && resp[1] != ' ') { 228579Sroot printf("illegal\n"); 229579Sroot flg++; 230579Sroot print = 0; 231579Sroot continue; 232579Sroot } 233579Sroot if (resp[1] == '\n' || resp[1] == '\0') { 234579Sroot p = getenv("HOME"); 23516731Sralph if (p != 0) 236579Sroot cat(resp+1, p, "/mbox"); 237579Sroot else 238579Sroot cat(resp+1, "", "mbox"); 239579Sroot } 240579Sroot for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) { 241579Sroot malf = fopen(lfil, "a"); 242579Sroot if (malf == NULL) { 24316731Sralph printf("mail: %s: cannot append\n", 24416731Sralph lfil); 245579Sroot flg++; 246579Sroot continue; 247579Sroot } 248579Sroot copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY); 249579Sroot fclose(malf); 250579Sroot } 251579Sroot if (flg) 252579Sroot print = 0; 253579Sroot else { 254579Sroot let[j].change = 'd'; 255579Sroot changed++; 256579Sroot i++; 257579Sroot } 258579Sroot break; 259579Sroot case 'm': 260579Sroot flg = 0; 261579Sroot if (resp[1] == '\n' || resp[1] == '\0') { 262579Sroot i++; 263579Sroot continue; 264579Sroot } 265579Sroot if (resp[1] != ' ') { 266579Sroot printf("invalid command\n"); 267579Sroot flg++; 268579Sroot print = 0; 269579Sroot continue; 270579Sroot } 271579Sroot for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) 27217019Sralph if (!sendmail(j, lfil, my_name)) 273579Sroot flg++; 274579Sroot if (flg) 275579Sroot print = 0; 276579Sroot else { 277579Sroot let[j].change = 'd'; 278579Sroot changed++; 279579Sroot i++; 280579Sroot } 281579Sroot break; 282579Sroot case '!': 283579Sroot system(resp+1); 284579Sroot printf("!\n"); 285579Sroot print = 0; 286579Sroot break; 287579Sroot case 'd': 288579Sroot let[j].change = 'd'; 289579Sroot changed++; 290579Sroot i++; 291579Sroot if (resp[1] == 'q') 292579Sroot goto donep; 293579Sroot break; 294579Sroot } 295579Sroot } 296579Sroot donep: 297579Sroot if (changed) 298579Sroot copyback(); 299579Sroot } 300579Sroot 30116731Sralph /* copy temp or whatever back to /usr/spool/mail */ 30216731Sralph copyback() 303579Sroot { 30433607Sbostic register int i, c; 30533607Sbostic long oldmask; 30633607Sbostic int fd, new = 0; 307579Sroot struct stat stbuf; 308579Sroot 30933607Sbostic oldmask = sigblock(sigmask(SIGINT)|sigmask(SIGHUP)|sigmask(SIGQUIT)); 31016731Sralph fd = open(mailfile, O_RDWR | O_CREAT, MAILMODE); 31116731Sralph if (fd >= 0) { 31216731Sralph flock(fd, LOCK_EX); 31336487Sbostic malf = fdopen(fd, "r+"); 31416731Sralph } 31516731Sralph if (fd < 0 || malf == NULL) 31616731Sralph panic("can't rewrite %s", lfil); 31716731Sralph fstat(fd, &stbuf); 318579Sroot if (stbuf.st_size != let[nlet].adr) { /* new mail has arrived */ 31916731Sralph fseek(malf, let[nlet].adr, L_SET); 32016731Sralph fseek(tmpf, let[nlet].adr, L_SET); 32116731Sralph while ((c = getc(malf)) != EOF) 32216731Sralph putc(c, tmpf); 323579Sroot let[++nlet].adr = stbuf.st_size; 324579Sroot new = 1; 32533607Sbostic fseek(malf, 0L, L_SET); 326579Sroot } 32733607Sbostic ftruncate(fd, 0L); 328579Sroot for (i = 0; i < nlet; i++) 32916731Sralph if (let[i].change != 'd') 330579Sroot copylet(i, malf, ORDINARY); 33116731Sralph fclose(malf); /* implict unlock */ 332579Sroot if (new) 33316731Sralph printf("New mail has arrived.\n"); 33416731Sralph sigsetmask(oldmask); 335579Sroot } 336579Sroot 33716731Sralph /* copy mail (f1) to temp (f2) */ 33816731Sralph copymt(f1, f2) 33916731Sralph FILE *f1, *f2; 340579Sroot { 341579Sroot long nextadr; 342579Sroot 343579Sroot nlet = nextadr = 0; 344579Sroot let[0].adr = 0; 345579Sroot while (fgets(line, LSIZE, f1) != NULL) { 346579Sroot if (isfrom(line)) 347579Sroot let[nlet++].adr = nextadr; 348579Sroot nextadr += strlen(line); 349579Sroot fputs(line, f2); 350579Sroot } 351579Sroot let[nlet].adr = nextadr; /* last plus 1 */ 352579Sroot } 353579Sroot 35411893Seric copylet(n, f, type) 35511893Seric FILE *f; 35611893Seric { 35711893Seric int ch; 35811893Seric long k; 35929763Skarels char hostname[MAXHOSTNAMELEN]; 36011893Seric 36116731Sralph fseek(tmpf, let[n].adr, L_SET); 362579Sroot k = let[n+1].adr - let[n].adr; 36316731Sralph while (k-- > 1 && (ch = getc(tmpf)) != '\n') 36416731Sralph if (type != ZAP) 36516731Sralph putc(ch, f); 36616731Sralph switch (type) { 36716731Sralph 36816731Sralph case REMOTE: 3696199Sroot gethostname(hostname, sizeof (hostname)); 3706199Sroot fprintf(f, " remote from %s\n", hostname); 37116731Sralph break; 37216731Sralph 37316731Sralph case FORWARD: 374579Sroot fprintf(f, forwmsg); 37516731Sralph break; 37616731Sralph 37716731Sralph case ORDINARY: 37816731Sralph putc(ch, f); 37916731Sralph break; 38016731Sralph 38117019Sralph case ZAP: 38217019Sralph break; 38317019Sralph 38416731Sralph default: 38516731Sralph panic("Bad letter type %d to copylet.", type); 38616731Sralph } 38716731Sralph while (k-- > 1) { 38816731Sralph ch = getc(tmpf); 38916731Sralph putc(ch, f); 39016731Sralph } 39116731Sralph if (type != ZAP || ch != '\n') 39216731Sralph putc(getc(tmpf), f); 393579Sroot } 394579Sroot 395579Sroot isfrom(lp) 396579Sroot register char *lp; 397579Sroot { 398579Sroot register char *p; 399579Sroot 400579Sroot for (p = from; *p; ) 401579Sroot if (*lp++ != *p++) 402579Sroot return(0); 403579Sroot return(1); 404579Sroot } 405579Sroot 4066015Swnj bulkmail(argc, argv) 407579Sroot char **argv; 408579Sroot { 40929763Skarels char *truename; 410579Sroot int first; 411579Sroot register char *cp; 412579Sroot char *newargv[1000]; 413579Sroot register char **ap; 414579Sroot register char **vp; 415579Sroot int dflag; 416579Sroot 417579Sroot dflag = 0; 41829763Skarels delflg = 0; 41916731Sralph if (argc < 1) { 420579Sroot fprintf(stderr, "puke\n"); 42116731Sralph return; 42216731Sralph } 423579Sroot for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++) 424579Sroot if (ap[0][0] == '-' && ap[0][1] == 'd') 425579Sroot dflag++; 42616731Sralph if (!dflag) { 4279978Seric /* give it to sendmail, rah rah! */ 428579Sroot unlink(lettmp); 429579Sroot ap = newargv+1; 430579Sroot if (rmail) 431579Sroot *ap-- = "-s"; 4329978Seric *ap = "-sendmail"; 4334461Sroot setuid(getuid()); 434*37465Sbostic execv(_PATH_SENDMAIL, ap); 435*37465Sbostic perror(_PATH_SENDMAIL); 436579Sroot exit(EX_UNAVAILABLE); 437579Sroot } 438579Sroot 43929763Skarels truename = 0; 440579Sroot line[0] = '\0'; 441579Sroot 442579Sroot /* 443579Sroot * When we fall out of this, argv[1] should be first name, 444579Sroot * argc should be number of names + 1. 445579Sroot */ 446579Sroot 447579Sroot while (argc > 1 && *argv[1] == '-') { 448579Sroot cp = *++argv; 449579Sroot argc--; 450579Sroot switch (cp[1]) { 451579Sroot case 'r': 45216731Sralph if (argc <= 1) 453579Sroot usage(); 45429763Skarels truename = argv[1]; 45515346Skarels fgets(line, LSIZE, stdin); 45635645Sbostic if (strncmp("From", line, 4) == 0) 45715346Skarels line[0] = '\0'; 458579Sroot argv++; 459579Sroot argc--; 460579Sroot break; 461579Sroot 462579Sroot case 'h': 46316731Sralph if (argc <= 1) 464579Sroot usage(); 465579Sroot hseqno = atoi(argv[1]); 466579Sroot argv++; 467579Sroot argc--; 468579Sroot break; 469579Sroot 470579Sroot case 'd': 471579Sroot break; 472579Sroot 473579Sroot default: 474579Sroot usage(); 475579Sroot } 476579Sroot } 47716731Sralph if (argc <= 1) 478579Sroot usage(); 47929763Skarels if (truename == 0) 48029763Skarels truename = my_name; 481579Sroot time(&iop); 482579Sroot fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop)); 483579Sroot iop = ftell(tmpf); 48416731Sralph flgf = first = 1; 48516731Sralph for (;;) { 48616731Sralph if (first) { 48716731Sralph first = 0; 48816731Sralph if (*line == '\0' && fgets(line, LSIZE, stdin) == NULL) 48916731Sralph break; 49016731Sralph } else { 49116731Sralph if (fgets(line, LSIZE, stdin) == NULL) 49216731Sralph break; 49316731Sralph } 49416731Sralph if (*line == '.' && line[1] == '\n' && isatty(fileno(stdin))) 495579Sroot break; 496579Sroot if (isfrom(line)) 49716731Sralph putc('>', tmpf); 498579Sroot fputs(line, tmpf); 499579Sroot flgf = 0; 500579Sroot } 50116731Sralph putc('\n', tmpf); 502579Sroot nlet = 1; 503579Sroot let[0].adr = 0; 504579Sroot let[1].adr = ftell(tmpf); 505579Sroot if (flgf) 506579Sroot return; 50716731Sralph while (--argc > 0) 5086015Swnj if (!sendmail(0, *++argv, truename)) 509579Sroot error++; 51010644Seric if (error && safefile(dead)) { 511579Sroot setuid(getuid()); 512579Sroot malf = fopen(dead, "w"); 513579Sroot if (malf == NULL) { 51416731Sralph printf("mail: cannot open %s\n", dead); 515579Sroot fclose(tmpf); 516579Sroot return; 517579Sroot } 518579Sroot copylet(0, malf, ZAP); 519579Sroot fclose(malf); 52016731Sralph printf("Mail saved in %s\n", dead); 521579Sroot } 522579Sroot fclose(tmpf); 523579Sroot } 524579Sroot 52517019Sralph sendrmt(n, name) 526579Sroot char *name; 527579Sroot { 528579Sroot FILE *rmf, *popen(); 529579Sroot register char *p; 530579Sroot char rsys[64], cmd[64]; 53117019Sralph register pid; 532579Sroot int sts; 533579Sroot 53417019Sralph #ifdef notdef 53517019Sralph if (any('^', name)) { 536579Sroot while (p = index(name, '^')) 537579Sroot *p = '!'; 538579Sroot if (strncmp(name, "researc", 7)) { 539579Sroot strcpy(rsys, "research"); 540579Sroot if (*name != '!') 541579Sroot --name; 542579Sroot goto skip; 543579Sroot } 544579Sroot } 54517019Sralph #endif 54617019Sralph for (p=rsys; *name!='!'; *p++ = *name++) 54717019Sralph if (*name=='\0') 54817019Sralph return(0); /* local address, no '!' */ 549579Sroot *p = '\0'; 55017019Sralph if (name[1]=='\0') { 55116731Sralph printf("null name\n"); 552579Sroot return(0); 553579Sroot } 554579Sroot skip: 555579Sroot if ((pid = fork()) == -1) { 556579Sroot fprintf(stderr, "mail: can't create proc for remote\n"); 557579Sroot return(0); 558579Sroot } 559579Sroot if (pid) { 560579Sroot while (wait(&sts) != pid) { 561579Sroot if (wait(&sts)==-1) 562579Sroot return(0); 563579Sroot } 564579Sroot return(!sts); 565579Sroot } 566579Sroot setuid(getuid()); 56717019Sralph if (any('!', name+1)) 56832414Sbostic (void)sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); 56917019Sralph else 57032414Sbostic (void)sprintf(cmd, "uux - %s!rmail %s", rsys, name+1); 571579Sroot if ((rmf=popen(cmd, "w")) == NULL) 572579Sroot exit(1); 57317019Sralph copylet(n, rmf, REMOTE); 57410783Seric exit(pclose(rmf) != 0); 575579Sroot } 576579Sroot 577579Sroot usage() 578579Sroot { 579579Sroot 580579Sroot fprintf(stderr, "Usage: mail [ -f ] people . . .\n"); 58115299Skarels error = EX_USAGE; 58216731Sralph done(); 583579Sroot } 584579Sroot 5856015Swnj #include <sys/socket.h> 5869226Ssam #include <netinet/in.h> 58710227Ssam #include <netdb.h> 5886015Swnj 58916731Sralph notifybiff(msg) 59016731Sralph char *msg; 59116731Sralph { 59216731Sralph static struct sockaddr_in addr; 59316731Sralph static int f = -1; 59416731Sralph 59516731Sralph if (addr.sin_family == 0) { 59616731Sralph struct hostent *hp = gethostbyname("localhost"); 59716731Sralph struct servent *sp = getservbyname("biff", "udp"); 59816731Sralph 59916731Sralph if (hp && sp) { 60016731Sralph addr.sin_family = hp->h_addrtype; 60116731Sralph bcopy(hp->h_addr, &addr.sin_addr, hp->h_length); 60216731Sralph addr.sin_port = sp->s_port; 60316731Sralph } 60416731Sralph } 60516731Sralph if (addr.sin_family) { 60616731Sralph if (f < 0) 60716731Sralph f = socket(AF_INET, SOCK_DGRAM, 0); 60831237Sbostic if (f >= 0) 60931237Sbostic sendto(f, msg, strlen(msg)+1, 0, &addr, sizeof (addr)); 61016731Sralph } 61116731Sralph } 61216731Sralph 6136015Swnj sendmail(n, name, fromaddr) 61416731Sralph int n; 61516731Sralph char *name, *fromaddr; 616579Sroot { 61716731Sralph char file[256]; 61816731Sralph int mask, fd; 61916731Sralph struct passwd *pw; 62016731Sralph #ifdef notdef 621579Sroot struct stat statb; 62216731Sralph #endif 6233666Swnj char buf[128]; 624579Sroot 62517019Sralph if (*name=='!') 62617019Sralph name++; 62717019Sralph if (any('!', name)) 62817019Sralph return (sendrmt(n, name)); 629579Sroot if ((pw = getpwnam(name)) == NULL) { 63016731Sralph printf("mail: can't send to %s\n", name); 631579Sroot return(0); 632579Sroot } 633579Sroot cat(file, maildir, name); 63416731Sralph #ifdef notdef 635579Sroot if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { 636579Sroot strcat(file, "/"); 637579Sroot strcat(file, name); 638579Sroot } 63916731Sralph #endif 64010644Seric if (!safefile(file)) 6414458Sroot return(0); 64216731Sralph fd = open(file, O_WRONLY | O_CREAT, MAILMODE); 64316731Sralph if (fd >= 0) { 64416731Sralph flock(fd, LOCK_EX); 64516731Sralph malf = fdopen(fd, "a"); 64616731Sralph } 64716731Sralph if (fd < 0 || malf == NULL) { 64816731Sralph close(fd); 64916731Sralph printf("mail: %s: cannot append\n", file); 650579Sroot return(0); 651579Sroot } 65216731Sralph fchown(fd, pw->pw_uid, pw->pw_gid); 65333607Sbostic (void)sprintf(buf, "%s@%ld\n", name, ftell(malf)); 654579Sroot copylet(n, malf, ORDINARY); 6556015Swnj fclose(malf); 65616731Sralph notifybiff(buf); 657579Sroot return(1); 658579Sroot } 659579Sroot 66016731Sralph delex(i) 661579Sroot { 66229763Skarels if (i != SIGINT) { 66329763Skarels setsig(i, SIG_DFL); 66433608Sbostic sigsetmask(sigblock(0L) &~ sigmask(i)); 66529763Skarels } 66616731Sralph putc('\n', stderr); 66716731Sralph if (delflg) 668579Sroot longjmp(sjbuf, 1); 66929763Skarels if (error == 0) 67029763Skarels error = i; 671579Sroot done(); 672579Sroot } 673579Sroot 67416731Sralph done() 675579Sroot { 676579Sroot 677579Sroot unlink(lettmp); 678579Sroot exit(error); 679579Sroot } 680579Sroot 681579Sroot cat(to, from1, from2) 68216731Sralph char *to, *from1, *from2; 683579Sroot { 68416731Sralph register char *cp, *dp; 685579Sroot 68616731Sralph cp = to; 68716731Sralph for (dp = from1; *cp = *dp++; cp++) 68816731Sralph ; 68916731Sralph for (dp = from2; *cp++ = *dp++; ) 69016731Sralph ; 691579Sroot } 692579Sroot 69316731Sralph /* copy p... into s, update p */ 69416731Sralph char * 69516731Sralph getarg(s, p) 69616731Sralph register char *s, *p; 697579Sroot { 698579Sroot while (*p == ' ' || *p == '\t') 699579Sroot p++; 700579Sroot if (*p == '\n' || *p == '\0') 701579Sroot return(NULL); 702579Sroot while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 703579Sroot *s++ = *p++; 704579Sroot *s = '\0'; 705579Sroot return(p); 706579Sroot } 70710644Seric 70810644Seric safefile(f) 70910644Seric char *f; 71010644Seric { 71110644Seric struct stat statb; 71210644Seric 71310644Seric if (lstat(f, &statb) < 0) 71410644Seric return (1); 71510644Seric if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) { 71616731Sralph fprintf(stderr, 71716731Sralph "mail: %s has more than one link or is a symbolic link\n", 71816731Sralph f); 71910644Seric return (0); 72010644Seric } 72110644Seric return (1); 72210644Seric } 72316731Sralph 72416731Sralph panic(msg, a1, a2, a3) 72516731Sralph char *msg; 72616731Sralph { 72716731Sralph 72816731Sralph fprintf(stderr, "mail: "); 72916731Sralph fprintf(stderr, msg, a1, a2, a3); 73016731Sralph fprintf(stderr, "\n"); 73116731Sralph done(); 73216731Sralph } 733