114465Ssam #ifndef lint 2*14934Sralph static char sccsid[] = "@(#)mail.local.c 4.18 (Berkeley) 09/09/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 } 449*14934Sralph if (strcmp(my_name, "root") && 450*14934Sralph strcmp(my_name, "daemon") && 451*14934Sralph strcmp(my_name, "network")) { 452*14934Sralph usage(); 453*14934Sralph done(); 454*14934Sralph } 455579Sroot gaver++; 456579Sroot strcpy(truename, argv[1]); 457579Sroot fgets(line, LSIZE, stdin); 458579Sroot if (strcmpn("From", line, 4) == 0) 459579Sroot line[0] = '\0'; 460579Sroot argv++; 461579Sroot argc--; 462579Sroot break; 463579Sroot 464579Sroot case 'h': 465579Sroot if (argc <= 0) { 466579Sroot usage(); 467579Sroot done(); 468579Sroot } 469579Sroot hseqno = atoi(argv[1]); 470579Sroot argv++; 471579Sroot argc--; 472579Sroot break; 473579Sroot 474579Sroot case 'd': 475579Sroot break; 476579Sroot 477579Sroot default: 478579Sroot usage(); 479579Sroot done(); 480579Sroot } 481579Sroot } 482579Sroot if (argc <= 1) { 483579Sroot usage(); 484579Sroot done(); 485579Sroot } 486579Sroot if (gaver == 0) 487579Sroot strcpy(truename, my_name); 488579Sroot /* 489579Sroot if (argc > 4 && strcmp(argv[1], "-r") == 0) { 490579Sroot strcpy(truename, argv[2]); 491579Sroot argc -= 2; 492579Sroot argv += 2; 493579Sroot fgets(line, LSIZE, stdin); 494579Sroot if (strcmpn("From", line, 4) == 0) 495579Sroot line[0] = '\0'; 496579Sroot } else 497579Sroot strcpy(truename, my_name); 498579Sroot */ 499579Sroot time(&iop); 500579Sroot fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop)); 501579Sroot iop = ftell(tmpf); 502579Sroot flgf = 1; 503579Sroot for (first = 1;; first = 0) { 504579Sroot if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL) 505579Sroot break; 506579Sroot if (!first && fgets(line, LSIZE, stdin) == NULL) 507579Sroot break; 508579Sroot if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin))) 509579Sroot break; 510579Sroot if (isfrom(line)) 511579Sroot fputs(">", tmpf); 512579Sroot fputs(line, tmpf); 513579Sroot flgf = 0; 514579Sroot } 515579Sroot fputs("\n", tmpf); 516579Sroot nlet = 1; 517579Sroot let[0].adr = 0; 518579Sroot let[1].adr = ftell(tmpf); 519579Sroot fclose(tmpf); 520579Sroot if (flgf) 521579Sroot return; 522579Sroot tmpf = fopen(lettmp, "r"); 523579Sroot if (tmpf == NULL) { 524579Sroot fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp); 525579Sroot return; 526579Sroot } 5276015Swnj while (--argc > 0) { 5286015Swnj if (!sendmail(0, *++argv, truename)) 529579Sroot error++; 5306015Swnj } 53110644Seric if (error && safefile(dead)) { 532579Sroot setuid(getuid()); 533579Sroot malf = fopen(dead, "w"); 534579Sroot if (malf == NULL) { 535579Sroot fprintf(stdout, "mail: cannot open %s\n", dead); 536579Sroot fclose(tmpf); 537579Sroot return; 538579Sroot } 539579Sroot copylet(0, malf, ZAP); 540579Sroot fclose(malf); 541579Sroot fprintf(stdout, "Mail saved in %s\n", dead); 542579Sroot } 543579Sroot fclose(tmpf); 544579Sroot } 545579Sroot 546579Sroot sendrmt(n, name, rcmd) 547579Sroot char *name; 548579Sroot char *rcmd; 549579Sroot { 550579Sroot FILE *rmf, *popen(); 551579Sroot register char *p; 552579Sroot char rsys[64], cmd[64]; 553579Sroot register local, pid; 554579Sroot int sts; 555579Sroot 556579Sroot local = 0; 557579Sroot if (index(name, '^')) { 558579Sroot while (p = index(name, '^')) 559579Sroot *p = '!'; 560579Sroot if (strncmp(name, "researc", 7)) { 561579Sroot strcpy(rsys, "research"); 562579Sroot if (*name != '!') 563579Sroot --name; 564579Sroot goto skip; 565579Sroot } 566579Sroot } 567579Sroot if (*name=='!') 568579Sroot name++; 569579Sroot for(p=rsys; *name!='!'; *p++ = *name++) 570579Sroot if (*name=='\0') { 571579Sroot local++; 572579Sroot break; 573579Sroot } 574579Sroot *p = '\0'; 575579Sroot if ((!local && *name=='\0') || (local && *rsys=='\0')) { 576579Sroot fprintf(stdout, "null name\n"); 577579Sroot return(0); 578579Sroot } 579579Sroot skip: 580579Sroot if ((pid = fork()) == -1) { 581579Sroot fprintf(stderr, "mail: can't create proc for remote\n"); 582579Sroot return(0); 583579Sroot } 584579Sroot if (pid) { 585579Sroot while (wait(&sts) != pid) { 586579Sroot if (wait(&sts)==-1) 587579Sroot return(0); 588579Sroot } 589579Sroot return(!sts); 590579Sroot } 591579Sroot setuid(getuid()); 592579Sroot if (local) 593579Sroot sprintf(cmd, "%s %s", rcmd, rsys); 594579Sroot else { 595579Sroot if (index(name+1, '!')) 596579Sroot sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); 597579Sroot else 598579Sroot sprintf(cmd, "uux - %s!rmail %s", rsys, name+1); 599579Sroot } 600579Sroot if ((rmf=popen(cmd, "w")) == NULL) 601579Sroot exit(1); 602579Sroot copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE); 60310783Seric exit(pclose(rmf) != 0); 604579Sroot } 605579Sroot 606579Sroot usage() 607579Sroot { 608579Sroot 609579Sroot fprintf(stderr, "Usage: mail [ -f ] people . . .\n"); 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