114465Ssam #ifndef lint 2*14912Sralph static char sccsid[] = "@(#)mail.local.c 4.17 (Berkeley) 09/07/83"; 314465Ssam #endif 414465Ssam 5579Sroot #include <ctype.h> 6579Sroot #include <stdio.h> 7579Sroot #include <pwd.h> 8579Sroot #include <utmp.h> 9579Sroot #include <signal.h> 10579Sroot #include <sys/types.h> 11579Sroot #include <sys/stat.h> 12579Sroot #include <setjmp.h> 13579Sroot #include <sysexits.h> 14579Sroot 159978Seric #define SENDMAIL "/usr/lib/sendmail" 16579Sroot 17579Sroot 18579Sroot /*copylet flags */ 19579Sroot /*remote mail, add rmtmsg */ 20579Sroot #define REMOTE 1 21579Sroot /* zap header and trailing empty line */ 22579Sroot #define ZAP 3 23579Sroot #define ORDINARY 2 24579Sroot #define FORWARD 4 25579Sroot #define LSIZE 256 26579Sroot #define MAXLET 300 /* maximum number of letters */ 2711899Sleres #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 *netname = "vax"; 45579Sroot char forwmsg[] = " forwarded\n"; 46579Sroot FILE *tmpf; 47579Sroot FILE *malf; 48579Sroot char *my_name; 49579Sroot char *getlogin(); 50579Sroot struct passwd *getpwuid(); 51579Sroot int error; 52579Sroot int changed; 53579Sroot int forward; 54579Sroot char from[] = "From "; 55579Sroot long ftell(); 56579Sroot int delete(); 57579Sroot char *ctime(); 58579Sroot int flgf; 59579Sroot int flgp; 60579Sroot int delflg = 1; 61579Sroot int hseqno; 62579Sroot jmp_buf sjbuf; 63579Sroot int rmail; 64579Sroot 65579Sroot main(argc, argv) 66579Sroot char **argv; 67579Sroot { 68579Sroot register i; 69579Sroot char sobuf[BUFSIZ]; 70579Sroot 71579Sroot setbuf(stdout, sobuf); 72579Sroot mktemp(lettmp); 73579Sroot unlink(lettmp); 74579Sroot my_name = getlogin(); 75579Sroot if (my_name == NULL || strlen(my_name) == 0) { 76579Sroot struct passwd *pwent; 77579Sroot pwent = getpwuid(getuid()); 78579Sroot if (pwent==NULL) 79579Sroot my_name = "???"; 80579Sroot else 81579Sroot my_name = pwent->pw_name; 82579Sroot } 83579Sroot if(setjmp(sjbuf)) done(); 84*14912Sralph for (i=SIGHUP; i<=SIGTERM; i++) 85579Sroot setsig(i, delete); 86579Sroot tmpf = fopen(lettmp, "w"); 87579Sroot if (tmpf == NULL) { 88579Sroot fprintf(stderr, "mail: cannot open %s for writing\n", lettmp); 89579Sroot done(); 90579Sroot } 91579Sroot if (argv[0][0] == 'r') 92579Sroot rmail++; 93579Sroot if (argv[0][0] != 'r' && /* no favors for rmail*/ 94579Sroot (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd"))) 95579Sroot printmail(argc, argv); 96579Sroot else 976015Swnj bulkmail(argc, argv); 98579Sroot done(); 99579Sroot } 100579Sroot 101579Sroot setsig(i, f) 102579Sroot int i; 103579Sroot int (*f)(); 104579Sroot { 105579Sroot if(signal(i, SIG_IGN)!=SIG_IGN) 106579Sroot signal(i, f); 107579Sroot } 108579Sroot 109579Sroot any(c, str) 110579Sroot register int c; 111579Sroot register char *str; 112579Sroot { 113579Sroot 114579Sroot while (*str) 115579Sroot if (c == *str++) 116579Sroot return(1); 117579Sroot return(0); 118579Sroot } 119579Sroot 120579Sroot printmail(argc, argv) 121579Sroot char **argv; 122579Sroot { 123579Sroot int flg, i, j, print; 124579Sroot char *p, *getarg(); 125579Sroot struct stat statb; 126579Sroot 127579Sroot setuid(getuid()); 128579Sroot cat(mailfile, maildir, my_name); 129579Sroot if (stat(mailfile, &statb) >= 0 130579Sroot && (statb.st_mode & S_IFMT) == S_IFDIR) { 131579Sroot strcat(mailfile, "/"); 132579Sroot strcat(mailfile, my_name); 133579Sroot } 134579Sroot for (; argc>1; argv++, argc--) { 135579Sroot if (argv[1][0]=='-') { 136579Sroot if (argv[1][1]=='q') 137579Sroot delflg = 0; 138579Sroot else if (argv[1][1]=='p') { 139579Sroot flgp++; 140579Sroot delflg = 0; 141579Sroot } else if (argv[1][1]=='f') { 142579Sroot if (argc>=3) { 143579Sroot strcpy(mailfile, argv[2]); 144579Sroot argv++; 145579Sroot argc--; 146579Sroot } 147579Sroot } else if (argv[1][1]=='r') { 148579Sroot forward = 1; 149579Sroot } else if (argv[1][1]=='h') { 150579Sroot forward = 1; 151579Sroot } else { 152579Sroot fprintf(stderr, "mail: unknown option %c\n", argv[1][1]); 153579Sroot done(); 154579Sroot } 155579Sroot } else 156579Sroot break; 157579Sroot } 158579Sroot malf = fopen(mailfile, "r"); 159579Sroot if (malf == NULL) { 160579Sroot fprintf(stdout, "No mail.\n"); 161579Sroot return; 162579Sroot } 163579Sroot lock(mailfile); 164579Sroot copymt(malf, tmpf); 165579Sroot fclose(malf); 166579Sroot fclose(tmpf); 167579Sroot unlock(); 168579Sroot tmpf = fopen(lettmp, "r"); 169579Sroot 170579Sroot changed = 0; 171579Sroot print = 1; 172579Sroot for (i = 0; i < nlet; ) { 173579Sroot j = forward ? i : nlet - i - 1; 174579Sroot if(setjmp(sjbuf)) { 175579Sroot 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); 186579Sroot fprintf(stdout, "? "); 187579Sroot fflush(stdout); 188579Sroot if (fgets(resp, LSIZE, stdin) == NULL) 189579Sroot break; 190579Sroot switch (resp[0]) { 191579Sroot 192579Sroot default: 193579Sroot fprintf(stderr, "usage\n"); 194579Sroot case '?': 195579Sroot print = 0; 196579Sroot fprintf(stderr, "q\tquit\n"); 197579Sroot fprintf(stderr, "x\texit without changing mail\n"); 198579Sroot fprintf(stderr, "p\tprint\n"); 199579Sroot fprintf(stderr, "s[file]\tsave (default mbox)\n"); 200579Sroot fprintf(stderr, "w[file]\tsame without header\n"); 201579Sroot fprintf(stderr, "-\tprint previous\n"); 202579Sroot fprintf(stderr, "d\tdelete\n"); 203579Sroot fprintf(stderr, "+\tnext (no delete)\n"); 204579Sroot fprintf(stderr, "m user\tmail to user\n"); 205579Sroot fprintf(stderr, "! 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"); 236579Sroot 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) { 244579Sroot fprintf(stdout, "mail: cannot append to %s\n", 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; ) 272579Sroot if (!sendrmt(j, lfil, "/bin/mail")) /* couldn't send it */ 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 301579Sroot copyback() /* copy temp or whatever back to /usr/spool/mail */ 302579Sroot { 303579Sroot register i, n, c; 304579Sroot int new = 0; 305579Sroot struct stat stbuf; 306579Sroot 307579Sroot signal(SIGINT, SIG_IGN); 308579Sroot signal(SIGHUP, SIG_IGN); 309579Sroot signal(SIGQUIT, SIG_IGN); 310579Sroot lock(mailfile); 311579Sroot stat(mailfile, &stbuf); 312579Sroot if (stbuf.st_size != let[nlet].adr) { /* new mail has arrived */ 313579Sroot malf = fopen(mailfile, "r"); 314579Sroot if (malf == NULL) { 315579Sroot fprintf(stdout, "mail: can't re-read %s\n", mailfile); 316579Sroot done(); 317579Sroot } 318579Sroot fseek(malf, let[nlet].adr, 0); 319579Sroot fclose(tmpf); 320579Sroot tmpf = fopen(lettmp, "a"); 321579Sroot fseek(tmpf, let[nlet].adr, 0); 322579Sroot while ((c = fgetc(malf)) != EOF) 323579Sroot fputc(c, tmpf); 324579Sroot fclose(malf); 325579Sroot fclose(tmpf); 326579Sroot tmpf = fopen(lettmp, "r"); 327579Sroot let[++nlet].adr = stbuf.st_size; 328579Sroot new = 1; 329579Sroot } 330579Sroot malf = fopen(mailfile, "w"); 331579Sroot if (malf == NULL) { 332579Sroot fprintf(stderr, "mail: can't rewrite %s\n", lfil); 333579Sroot done(); 334579Sroot } 335579Sroot n = 0; 336579Sroot for (i = 0; i < nlet; i++) 337579Sroot if (let[i].change != 'd') { 338579Sroot copylet(i, malf, ORDINARY); 339579Sroot n++; 340579Sroot } 341579Sroot fclose(malf); 342579Sroot if (new) 343579Sroot fprintf(stdout, "new mail arrived\n"); 344579Sroot unlock(); 345579Sroot } 346579Sroot 347579Sroot copymt(f1, f2) /* copy mail (f1) to temp (f2) */ 348579Sroot FILE *f1, *f2; 349579Sroot { 350579Sroot long nextadr; 351579Sroot 352579Sroot nlet = nextadr = 0; 353579Sroot let[0].adr = 0; 354579Sroot while (fgets(line, LSIZE, f1) != NULL) { 355579Sroot if (isfrom(line)) 356579Sroot let[nlet++].adr = nextadr; 357579Sroot nextadr += strlen(line); 358579Sroot fputs(line, f2); 359579Sroot } 360579Sroot let[nlet].adr = nextadr; /* last plus 1 */ 361579Sroot } 362579Sroot 36311893Seric copylet(n, f, type) 36411893Seric FILE *f; 36511893Seric { 36611893Seric int ch; 36711893Seric long k; 36811893Seric 369579Sroot fseek(tmpf, let[n].adr, 0); 370579Sroot k = let[n+1].adr - let[n].adr; 371579Sroot while(k-- > 1 && (ch=fgetc(tmpf))!='\n') 372579Sroot if(type!=ZAP) fputc(ch,f); 3736199Sroot if(type==REMOTE) { 3746199Sroot char hostname[32]; 3756199Sroot gethostname(hostname, sizeof (hostname)); 3766199Sroot fprintf(f, " remote from %s\n", hostname); 3776199Sroot } else if (type==FORWARD) 378579Sroot fprintf(f, forwmsg); 379579Sroot else if(type==ORDINARY) 380579Sroot fputc(ch,f); 381579Sroot while(k-->1) 382579Sroot fputc(ch=fgetc(tmpf), f); 383579Sroot if(type!=ZAP || ch!= '\n') 384579Sroot fputc(fgetc(tmpf), f); 385579Sroot } 386579Sroot 387579Sroot isfrom(lp) 388579Sroot register char *lp; 389579Sroot { 390579Sroot register char *p; 391579Sroot 392579Sroot for (p = from; *p; ) 393579Sroot if (*lp++ != *p++) 394579Sroot return(0); 395579Sroot return(1); 396579Sroot } 397579Sroot 3986015Swnj bulkmail(argc, argv) 399579Sroot char **argv; 400579Sroot { 401579Sroot char truename[100]; 402579Sroot int first; 403579Sroot register char *cp; 404579Sroot int gaver = 0; 405579Sroot char *newargv[1000]; 406579Sroot register char **ap; 407579Sroot register char **vp; 408579Sroot int dflag; 409579Sroot 410579Sroot dflag = 0; 411579Sroot if (argc < 1) 412579Sroot fprintf(stderr, "puke\n"); 413579Sroot for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++) 414579Sroot { 415579Sroot if (ap[0][0] == '-' && ap[0][1] == 'd') 416579Sroot dflag++; 417579Sroot } 418579Sroot if (!dflag) 419579Sroot { 4209978Seric /* give it to sendmail, rah rah! */ 421579Sroot unlink(lettmp); 422579Sroot ap = newargv+1; 423579Sroot if (rmail) 424579Sroot *ap-- = "-s"; 4259978Seric *ap = "-sendmail"; 4264461Sroot setuid(getuid()); 4279978Seric execv(SENDMAIL, ap); 4289978Seric perror(SENDMAIL); 429579Sroot exit(EX_UNAVAILABLE); 430579Sroot } 431579Sroot 432579Sroot truename[0] = 0; 433579Sroot line[0] = '\0'; 434579Sroot 435579Sroot /* 436579Sroot * When we fall out of this, argv[1] should be first name, 437579Sroot * argc should be number of names + 1. 438579Sroot */ 439579Sroot 440579Sroot while (argc > 1 && *argv[1] == '-') { 441579Sroot cp = *++argv; 442579Sroot argc--; 443579Sroot switch (cp[1]) { 444579Sroot case 'r': 445579Sroot if (argc <= 0) { 446579Sroot usage(); 447579Sroot done(); 448579Sroot } 449579Sroot gaver++; 450579Sroot strcpy(truename, argv[1]); 451579Sroot fgets(line, LSIZE, stdin); 452579Sroot if (strcmpn("From", line, 4) == 0) 453579Sroot line[0] = '\0'; 454579Sroot argv++; 455579Sroot argc--; 456579Sroot break; 457579Sroot 458579Sroot case 'h': 459579Sroot if (argc <= 0) { 460579Sroot usage(); 461579Sroot done(); 462579Sroot } 463579Sroot hseqno = atoi(argv[1]); 464579Sroot argv++; 465579Sroot argc--; 466579Sroot break; 467579Sroot 468579Sroot case 'd': 469579Sroot break; 470579Sroot 471579Sroot default: 472579Sroot usage(); 473579Sroot done(); 474579Sroot } 475579Sroot } 476579Sroot if (argc <= 1) { 477579Sroot usage(); 478579Sroot done(); 479579Sroot } 480579Sroot if (gaver == 0) 481579Sroot strcpy(truename, my_name); 482579Sroot /* 483579Sroot if (argc > 4 && strcmp(argv[1], "-r") == 0) { 484579Sroot strcpy(truename, argv[2]); 485579Sroot argc -= 2; 486579Sroot argv += 2; 487579Sroot fgets(line, LSIZE, stdin); 488579Sroot if (strcmpn("From", line, 4) == 0) 489579Sroot line[0] = '\0'; 490579Sroot } else 491579Sroot strcpy(truename, my_name); 492579Sroot */ 493579Sroot time(&iop); 494579Sroot fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop)); 495579Sroot iop = ftell(tmpf); 496579Sroot flgf = 1; 497579Sroot for (first = 1;; first = 0) { 498579Sroot if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL) 499579Sroot break; 500579Sroot if (!first && fgets(line, LSIZE, stdin) == NULL) 501579Sroot break; 502579Sroot if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin))) 503579Sroot break; 504579Sroot if (isfrom(line)) 505579Sroot fputs(">", tmpf); 506579Sroot fputs(line, tmpf); 507579Sroot flgf = 0; 508579Sroot } 509579Sroot fputs("\n", tmpf); 510579Sroot nlet = 1; 511579Sroot let[0].adr = 0; 512579Sroot let[1].adr = ftell(tmpf); 513579Sroot fclose(tmpf); 514579Sroot if (flgf) 515579Sroot return; 516579Sroot tmpf = fopen(lettmp, "r"); 517579Sroot if (tmpf == NULL) { 518579Sroot fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp); 519579Sroot return; 520579Sroot } 5216015Swnj while (--argc > 0) { 5226015Swnj if (!sendmail(0, *++argv, truename)) 523579Sroot error++; 5246015Swnj } 52510644Seric if (error && safefile(dead)) { 526579Sroot setuid(getuid()); 527579Sroot malf = fopen(dead, "w"); 528579Sroot if (malf == NULL) { 529579Sroot fprintf(stdout, "mail: cannot open %s\n", dead); 530579Sroot fclose(tmpf); 531579Sroot return; 532579Sroot } 533579Sroot copylet(0, malf, ZAP); 534579Sroot fclose(malf); 535579Sroot fprintf(stdout, "Mail saved in %s\n", dead); 536579Sroot } 537579Sroot fclose(tmpf); 538579Sroot } 539579Sroot 540579Sroot sendrmt(n, name, rcmd) 541579Sroot char *name; 542579Sroot char *rcmd; 543579Sroot { 544579Sroot FILE *rmf, *popen(); 545579Sroot register char *p; 546579Sroot char rsys[64], cmd[64]; 547579Sroot register local, pid; 548579Sroot int sts; 549579Sroot 550579Sroot local = 0; 551579Sroot if (index(name, '^')) { 552579Sroot while (p = index(name, '^')) 553579Sroot *p = '!'; 554579Sroot if (strncmp(name, "researc", 7)) { 555579Sroot strcpy(rsys, "research"); 556579Sroot if (*name != '!') 557579Sroot --name; 558579Sroot goto skip; 559579Sroot } 560579Sroot } 561579Sroot if (*name=='!') 562579Sroot name++; 563579Sroot for(p=rsys; *name!='!'; *p++ = *name++) 564579Sroot if (*name=='\0') { 565579Sroot local++; 566579Sroot break; 567579Sroot } 568579Sroot *p = '\0'; 569579Sroot if ((!local && *name=='\0') || (local && *rsys=='\0')) { 570579Sroot fprintf(stdout, "null name\n"); 571579Sroot return(0); 572579Sroot } 573579Sroot skip: 574579Sroot if ((pid = fork()) == -1) { 575579Sroot fprintf(stderr, "mail: can't create proc for remote\n"); 576579Sroot return(0); 577579Sroot } 578579Sroot if (pid) { 579579Sroot while (wait(&sts) != pid) { 580579Sroot if (wait(&sts)==-1) 581579Sroot return(0); 582579Sroot } 583579Sroot return(!sts); 584579Sroot } 585579Sroot setuid(getuid()); 586579Sroot if (local) 587579Sroot sprintf(cmd, "%s %s", rcmd, rsys); 588579Sroot else { 589579Sroot if (index(name+1, '!')) 590579Sroot sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); 591579Sroot else 592579Sroot sprintf(cmd, "uux - %s!rmail %s", rsys, name+1); 593579Sroot } 594579Sroot if ((rmf=popen(cmd, "w")) == NULL) 595579Sroot exit(1); 596579Sroot copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE); 59710783Seric exit(pclose(rmf) != 0); 598579Sroot } 599579Sroot 600579Sroot usage() 601579Sroot { 602579Sroot 603579Sroot fprintf(stderr, "Usage: mail [ -f ] people . . .\n"); 604579Sroot } 605579Sroot 6066015Swnj #include <sys/socket.h> 6079226Ssam #include <netinet/in.h> 60810227Ssam #include <netdb.h> 60910227Ssam struct sockaddr_in biffaddr; 6106015Swnj 6116015Swnj sendmail(n, name, fromaddr) 612579Sroot int n; 613579Sroot char *name; 614579Sroot char *fromaddr; 615579Sroot { 616579Sroot char file[100]; 617579Sroot register char *p; 618579Sroot register mask; 619579Sroot struct passwd *pw, *getpwnam(); 620579Sroot struct stat statb; 6213666Swnj char buf[128]; 6223666Swnj int f; 62310227Ssam struct hostent *hp = NULL; 62410227Ssam struct servent *sp = NULL; 625579Sroot 626579Sroot for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++) 627579Sroot ; 628579Sroot if (*p == '!'|| *p=='^') 629579Sroot return(sendrmt(n, name, 0)); 630579Sroot if ((pw = getpwnam(name)) == NULL) { 631579Sroot fprintf(stdout, "mail: can't send to %s\n", name); 632579Sroot return(0); 633579Sroot } 634579Sroot cat(file, maildir, name); 635579Sroot if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { 636579Sroot strcat(file, "/"); 637579Sroot strcat(file, name); 638579Sroot } 639579Sroot mask = umask(MAILMODE); 64010644Seric if (!safefile(file)) 6414458Sroot return(0); 64211893Seric lock(file); 643579Sroot malf = fopen(file, "a"); 644579Sroot umask(mask); 645579Sroot if (malf == NULL) { 64611893Seric unlock(); 647579Sroot fprintf(stdout, "mail: cannot append to %s\n", file); 648579Sroot return(0); 649579Sroot } 6506015Swnj chown(file, pw->pw_uid, pw->pw_gid); 6513666Swnj { 65210227Ssam hp = gethostbyname("localhost"); 65310227Ssam sp = getservbyname("biff", "udp"); 65410227Ssam if (hp && sp) { 65510227Ssam f = socket(AF_INET, SOCK_DGRAM, 0, 0); 65610227Ssam sprintf(buf, "%s@%d\n", name, ftell(malf)); 65710227Ssam } 6583666Swnj } 659579Sroot copylet(n, malf, ORDINARY); 6606015Swnj fclose(malf); 66110227Ssam if (hp && sp) { 66210227Ssam biffaddr.sin_family = hp->h_addrtype; 66310227Ssam bcopy(hp->h_addr, &biffaddr.sin_addr, hp->h_length); 66410227Ssam biffaddr.sin_port = sp->s_port; 6659226Ssam sendto(f, buf, strlen(buf)+1, 0, &biffaddr, sizeof (biffaddr)); 6663666Swnj close(f); 6673666Swnj } 668579Sroot unlock(); 669579Sroot return(1); 670579Sroot } 671579Sroot 672579Sroot delete(i) 673579Sroot { 674579Sroot setsig(i, delete); 675579Sroot fprintf(stderr, "\n"); 676579Sroot if(delflg) 677579Sroot longjmp(sjbuf, 1); 678579Sroot done(); 679579Sroot } 680579Sroot 681579Sroot /* 682579Sroot * Lock the specified mail file by setting the file mailfile.lock. 683579Sroot * We must, of course, be careful to unlink the lock file by a call 684579Sroot * to unlock before we stop. The algorithm used here is to see if 685579Sroot * the lock exists, and if it does, to check its modify time. If it 686579Sroot * is older than 30 seconds, we assume error and set our own file. 687579Sroot * Otherwise, we wait for 5 seconds and try again. 688579Sroot */ 689579Sroot 690579Sroot char *maillock = ".lock"; /* Lock suffix for mailname */ 691579Sroot char *lockname = "/usr/spool/mail/tmXXXXXX"; 692579Sroot char locktmp[30]; /* Usable lock temporary */ 693579Sroot char curlock[50]; /* Last used name of lock */ 694579Sroot int locked; /* To note that we locked it */ 695579Sroot 696579Sroot lock(file) 697579Sroot char *file; 698579Sroot { 699579Sroot register int f; 700579Sroot struct stat sbuf; 701579Sroot long curtime; 702579Sroot int statfailed; 703579Sroot 704579Sroot if (locked || flgf) 705579Sroot return(0); 706579Sroot strcpy(curlock, file); 707579Sroot strcat(curlock, maillock); 708579Sroot strcpy(locktmp, lockname); 709579Sroot mktemp(locktmp); 710579Sroot unlink(locktmp); 711579Sroot statfailed = 0; 712579Sroot for (;;) { 713579Sroot f = lock1(locktmp, curlock); 714579Sroot if (f == 0) { 715579Sroot locked = 1; 716579Sroot return(0); 717579Sroot } 718579Sroot if (stat(curlock, &sbuf) < 0) { 719579Sroot if (statfailed++ > 5) 720579Sroot return(-1); 721579Sroot sleep(5); 722579Sroot continue; 723579Sroot } 724579Sroot statfailed = 0; 725579Sroot time(&curtime); 726579Sroot if (curtime < sbuf.st_ctime + 30) { 727579Sroot sleep(5); 728579Sroot continue; 729579Sroot } 730579Sroot unlink(curlock); 731579Sroot } 732579Sroot } 733579Sroot 734579Sroot /* 735579Sroot * Remove the mail lock, and note that we no longer 736579Sroot * have it locked. 737579Sroot */ 738579Sroot 739579Sroot unlock() 740579Sroot { 741579Sroot 742579Sroot unlink(curlock); 743579Sroot locked = 0; 744579Sroot } 745579Sroot 746579Sroot /* 747579Sroot * Attempt to set the lock by creating the temporary file, 748579Sroot * then doing a link/unlink. If it fails, return -1 else 0 749579Sroot */ 750579Sroot 751579Sroot lock1(tempfile, name) 752579Sroot char tempfile[], name[]; 753579Sroot { 754579Sroot register int fd; 755579Sroot 756579Sroot fd = creat(tempfile, 0); 757579Sroot if (fd < 0) 758579Sroot return(-1); 759579Sroot close(fd); 760579Sroot if (link(tempfile, name) < 0) { 761579Sroot unlink(tempfile); 762579Sroot return(-1); 763579Sroot } 764579Sroot unlink(tempfile); 765579Sroot return(0); 766579Sroot } 767579Sroot 768579Sroot done() 769579Sroot { 770579Sroot if(locked) 771579Sroot unlock(); 772579Sroot unlink(lettmp); 773579Sroot unlink(locktmp); 774579Sroot exit(error); 775579Sroot } 776579Sroot 777579Sroot cat(to, from1, from2) 778579Sroot char *to, *from1, *from2; 779579Sroot { 780579Sroot int i, j; 781579Sroot 782579Sroot j = 0; 783579Sroot for (i=0; from1[i]; i++) 784579Sroot to[j++] = from1[i]; 785579Sroot for (i=0; from2[i]; i++) 786579Sroot to[j++] = from2[i]; 787579Sroot to[j] = 0; 788579Sroot } 789579Sroot 790579Sroot char *getarg(s, p) /* copy p... into s, update p */ 791579Sroot register char *s, *p; 792579Sroot { 793579Sroot while (*p == ' ' || *p == '\t') 794579Sroot p++; 795579Sroot if (*p == '\n' || *p == '\0') 796579Sroot return(NULL); 797579Sroot while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 798579Sroot *s++ = *p++; 799579Sroot *s = '\0'; 800579Sroot return(p); 801579Sroot } 80210644Seric 80310644Seric safefile(f) 80410644Seric char *f; 80510644Seric { 80610644Seric struct stat statb; 80710644Seric 80810644Seric if (lstat(f, &statb) < 0) 80910644Seric return (1); 81010644Seric if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) { 81110644Seric fprintf(stderr, "mail: %s has more than one link or is a symbolic link\n", f); 81210644Seric return (0); 81310644Seric } 81410644Seric return (1); 81510644Seric } 816