114465Ssam #ifndef lint 2*15299Skarels static char sccsid[] = "@(#)mail.local.c 4.20 (Berkeley) 10/27/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(); 8414912Sralph 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 } 44915288Seric if (strcmp(my_name, "root") == 0 || 45015288Seric strcmp(my_name, "daemon") == 0 || 45115288Seric strcmp(my_name, "network") == 0 || 45215288Seric strcmp(my_name, "uucp")) { 45315288Seric gaver++; 45415288Seric strcpy(truename, argv[1]); 45515288Seric fgets(line, LSIZE, stdin); 45615288Seric if (strncmp("From", line, 4) == 0) 45715288Seric line[0] = '\0'; 45814934Sralph } 459579Sroot argv++; 460579Sroot argc--; 461579Sroot break; 462579Sroot 463579Sroot case 'h': 464579Sroot if (argc <= 0) { 465579Sroot usage(); 466579Sroot done(); 467579Sroot } 468579Sroot hseqno = atoi(argv[1]); 469579Sroot argv++; 470579Sroot argc--; 471579Sroot break; 472579Sroot 473579Sroot case 'd': 474579Sroot break; 475579Sroot 476579Sroot default: 477579Sroot usage(); 478579Sroot done(); 479579Sroot } 480579Sroot } 481579Sroot if (argc <= 1) { 482579Sroot usage(); 483579Sroot done(); 484579Sroot } 485579Sroot if (gaver == 0) 486579Sroot strcpy(truename, my_name); 487579Sroot /* 488579Sroot if (argc > 4 && strcmp(argv[1], "-r") == 0) { 489579Sroot strcpy(truename, argv[2]); 490579Sroot argc -= 2; 491579Sroot argv += 2; 492579Sroot fgets(line, LSIZE, stdin); 49315288Seric if (strncmp("From", line, 4) == 0) 494579Sroot line[0] = '\0'; 495579Sroot } else 496579Sroot strcpy(truename, my_name); 497579Sroot */ 498579Sroot time(&iop); 499579Sroot fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop)); 500579Sroot iop = ftell(tmpf); 501579Sroot flgf = 1; 502579Sroot for (first = 1;; first = 0) { 503579Sroot if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL) 504579Sroot break; 505579Sroot if (!first && fgets(line, LSIZE, stdin) == NULL) 506579Sroot break; 507579Sroot if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin))) 508579Sroot break; 509579Sroot if (isfrom(line)) 510579Sroot fputs(">", tmpf); 511579Sroot fputs(line, tmpf); 512579Sroot flgf = 0; 513579Sroot } 514579Sroot fputs("\n", tmpf); 515579Sroot nlet = 1; 516579Sroot let[0].adr = 0; 517579Sroot let[1].adr = ftell(tmpf); 518579Sroot fclose(tmpf); 519579Sroot if (flgf) 520579Sroot return; 521579Sroot tmpf = fopen(lettmp, "r"); 522579Sroot if (tmpf == NULL) { 523579Sroot fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp); 524579Sroot return; 525579Sroot } 5266015Swnj while (--argc > 0) { 5276015Swnj if (!sendmail(0, *++argv, truename)) 528579Sroot error++; 5296015Swnj } 53010644Seric if (error && safefile(dead)) { 531579Sroot setuid(getuid()); 532579Sroot malf = fopen(dead, "w"); 533579Sroot if (malf == NULL) { 534579Sroot fprintf(stdout, "mail: cannot open %s\n", dead); 535579Sroot fclose(tmpf); 536579Sroot return; 537579Sroot } 538579Sroot copylet(0, malf, ZAP); 539579Sroot fclose(malf); 540579Sroot fprintf(stdout, "Mail saved in %s\n", dead); 541579Sroot } 542579Sroot fclose(tmpf); 543579Sroot } 544579Sroot 545579Sroot sendrmt(n, name, rcmd) 546579Sroot char *name; 547579Sroot char *rcmd; 548579Sroot { 549579Sroot FILE *rmf, *popen(); 550579Sroot register char *p; 551579Sroot char rsys[64], cmd[64]; 552579Sroot register local, pid; 553579Sroot int sts; 554579Sroot 555579Sroot local = 0; 556579Sroot if (index(name, '^')) { 557579Sroot while (p = index(name, '^')) 558579Sroot *p = '!'; 559579Sroot if (strncmp(name, "researc", 7)) { 560579Sroot strcpy(rsys, "research"); 561579Sroot if (*name != '!') 562579Sroot --name; 563579Sroot goto skip; 564579Sroot } 565579Sroot } 566579Sroot if (*name=='!') 567579Sroot name++; 568579Sroot for(p=rsys; *name!='!'; *p++ = *name++) 569579Sroot if (*name=='\0') { 570579Sroot local++; 571579Sroot break; 572579Sroot } 573579Sroot *p = '\0'; 574579Sroot if ((!local && *name=='\0') || (local && *rsys=='\0')) { 575579Sroot fprintf(stdout, "null name\n"); 576579Sroot return(0); 577579Sroot } 578579Sroot skip: 579579Sroot if ((pid = fork()) == -1) { 580579Sroot fprintf(stderr, "mail: can't create proc for remote\n"); 581579Sroot return(0); 582579Sroot } 583579Sroot if (pid) { 584579Sroot while (wait(&sts) != pid) { 585579Sroot if (wait(&sts)==-1) 586579Sroot return(0); 587579Sroot } 588579Sroot return(!sts); 589579Sroot } 590579Sroot setuid(getuid()); 591579Sroot if (local) 592579Sroot sprintf(cmd, "%s %s", rcmd, rsys); 593579Sroot else { 594579Sroot if (index(name+1, '!')) 595579Sroot sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); 596579Sroot else 597579Sroot sprintf(cmd, "uux - %s!rmail %s", rsys, name+1); 598579Sroot } 599579Sroot if ((rmf=popen(cmd, "w")) == NULL) 600579Sroot exit(1); 601579Sroot copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE); 60210783Seric exit(pclose(rmf) != 0); 603579Sroot } 604579Sroot 605579Sroot usage() 606579Sroot { 607579Sroot 608579Sroot fprintf(stderr, "Usage: mail [ -f ] people . . .\n"); 609*15299Skarels error = EX_USAGE; 610579Sroot } 611579Sroot 6126015Swnj #include <sys/socket.h> 6139226Ssam #include <netinet/in.h> 61410227Ssam #include <netdb.h> 61510227Ssam struct sockaddr_in biffaddr; 6166015Swnj 6176015Swnj sendmail(n, name, fromaddr) 618579Sroot int n; 619579Sroot char *name; 620579Sroot char *fromaddr; 621579Sroot { 622579Sroot char file[100]; 623579Sroot register char *p; 624579Sroot register mask; 625579Sroot struct passwd *pw, *getpwnam(); 626579Sroot struct stat statb; 6273666Swnj char buf[128]; 6283666Swnj int f; 62910227Ssam struct hostent *hp = NULL; 63010227Ssam struct servent *sp = NULL; 631579Sroot 632579Sroot for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++) 633579Sroot ; 634579Sroot if (*p == '!'|| *p=='^') 635579Sroot return(sendrmt(n, name, 0)); 636579Sroot if ((pw = getpwnam(name)) == NULL) { 637579Sroot fprintf(stdout, "mail: can't send to %s\n", name); 638579Sroot return(0); 639579Sroot } 640579Sroot cat(file, maildir, name); 641579Sroot if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { 642579Sroot strcat(file, "/"); 643579Sroot strcat(file, name); 644579Sroot } 645579Sroot mask = umask(MAILMODE); 64610644Seric if (!safefile(file)) 6474458Sroot return(0); 64811893Seric lock(file); 649579Sroot malf = fopen(file, "a"); 650579Sroot umask(mask); 651579Sroot if (malf == NULL) { 65211893Seric unlock(); 653579Sroot fprintf(stdout, "mail: cannot append to %s\n", file); 654579Sroot return(0); 655579Sroot } 6566015Swnj chown(file, pw->pw_uid, pw->pw_gid); 6573666Swnj { 65810227Ssam hp = gethostbyname("localhost"); 65910227Ssam sp = getservbyname("biff", "udp"); 66010227Ssam if (hp && sp) { 66110227Ssam f = socket(AF_INET, SOCK_DGRAM, 0, 0); 66210227Ssam sprintf(buf, "%s@%d\n", name, ftell(malf)); 66310227Ssam } 6643666Swnj } 665579Sroot copylet(n, malf, ORDINARY); 6666015Swnj fclose(malf); 66710227Ssam if (hp && sp) { 66810227Ssam biffaddr.sin_family = hp->h_addrtype; 66910227Ssam bcopy(hp->h_addr, &biffaddr.sin_addr, hp->h_length); 67010227Ssam biffaddr.sin_port = sp->s_port; 6719226Ssam sendto(f, buf, strlen(buf)+1, 0, &biffaddr, sizeof (biffaddr)); 6723666Swnj close(f); 6733666Swnj } 674579Sroot unlock(); 675579Sroot return(1); 676579Sroot } 677579Sroot 678579Sroot delete(i) 679579Sroot { 680579Sroot setsig(i, delete); 681579Sroot fprintf(stderr, "\n"); 682579Sroot if(delflg) 683579Sroot longjmp(sjbuf, 1); 684579Sroot done(); 685579Sroot } 686579Sroot 687579Sroot /* 688579Sroot * Lock the specified mail file by setting the file mailfile.lock. 689579Sroot * We must, of course, be careful to unlink the lock file by a call 690579Sroot * to unlock before we stop. The algorithm used here is to see if 691579Sroot * the lock exists, and if it does, to check its modify time. If it 692579Sroot * is older than 30 seconds, we assume error and set our own file. 693579Sroot * Otherwise, we wait for 5 seconds and try again. 694579Sroot */ 695579Sroot 696579Sroot char *maillock = ".lock"; /* Lock suffix for mailname */ 697579Sroot char *lockname = "/usr/spool/mail/tmXXXXXX"; 698579Sroot char locktmp[30]; /* Usable lock temporary */ 699579Sroot char curlock[50]; /* Last used name of lock */ 700579Sroot int locked; /* To note that we locked it */ 701579Sroot 702579Sroot lock(file) 703579Sroot char *file; 704579Sroot { 705579Sroot register int f; 706579Sroot struct stat sbuf; 707579Sroot long curtime; 708579Sroot int statfailed; 709579Sroot 710579Sroot if (locked || flgf) 711579Sroot return(0); 712579Sroot strcpy(curlock, file); 713579Sroot strcat(curlock, maillock); 714579Sroot strcpy(locktmp, lockname); 715579Sroot mktemp(locktmp); 716579Sroot unlink(locktmp); 717579Sroot statfailed = 0; 718579Sroot for (;;) { 719579Sroot f = lock1(locktmp, curlock); 720579Sroot if (f == 0) { 721579Sroot locked = 1; 722579Sroot return(0); 723579Sroot } 724579Sroot if (stat(curlock, &sbuf) < 0) { 725579Sroot if (statfailed++ > 5) 726579Sroot return(-1); 727579Sroot sleep(5); 728579Sroot continue; 729579Sroot } 730579Sroot statfailed = 0; 731579Sroot time(&curtime); 732579Sroot if (curtime < sbuf.st_ctime + 30) { 733579Sroot sleep(5); 734579Sroot continue; 735579Sroot } 736579Sroot unlink(curlock); 737579Sroot } 738579Sroot } 739579Sroot 740579Sroot /* 741579Sroot * Remove the mail lock, and note that we no longer 742579Sroot * have it locked. 743579Sroot */ 744579Sroot 745579Sroot unlock() 746579Sroot { 747579Sroot 748579Sroot unlink(curlock); 749579Sroot locked = 0; 750579Sroot } 751579Sroot 752579Sroot /* 753579Sroot * Attempt to set the lock by creating the temporary file, 754579Sroot * then doing a link/unlink. If it fails, return -1 else 0 755579Sroot */ 756579Sroot 757579Sroot lock1(tempfile, name) 758579Sroot char tempfile[], name[]; 759579Sroot { 760579Sroot register int fd; 761579Sroot 762579Sroot fd = creat(tempfile, 0); 763579Sroot if (fd < 0) 764579Sroot return(-1); 765579Sroot close(fd); 766579Sroot if (link(tempfile, name) < 0) { 767579Sroot unlink(tempfile); 768579Sroot return(-1); 769579Sroot } 770579Sroot unlink(tempfile); 771579Sroot return(0); 772579Sroot } 773579Sroot 774579Sroot done() 775579Sroot { 776579Sroot if(locked) 777579Sroot unlock(); 778579Sroot unlink(lettmp); 779579Sroot unlink(locktmp); 780579Sroot exit(error); 781579Sroot } 782579Sroot 783579Sroot cat(to, from1, from2) 784579Sroot char *to, *from1, *from2; 785579Sroot { 786579Sroot int i, j; 787579Sroot 788579Sroot j = 0; 789579Sroot for (i=0; from1[i]; i++) 790579Sroot to[j++] = from1[i]; 791579Sroot for (i=0; from2[i]; i++) 792579Sroot to[j++] = from2[i]; 793579Sroot to[j] = 0; 794579Sroot } 795579Sroot 796579Sroot char *getarg(s, p) /* copy p... into s, update p */ 797579Sroot register char *s, *p; 798579Sroot { 799579Sroot while (*p == ' ' || *p == '\t') 800579Sroot p++; 801579Sroot if (*p == '\n' || *p == '\0') 802579Sroot return(NULL); 803579Sroot while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 804579Sroot *s++ = *p++; 805579Sroot *s = '\0'; 806579Sroot return(p); 807579Sroot } 80810644Seric 80910644Seric safefile(f) 81010644Seric char *f; 81110644Seric { 81210644Seric struct stat statb; 81310644Seric 81410644Seric if (lstat(f, &statb) < 0) 81510644Seric return (1); 81610644Seric if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) { 81710644Seric fprintf(stderr, "mail: %s has more than one link or is a symbolic link\n", f); 81810644Seric return (0); 81910644Seric } 82010644Seric return (1); 82110644Seric } 822