1*8208Smckusick static char sccsid[] = "@(#)v6mail.c 4.1 (Berkeley) 09/12/82"; 2*8208Smckusick 3*8208Smckusick /* 4*8208Smckusick * Version 6 Cory mail-- 5*8208Smckusick * a clean and simple mail program 6*8208Smckusick * machine and version independent 7*8208Smckusick * Eric Schmidt 8*8208Smckusick * must run as setuid root to chown the destination mailbox 9*8208Smckusick * if NOTROOT defined, doesn't need to run as root 10*8208Smckusick * 11*8208Smckusick * DON'T CHANGE THIS CODE 12*8208Smckusick * bitch to "csvax:schmidt" instead 13*8208Smckusick */ 14*8208Smckusick 15*8208Smckusick /* 16*8208Smckusick * mail command usage 17*8208Smckusick * mail [-yn] 18*8208Smckusick * prints your mail 19*8208Smckusick * mail people 20*8208Smckusick * sends standard input to people 21*8208Smckusick * 22*8208Smckusick * mail -r fromaddr people 23*8208Smckusick * sends mail from the network 24*8208Smckusick * 25*8208Smckusick * mail -d people 26*8208Smckusick * don't call delivermail, send mail directly 27*8208Smckusick * mail msgs 28*8208Smckusick * send to "msgs" 29*8208Smckusick * mail filename 30*8208Smckusick * mail to filename instead of user (must be at least one /) 31*8208Smckusick * mail -D 32*8208Smckusick * delete the invokers mailbox (more efficient than 33*8208Smckusick * mail -n >/dev/null) 34*8208Smckusick */ 35*8208Smckusick 36*8208Smckusick /* 37*8208Smckusick * bugs: 38*8208Smckusick * Ingres 11/70 multiple names/uid? 39*8208Smckusick * additions: 40*8208Smckusick * Save? type 'x' - doesn't unlink the mail file 41*8208Smckusick */ 42*8208Smckusick /* 43*8208Smckusick * BIFF is an immediate notification flag using the MPX stuff 44*8208Smckusick */ 45*8208Smckusick # include "local.h" 46*8208Smckusick # include <stdio.h> 47*8208Smckusick # include "mach.h" 48*8208Smckusick 49*8208Smckusick # ifdef RAND 50*8208Smckusick 51*8208Smckusick /* for all machines at RAND */ 52*8208Smckusick # define MAILMODE 0644 53*8208Smckusick 54*8208Smckusick # endif RAND 55*8208Smckusick 56*8208Smckusick # ifdef NOSC 57*8208Smckusick 58*8208Smckusick /* for all machines at NOSC */ 59*8208Smckusick # define MAILMODE 0644 60*8208Smckusick 61*8208Smckusick # endif NOSC 62*8208Smckusick 63*8208Smckusick # ifdef BERKELEY 64*8208Smckusick /* for Berkeley */ 65*8208Smckusick /* for each machine */ 66*8208Smckusick /* lump the CC machines into one */ 67*8208Smckusick # ifdef CCV7 68*8208Smckusick # define MAILMODE 0600 69*8208Smckusick # define MSGSCMD "/usr/ucb/bin/msgs" 70*8208Smckusick # endif 71*8208Smckusick 72*8208Smckusick # ifdef CCV6 73*8208Smckusick # define MSGSCMD "/usr/bin/eecs/msgs" 74*8208Smckusick # define MAILMODE 0600 75*8208Smckusick # endif 76*8208Smckusick 77*8208Smckusick # ifdef ING70 78*8208Smckusick # define MAILMODE 0666 79*8208Smckusick # define MSGSCMD "/usr/bin/msgs" 80*8208Smckusick # define NOTROOT 81*8208Smckusick # endif 82*8208Smckusick 83*8208Smckusick # ifdef INGVAX 84*8208Smckusick # define MAILMODE 0644 85*8208Smckusick # define MSGSCMD "/usr/ucb/msgs" 86*8208Smckusick # endif 87*8208Smckusick 88*8208Smckusick /* 89*8208Smckusick # ifdef VIRUS 90*8208Smckusick # define MAILMODE 0644 91*8208Smckusick # define MSGSCMD "/usr/bin/msgs" 92*8208Smckusick # endif 93*8208Smckusick */ 94*8208Smckusick 95*8208Smckusick # ifdef UCBVAX 96*8208Smckusick # define MAILMODE 0644 97*8208Smckusick # define MSGSCMD "/usr/ucb/msgs" 98*8208Smckusick # define BIFF 99*8208Smckusick # endif 100*8208Smckusick 101*8208Smckusick # ifdef IMAGE 102*8208Smckusick # define MAILMODE 0644 103*8208Smckusick # define MSGSCMD "/usr/bin/msgs" 104*8208Smckusick # endif 105*8208Smckusick 106*8208Smckusick # ifdef KIM 107*8208Smckusick # define MAILMODE 0644 108*8208Smckusick # define MSGSCMD "/usr/ucb/msgs" 109*8208Smckusick # endif 110*8208Smckusick 111*8208Smckusick # ifdef ESVAX 112*8208Smckusick # define MAILMODE 0644 113*8208Smckusick # define MSGSCMD "/usr/ucb/msgs" 114*8208Smckusick # endif 115*8208Smckusick 116*8208Smckusick # ifdef Q 117*8208Smckusick # define MAILMODE 0600 118*8208Smckusick # define MSGSCMD "/usr/bin/eecs/msgs" 119*8208Smckusick # endif 120*8208Smckusick 121*8208Smckusick # ifdef ARPAVAX 122*8208Smckusick # define MAILMODE 0644 123*8208Smckusick # define MSGSCMD "/usr/ucb/msgs" 124*8208Smckusick # define BIFF 125*8208Smckusick # endif 126*8208Smckusick 127*8208Smckusick # ifdef SRC 128*8208Smckusick # define MAILMODE 0600 129*8208Smckusick # define MSGSCMD "/usr/bin/msgs" 130*8208Smckusick # endif 131*8208Smckusick 132*8208Smckusick # ifdef MATHSTAT 133*8208Smckusick # define MAILMODE 0600 134*8208Smckusick # define MSGSCMD "/usr/bin/msgs" 135*8208Smckusick # endif 136*8208Smckusick 137*8208Smckusick # ifdef CSVAX 138*8208Smckusick # define MAILMODE 0644 139*8208Smckusick # define MSGSCMD "/usr/ucb/msgs" 140*8208Smckusick # define BIFF 141*8208Smckusick # endif 142*8208Smckusick 143*8208Smckusick # ifdef ONYX 144*8208Smckusick # define MAILMODE 0644 145*8208Smckusick # define MSGSCMD "/usr/ucb/bin/msgs" 146*8208Smckusick # endif 147*8208Smckusick 148*8208Smckusick # ifdef CORY 149*8208Smckusick # define MAILMODE 0600 150*8208Smckusick # define MSGSCMD "/usr/bin/eecs/msgs" 151*8208Smckusick # endif 152*8208Smckusick 153*8208Smckusick # ifdef EECS40 154*8208Smckusick # define MAILMODE 0644 155*8208Smckusick # define MSGSCMD "/usr/bin/msgs" 156*8208Smckusick # endif 157*8208Smckusick /* end of berkeley defsn */ 158*8208Smckusick 159*8208Smckusick # endif 160*8208Smckusick /* end of per-machine ifdefs */ 161*8208Smckusick 162*8208Smckusick # ifdef USRMAIL 163*8208Smckusick # define MAILDIR "/usr/mail" 164*8208Smckusick # else 165*8208Smckusick # define MAILDIR "/usr/spool/mail" 166*8208Smckusick # endif 167*8208Smckusick 168*8208Smckusick char lettmp[] = "/tmp/MaXXXXX"; /* keep letter before sending it */ 169*8208Smckusick char preptmp[] = "/tmp/mbXXXXX"; /* if prepending msg, use this file */ 170*8208Smckusick int chew; /* if true, strip extra from lines */ 171*8208Smckusick int dflag; /* if true, don't call delivermail */ 172*8208Smckusick char shopcnt[30] = "0"; /* hop count parameter for rmt mail */ 173*8208Smckusick int errs; /* no of errs in sending */ 174*8208Smckusick char deleteonly; /* if true, just delete mailbox */ 175*8208Smckusick char remname[50]; /* if non-empty, from line extra */ 176*8208Smckusick 177*8208Smckusick char _sobuf[BUFSIZ]; 178*8208Smckusick main(argc, argv) 179*8208Smckusick char **argv; 180*8208Smckusick { 181*8208Smckusick register int myuid; 182*8208Smckusick int delexit(); 183*8208Smckusick char namebuf[128], *sn = NULL, logindir[60]; 184*8208Smckusick struct passwd *pwd; 185*8208Smckusick 186*8208Smckusick setbuf(stdout,_sobuf); 187*8208Smckusick mktemp(lettmp); 188*8208Smckusick mktemp(preptmp); 189*8208Smckusick unlink(lettmp); 190*8208Smckusick unlink(preptmp); 191*8208Smckusick myuid = getuid(); 192*8208Smckusick logindir[0] = 0; 193*8208Smckusick sn = getlogin(); 194*8208Smckusick if(sn == NULL || *sn == 0 || *sn == ' '){ 195*8208Smckusick pwd = getpwuid(myuid); /* will read passwd file */ 196*8208Smckusick if(pwd != NULL){ 197*8208Smckusick sn = pwd->pw_name; 198*8208Smckusick strcpy(logindir,pwd->pw_dir); 199*8208Smckusick } 200*8208Smckusick if(sn == NULL){ 201*8208Smckusick fprintf(stderr,"Who are you?\n"); 202*8208Smckusick delexit(EX_OSFILE); 203*8208Smckusick } 204*8208Smckusick } 205*8208Smckusick strcpy(namebuf,sn); 206*8208Smckusick if (argc < 2) 207*8208Smckusick goto hitit; 208*8208Smckusick for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) 209*8208Smckusick switch(argv[0][1]) { 210*8208Smckusick case 'y': 211*8208Smckusick case 'n': 212*8208Smckusick argc++, argv--; 213*8208Smckusick hitit: 214*8208Smckusick printmail(argc, argv, namebuf,logindir); 215*8208Smckusick delexit(EX_OK); 216*8208Smckusick 217*8208Smckusick case 'r': /* one-arg -r-- -r addr */ 218*8208Smckusick if (argc < 2) 219*8208Smckusick continue; 220*8208Smckusick /* ignore -r if not network or root */ 221*8208Smckusick if (strcmp("network", namebuf) == 0 || myuid == 0 || 222*8208Smckusick strcmp("uucp", namebuf) == 0 || index(argv[1], '!') != NULL) { 223*8208Smckusick strcpy(namebuf,argv[1]); 224*8208Smckusick chew++; /* eat From lines */ 225*8208Smckusick } 226*8208Smckusick else strcpy(remname, argv[1]); 227*8208Smckusick argc--, argv++; 228*8208Smckusick continue; 229*8208Smckusick case 'h': /* hop count - used by network */ 230*8208Smckusick if(argc < 2) continue; 231*8208Smckusick strcpy(shopcnt,argv[1]); 232*8208Smckusick argc--, argv++; 233*8208Smckusick continue; 234*8208Smckusick case 'd': /* really deliver this message */ 235*8208Smckusick dflag++; 236*8208Smckusick continue; 237*8208Smckusick case 'D': /* only delete the invokers mailbox */ 238*8208Smckusick deleteonly++; 239*8208Smckusick goto hitit; /* delete mail box, thats all */ 240*8208Smckusick } 241*8208Smckusick /* if we are already ignoring signals, catch sigint */ 242*8208Smckusick if(signal(SIGINT,SIG_IGN) != SIG_IGN) 243*8208Smckusick signal(SIGINT, delexit); 244*8208Smckusick argc++, argv--; 245*8208Smckusick bulkmail(argc, argv, namebuf); 246*8208Smckusick delexit(EX_OK); 247*8208Smckusick } 248*8208Smckusick 249*8208Smckusick printmail(argc, argv, name, logindir) 250*8208Smckusick char **argv; 251*8208Smckusick char *name, *logindir; 252*8208Smckusick { 253*8208Smckusick register int c; 254*8208Smckusick FILE *fdin; 255*8208Smckusick char sfnmail[60], mbox[120]; 256*8208Smckusick struct stat statbuf; 257*8208Smckusick 258*8208Smckusick # ifdef OLDMAIL 259*8208Smckusick if(logindir[0] == 0){ 260*8208Smckusick pwd = getpwuid(getuid()); 261*8208Smckusick if(pwd == NULL){ 262*8208Smckusick fprintf(stderr,"Can't get directory\n"); 263*8208Smckusick exit(EX_OSFILE); 264*8208Smckusick } 265*8208Smckusick strcpy(logindir, pwd->pw_dir); 266*8208Smckusick } 267*8208Smckusick sprintf(sfnmail,"%s/.mail",logindir); 268*8208Smckusick # else 269*8208Smckusick sprintf(sfnmail,"%s/%s",MAILDIR,name); 270*8208Smckusick # endif 271*8208Smckusick if(deleteonly){ 272*8208Smckusick remove(sfnmail); 273*8208Smckusick return; 274*8208Smckusick } 275*8208Smckusick if (stat(sfnmail, &statbuf)>=0 && statbuf.st_nlink==1 && 276*8208Smckusick getsize(&statbuf) > 0L && (fdin = fopen(sfnmail, "r")) != NULL){ 277*8208Smckusick getput(fdin, stdout); 278*8208Smckusick fclose(fdin); 279*8208Smckusick fflush(stdout); 280*8208Smckusick c = 'y'; 281*8208Smckusick if (argc<2) { 282*8208Smckusick if(isatty(0)){ 283*8208Smckusick printf("Save(y-n) ?"); 284*8208Smckusick fflush(stdout); 285*8208Smckusick c = getchar(); 286*8208Smckusick } 287*8208Smckusick } else 288*8208Smckusick c = argv[1][1]; 289*8208Smckusick if (!any(c, "xyn")) 290*8208Smckusick delexit(EX_OK); 291*8208Smckusick if (c == 'y') { 292*8208Smckusick sprintf(mbox,"%s/mbox",logindir); 293*8208Smckusick if (accesss(mbox)) { 294*8208Smckusick printf("Saved mail in 'mbox'\n"); 295*8208Smckusick if(insert(sfnmail, mbox, getuid(),getgid())) 296*8208Smckusick remove(sfnmail); 297*8208Smckusick } 298*8208Smckusick else printf("In wrong directory\n"); 299*8208Smckusick } 300*8208Smckusick else if(c != 'x') remove(sfnmail); 301*8208Smckusick } else 302*8208Smckusick printf("No mail.\n"); 303*8208Smckusick } 304*8208Smckusick 305*8208Smckusick bulkmail(argc, argv, from) 306*8208Smckusick char **argv, *from; 307*8208Smckusick { 308*8208Smckusick extern int errno; 309*8208Smckusick char linebuf[BUFSIZ]; 310*8208Smckusick char *getdate(); 311*8208Smckusick FILE *fdout; 312*8208Smckusick 313*8208Smckusick # ifdef DELIVERM 314*8208Smckusick /* 315*8208Smckusick ** Ship off to delivermail if appropriate (and possible) 316*8208Smckusick */ 317*8208Smckusick 318*8208Smckusick if (!dflag) 319*8208Smckusick { 320*8208Smckusick argv[0] = "-delivermail"; 321*8208Smckusick argv[argc] = 0; 322*8208Smckusick execv("/etc/delivermail", argv); 323*8208Smckusick /* oops... better just deliver it. */ 324*8208Smckusick fprintf(stderr, "Not using delivermail\n"); 325*8208Smckusick errno = 0; 326*8208Smckusick argv[argc] = (char *)-1; 327*8208Smckusick } 328*8208Smckusick # endif 329*8208Smckusick 330*8208Smckusick fdout = fopen(lettmp, "w"); 331*8208Smckusick if (fdout == NULL) { 332*8208Smckusick perror(lettmp); 333*8208Smckusick delexit(EX_OSFILE); 334*8208Smckusick } 335*8208Smckusick /* 336*8208Smckusick * If delivering mail from the network via mail -r, 337*8208Smckusick * Strip the leading line and throw it away, as long 338*8208Smckusick * as it begins with "From ..." (and preserve the date if poss.) 339*8208Smckusick */ 340*8208Smckusick if (chew) { 341*8208Smckusick fgets(linebuf,BUFSIZ,stdin); 342*8208Smckusick if(strncmp(linebuf,"From ",5) != 0){ 343*8208Smckusick fline(fdout,NULL,from); 344*8208Smckusick fprintf(fdout,"%s", linebuf); 345*8208Smckusick } 346*8208Smckusick else fline(fdout,getdate(linebuf),from); 347*8208Smckusick } 348*8208Smckusick else fline(fdout,NULL,from); 349*8208Smckusick if(remname[0]) fprintf(fdout,"(from %s)\n",remname); 350*8208Smckusick 351*8208Smckusick /* on the image machine, promt with subj */ 352*8208Smckusick if(getput(stdin,fdout) == 0) 353*8208Smckusick delexit(EX_OSERR); 354*8208Smckusick putc('\n',fdout); 355*8208Smckusick fclose(fdout); 356*8208Smckusick while (--argc > 0) 357*8208Smckusick sendto(*++argv,from); 358*8208Smckusick delexit(errs); 359*8208Smckusick } 360*8208Smckusick /* print from line, with date date, if date = NULL, compute it */ 361*8208Smckusick fline(fdout,date,from) 362*8208Smckusick FILE *fdout; 363*8208Smckusick char *date; 364*8208Smckusick char *from; 365*8208Smckusick { 366*8208Smckusick int tbuf[2]; 367*8208Smckusick 368*8208Smckusick if(date == NULL){ 369*8208Smckusick time(tbuf); 370*8208Smckusick date = ctime(tbuf); 371*8208Smckusick } 372*8208Smckusick fprintf(fdout,"From %s %s", from, date); 373*8208Smckusick } 374*8208Smckusick /* look over linebuf and return ptr to date, NULL if error */ 375*8208Smckusick char *getdate(linebuf) 376*8208Smckusick char *linebuf; 377*8208Smckusick { 378*8208Smckusick register char *s; 379*8208Smckusick s = linebuf; 380*8208Smckusick while(*s){ 381*8208Smckusick if(strncmp(s," Sun ",5) == 0 382*8208Smckusick || strncmp(s," Mon ",5) == 0 383*8208Smckusick || strncmp(s," Tue ",5) == 0 384*8208Smckusick || strncmp(s," Wed ",5) == 0 385*8208Smckusick || strncmp(s," Thu ",5) == 0 386*8208Smckusick || strncmp(s," Fri ",5) == 0 387*8208Smckusick || strncmp(s," Sat ",5) == 0) 388*8208Smckusick return(++s); 389*8208Smckusick s++; 390*8208Smckusick } 391*8208Smckusick return(NULL); 392*8208Smckusick } 393*8208Smckusick 394*8208Smckusick sendto(person, fromaddr) 395*8208Smckusick char *person; 396*8208Smckusick char *fromaddr; 397*8208Smckusick { 398*8208Smckusick static int saved = 0; 399*8208Smckusick register int hisuid, hisgid; 400*8208Smckusick char sfnmail[60], logindir[60]; 401*8208Smckusick struct passwd *pwd; 402*8208Smckusick 403*8208Smckusick stripmach(&person); 404*8208Smckusick if(person[0] == ':')person++; 405*8208Smckusick /* delivermail provides these services */ 406*8208Smckusick if(any(':',person) 407*8208Smckusick # ifdef MSGSCMD 408*8208Smckusick || strcmp(person,"msgs") == 0 409*8208Smckusick # endif 410*8208Smckusick ){ 411*8208Smckusick int pid; 412*8208Smckusick int pidchild; 413*8208Smckusick 414*8208Smckusick while((pid = fork()) == -1)sleep(2); 415*8208Smckusick if (pid < 0) { 416*8208Smckusick perror("fork"); 417*8208Smckusick goto assback; 418*8208Smckusick } 419*8208Smckusick if (pid == 0) { 420*8208Smckusick fclose(stdin); 421*8208Smckusick freopen(lettmp,"r",stdin); 422*8208Smckusick setuid(getuid()); /* insure no security hole*/ 423*8208Smckusick if (strcmp(person,"msgs") != 0) { 424*8208Smckusick /* 425*8208Smckusick sendberkmail will add the machine, e.g. 426*8208Smckusick CSVAX:schmidt, if the -f flag is not set 427*8208Smckusick */ 428*8208Smckusick execl("/usr/net/bin/sendberkmail", 429*8208Smckusick "sendberkmail", "-t",person,"-h",shopcnt, 430*8208Smckusick chew ? "-f" : 0,fromaddr,0); 431*8208Smckusick perror("/usr/net/bin/sendberkmail"); 432*8208Smckusick } 433*8208Smckusick # ifdef MSGSCMD 434*8208Smckusick else { 435*8208Smckusick execl(MSGSCMD, "msgs", "-s", 0); 436*8208Smckusick perror(MSGSCMD); 437*8208Smckusick } 438*8208Smckusick # endif 439*8208Smckusick exit(EX_UNAVAILABLE); 440*8208Smckusick } 441*8208Smckusick for (;;) { 442*8208Smckusick register int rcode = wait(&pidchild); 443*8208Smckusick if (rcode == -1) 444*8208Smckusick goto assback; 445*8208Smckusick if (rcode == pid) 446*8208Smckusick break; 447*8208Smckusick } 448*8208Smckusick if ((pidchild & 0377) != 0 || (pidchild >> 8) != 0) 449*8208Smckusick goto assback; 450*8208Smckusick return; 451*8208Smckusick } 452*8208Smckusick 453*8208Smckusick if(!any('/',person)){ 454*8208Smckusick /* if name has no / in it, we assume it is a user's name */ 455*8208Smckusick # ifdef HPASSWD 456*8208Smckusick hisuid = uidfromsn(person); 457*8208Smckusick # else 458*8208Smckusick pwd = getpwnam(person); 459*8208Smckusick if(pwd != NULL){ 460*8208Smckusick hisuid = guid(pwd->pw_uid,pwd->pw_gid); 461*8208Smckusick hisgid = pwd->pw_gid; 462*8208Smckusick strcpy(logindir,pwd->pw_dir); 463*8208Smckusick } 464*8208Smckusick else hisuid = -1; 465*8208Smckusick # endif 466*8208Smckusick if(hisuid == -1){ 467*8208Smckusick assback: 468*8208Smckusick fflush(stdout); 469*8208Smckusick fprintf(stderr,"Can't send to %s.\n", person); 470*8208Smckusick errs++; 471*8208Smckusick if (isatty(0) && saved==0) { 472*8208Smckusick saved++; 473*8208Smckusick if (accesss("dead.letter")) { 474*8208Smckusick printf("Letter saved in 'dead.letter'\n"); 475*8208Smckusick insert(lettmp, "dead.letter", 476*8208Smckusick getuid(),getgid()); 477*8208Smckusick } else 478*8208Smckusick printf("In wrong directory\n"); 479*8208Smckusick } 480*8208Smckusick return; 481*8208Smckusick } 482*8208Smckusick # ifdef OLDMAIL 483*8208Smckusick sprintf(sfnmail,"%s/.mail",logindir); 484*8208Smckusick # else 485*8208Smckusick sprintf(sfnmail,"%s/%s",MAILDIR,person); 486*8208Smckusick # endif 487*8208Smckusick lock(sfnmail); 488*8208Smckusick insert(lettmp, sfnmail, hisuid, hisgid); 489*8208Smckusick unlock(); 490*8208Smckusick } 491*8208Smckusick else { /* it has / in it, "person" is a file */ 492*8208Smckusick if(accesss(person)){ 493*8208Smckusick lock(person); 494*8208Smckusick insert(lettmp, person, -1, -1); 495*8208Smckusick unlock(); 496*8208Smckusick } 497*8208Smckusick else 498*8208Smckusick fprintf(stderr,"Can't access %s\n",person); 499*8208Smckusick } 500*8208Smckusick } 501*8208Smckusick 502*8208Smckusick /* return 1 if success, 0 otherwise */ 503*8208Smckusick insert(from, to, uid, gid) 504*8208Smckusick char *from, *to; 505*8208Smckusick { 506*8208Smckusick # ifdef V6 507*8208Smckusick return(prepend(from,to,uid, gid)); 508*8208Smckusick # else 509*8208Smckusick return(append(from,to,uid, gid)); 510*8208Smckusick # endif 511*8208Smckusick } 512*8208Smckusick /* return 1 if success, 0 otherwise */ 513*8208Smckusick append(from,to,uid, gid) 514*8208Smckusick char *from, *to; 515*8208Smckusick { 516*8208Smckusick register FILE *fdin, *fdout; 517*8208Smckusick int ret; 518*8208Smckusick struct stat statbuf; 519*8208Smckusick #ifdef BIFF 520*8208Smckusick /* biff ... */ 521*8208Smckusick char *rindex(); 522*8208Smckusick char *cp; 523*8208Smckusick char buf[100]; 524*8208Smckusick int f; 525*8208Smckusick /* end biff */ 526*8208Smckusick #endif BIFF 527*8208Smckusick if (stat(to, &statbuf) >= 0 && (statbuf.st_mode&S_IFDIR) != 0) { 528*8208Smckusick fprintf(stderr, "Exotic destination %s\n", to); 529*8208Smckusick errs++; 530*8208Smckusick return(0); 531*8208Smckusick } 532*8208Smckusick if ((fdout = fopen(to, "a")) == NULL) { 533*8208Smckusick perror(to); 534*8208Smckusick errs++; 535*8208Smckusick return(0); 536*8208Smckusick } 537*8208Smckusick # ifndef NOTROOT 538*8208Smckusick if(uid != -1)mchown(to, uid, gid); 539*8208Smckusick # endif 540*8208Smckusick if(uid != -1)chmod(to, MAILMODE); 541*8208Smckusick if ((fdin = fopen(from, "r")) == NULL) { 542*8208Smckusick perror(from); 543*8208Smckusick return(0); 544*8208Smckusick } 545*8208Smckusick #ifdef BIFF 546*8208Smckusick { 547*8208Smckusick f = open("/dev/mail", 1); 548*8208Smckusick cp = rindex(to, '/'); 549*8208Smckusick if (cp) { 550*8208Smckusick sprintf(buf, "%s@%d\n", cp+1, ftell(fdout)); 551*8208Smckusick } 552*8208Smckusick } 553*8208Smckusick #endif BIFF 554*8208Smckusick ret = getput(fdin,fdout); 555*8208Smckusick fclose(fdin); 556*8208Smckusick fclose(fdout); 557*8208Smckusick #ifdef BIFF 558*8208Smckusick if (cp && f >= 0) { 559*8208Smckusick write(f, buf, strlen(buf)+1); 560*8208Smckusick close(f); 561*8208Smckusick } 562*8208Smckusick #endif BIFF 563*8208Smckusick return(ret); 564*8208Smckusick } 565*8208Smckusick 566*8208Smckusick /* return 1 if success, 0 otherwise */ 567*8208Smckusick prepend(from, to, uid, gid) 568*8208Smckusick char *from, *to; 569*8208Smckusick { 570*8208Smckusick register int (*sig)(); 571*8208Smckusick struct stat statbuf; 572*8208Smckusick FILE *fdout, *fdin; 573*8208Smckusick int ret; 574*8208Smckusick 575*8208Smckusick if (stat(to, &statbuf) >= 0 && (statbuf.st_mode&S_IFDIR) != 0) { 576*8208Smckusick fprintf(stderr, "Exotic destination %s\n", to); 577*8208Smckusick goto badexit; 578*8208Smckusick } 579*8208Smckusick unlink(preptmp); 580*8208Smckusick if ((fdout = fopen(preptmp, "w")) == NULL) { 581*8208Smckusick perror("mail"); 582*8208Smckusick goto badexit; 583*8208Smckusick } 584*8208Smckusick chmod(preptmp, MAILMODE); 585*8208Smckusick if ((fdin = fopen(from, "r")) == NULL) { 586*8208Smckusick perror("mail"); 587*8208Smckusick goto badexit; 588*8208Smckusick } 589*8208Smckusick if(getput(fdin,fdout) == 0){ 590*8208Smckusick perror("file i/o"); 591*8208Smckusick goto badexit; 592*8208Smckusick } 593*8208Smckusick fclose(fdin); 594*8208Smckusick fdin = fopen(to, "r"); 595*8208Smckusick /* ignore error since may not exist */ 596*8208Smckusick if(fdin != NULL && getput(fdin,fdout) == 0){ 597*8208Smckusick perror("file i/o"); 598*8208Smckusick goto badexit; 599*8208Smckusick } 600*8208Smckusick if(fdin != NULL)fclose(fdin); 601*8208Smckusick fclose(fdout); 602*8208Smckusick sig = signal(SIGINT, SIG_IGN); 603*8208Smckusick remove(to); 604*8208Smckusick if ((fdout = fopen(to, "w")) == NULL) { 605*8208Smckusick perror(to); 606*8208Smckusick unlink(preptmp); 607*8208Smckusick signal(SIGINT, sig); 608*8208Smckusick goto badexit; 609*8208Smckusick } 610*8208Smckusick # ifdef NOTROOT 611*8208Smckusick if(uid != -1)chmod(to,0666); 612*8208Smckusick # else 613*8208Smckusick if(uid != -1)mchown(to, uid, gid); 614*8208Smckusick # endif 615*8208Smckusick if(stat(to, &statbuf) < 0 || statbuf.st_nlink != 1) { 616*8208Smckusick fclose(fdout); 617*8208Smckusick signal(SIGINT, sig); 618*8208Smckusick goto badexit; 619*8208Smckusick } 620*8208Smckusick if ((fdin = fopen(preptmp, "r")) == NULL) { 621*8208Smckusick perror("mail"); 622*8208Smckusick signal(SIGINT, sig); 623*8208Smckusick goto badexit; 624*8208Smckusick } 625*8208Smckusick ret = getput(fdin,fdout); 626*8208Smckusick fclose(fdout); 627*8208Smckusick fclose(fdin); 628*8208Smckusick signal(SIGINT, sig); 629*8208Smckusick return(ret); 630*8208Smckusick badexit: 631*8208Smckusick unlink(preptmp); 632*8208Smckusick errs++; 633*8208Smckusick return(0); 634*8208Smckusick } 635*8208Smckusick 636*8208Smckusick delexit(ex) 637*8208Smckusick { 638*8208Smckusick unlink(lettmp); 639*8208Smckusick unlink(preptmp); 640*8208Smckusick exit(ex); 641*8208Smckusick } 642*8208Smckusick 643*8208Smckusick /* return 1 if ok, 0 otherwise */ 644*8208Smckusick getput(fdin, fdout) 645*8208Smckusick register FILE *fdin, *fdout; 646*8208Smckusick { 647*8208Smckusick extern int errno; 648*8208Smckusick register int c; 649*8208Smckusick 650*8208Smckusick while((c = getc(fdin)) != EOF) { 651*8208Smckusick errno = 0; 652*8208Smckusick putc(c,fdout); 653*8208Smckusick if(errno) { 654*8208Smckusick perror("mail"); 655*8208Smckusick return(0); 656*8208Smckusick } 657*8208Smckusick } 658*8208Smckusick return(1); 659*8208Smckusick } 660*8208Smckusick 661*8208Smckusick accesss(s1) 662*8208Smckusick register char *s1; 663*8208Smckusick { 664*8208Smckusick struct stat statbuf; 665*8208Smckusick if(stat(s1,&statbuf)<0 || access(s1,2) == 0) 666*8208Smckusick return(1); 667*8208Smckusick return(0); 668*8208Smckusick } 669*8208Smckusick 670*8208Smckusick any(c, str) 671*8208Smckusick register char *str, c; 672*8208Smckusick { 673*8208Smckusick register char *f; 674*8208Smckusick 675*8208Smckusick f = str; 676*8208Smckusick while (*f) 677*8208Smckusick if (c == *f++) 678*8208Smckusick return(1); 679*8208Smckusick return(0); 680*8208Smckusick } 681*8208Smckusick char locktmp[30]; /* Usable lock temporary */ 682*8208Smckusick char curlock[50]; /* Last used name of lock */ 683*8208Smckusick int locked; /* To note that we locked it */ 684*8208Smckusick 685*8208Smckusick /* 686*8208Smckusick * Lock the specified mail file by setting the file mailfile.lock. 687*8208Smckusick * We must, of course, be careful to unlink the lock file by a call 688*8208Smckusick * to unlock before we stop. The algorithm used here is to see if 689*8208Smckusick * the lock exists, and if it does, to check its modify time. If it 690*8208Smckusick * is older than 30 seconds, we assume error and set our own file. 691*8208Smckusick * Otherwise, we wait for 5 seconds and try again. 692*8208Smckusick */ 693*8208Smckusick 694*8208Smckusick lock(file) 695*8208Smckusick char *file; 696*8208Smckusick { 697*8208Smckusick register int f; 698*8208Smckusick struct stat statbuf; 699*8208Smckusick long curtime; 700*8208Smckusick /* 701*8208Smckusick if using OLDMAIL, and NOTROOT, cann't lock since can't necessarily 702*8208Smckusick write on user's login directory 703*8208Smckusick */ 704*8208Smckusick # ifdef OLDMAIL 705*8208Smckusick return; 706*8208Smckusick # endif 707*8208Smckusick 708*8208Smckusick if (file == NULL) { 709*8208Smckusick printf("Locked = %d\n", locked); 710*8208Smckusick return(0); 711*8208Smckusick } 712*8208Smckusick if (locked) 713*8208Smckusick return(0); 714*8208Smckusick sprintf(curlock,"%s%s",file,".mail"); 715*8208Smckusick sprintf(locktmp,"%s/tmXXXXXX",MAILDIR); 716*8208Smckusick mktemp(locktmp); 717*8208Smckusick unlink(locktmp); 718*8208Smckusick for (;;) { 719*8208Smckusick f = lock1(locktmp, curlock); 720*8208Smckusick if (f == 0) { 721*8208Smckusick locked = 1; 722*8208Smckusick return(0); 723*8208Smckusick } 724*8208Smckusick if (stat(curlock, &statbuf) < 0) 725*8208Smckusick return(0); 726*8208Smckusick time(&curtime); 727*8208Smckusick if (curtime < statbuf.st_mtime + 30) { 728*8208Smckusick sleep(5); 729*8208Smckusick continue; 730*8208Smckusick } 731*8208Smckusick unlink(curlock); 732*8208Smckusick } 733*8208Smckusick } 734*8208Smckusick 735*8208Smckusick /* 736*8208Smckusick * Remove the mail lock, and note that we no longer 737*8208Smckusick * have it locked. 738*8208Smckusick */ 739*8208Smckusick 740*8208Smckusick unlock() 741*8208Smckusick { 742*8208Smckusick 743*8208Smckusick if (locked) 744*8208Smckusick unlink(curlock); 745*8208Smckusick locked = 0; 746*8208Smckusick } 747*8208Smckusick 748*8208Smckusick /* 749*8208Smckusick * Attempt to set the lock by creating the temporary file, 750*8208Smckusick * then doing a link/unlink. If it fails, return -1 else 0 751*8208Smckusick */ 752*8208Smckusick 753*8208Smckusick lock1(tempfile, name) 754*8208Smckusick char tempfile[], name[]; 755*8208Smckusick { 756*8208Smckusick int fno; 757*8208Smckusick 758*8208Smckusick fno = creat(tempfile, 0400); 759*8208Smckusick if (fno < 0) 760*8208Smckusick return(-1); 761*8208Smckusick close(fno); 762*8208Smckusick if (link(tempfile, name) < 0) { 763*8208Smckusick unlink(tempfile); 764*8208Smckusick return(-1); 765*8208Smckusick } 766*8208Smckusick unlink(tempfile); 767*8208Smckusick return(0); 768*8208Smckusick } 769*8208Smckusick 770*8208Smckusick /* 771*8208Smckusick stripfx(prefix string, pointer to string) 772*8208Smckusick 773*8208Smckusick takes a ptr to string and compares it to prefix string. 774*8208Smckusick may be called multiple times 775*8208Smckusick returns ":username" 776*8208Smckusick */ 777*8208Smckusick stripfx(pfx, name) 778*8208Smckusick register char *pfx; 779*8208Smckusick register char **name; 780*8208Smckusick { 781*8208Smckusick register char *cp = *name; 782*8208Smckusick 783*8208Smckusick while (*pfx && (*cp == *pfx || *cp == toupper(*pfx))) 784*8208Smckusick cp++, pfx++; 785*8208Smckusick if (*cp != ':' || *pfx != 0) 786*8208Smckusick return; 787*8208Smckusick *name = cp; 788*8208Smckusick } 789*8208Smckusick stripmach(pperson) 790*8208Smckusick register char **pperson; 791*8208Smckusick { 792*8208Smckusick # ifdef RAND 793*8208Smckusick /* for machines at RAND */ 794*8208Smckusick # ifdef GRAPHICS 795*8208Smckusick stripfx("g",pperson); 796*8208Smckusick stripfx("graphics",pperson); 797*8208Smckusick # endif 798*8208Smckusick # ifdef TP 799*8208Smckusick stripfx("t",pperson); 800*8208Smckusick stripfx("tp",pperson); 801*8208Smckusick # endif 802*8208Smckusick # ifdef VAX 803*8208Smckusick stripfx("v",pperson); 804*8208Smckusick stripfx("vax",pperson); 805*8208Smckusick # endif 806*8208Smckusick /* end of defns for Rand */ 807*8208Smckusick # endif 808*8208Smckusick 809*8208Smckusick # ifdef NOSC 810*8208Smckusick /* for machines at NOSC */ 811*8208Smckusick # ifdef ATTS 812*8208Smckusick stripfx("a",pperson); 813*8208Smckusick stripfx("atts",pperson); 814*8208Smckusick # endif 815*8208Smckusick # ifdef CCMM 816*8208Smckusick stripfx("c",pperson); 817*8208Smckusick stripfx("ccmm",pperson); 818*8208Smckusick # endif 819*8208Smckusick # ifdef MSSF 820*8208Smckusick stripfx("m",pperson); 821*8208Smckusick stripfx("mssf",pperson); 822*8208Smckusick # endif 823*8208Smckusick /* end of defns for NOSC */ 824*8208Smckusick # endif 825*8208Smckusick 826*8208Smckusick # ifdef BERKELEY 827*8208Smckusick 828*8208Smckusick /* for Berkeley */ 829*8208Smckusick # ifdef A 830*8208Smckusick stripfx("a",pperson); 831*8208Smckusick # endif 832*8208Smckusick # ifdef B 833*8208Smckusick stripfx("b",pperson); 834*8208Smckusick # endif 835*8208Smckusick # ifdef C 836*8208Smckusick stripfx("c",pperson); 837*8208Smckusick # endif 838*8208Smckusick # ifdef D 839*8208Smckusick stripfx("d",pperson); 840*8208Smckusick # endif 841*8208Smckusick # ifdef E 842*8208Smckusick stripfx("e",pperson); 843*8208Smckusick # endif 844*8208Smckusick # ifdef ING70 845*8208Smckusick stripfx("i",pperson); 846*8208Smckusick stripfx("ing70",pperson); 847*8208Smckusick stripfx("ingres",pperson); 848*8208Smckusick # endif 849*8208Smckusick # ifdef INGVAX 850*8208Smckusick stripfx("j",pperson); 851*8208Smckusick stripfx("ingvax",pperson); 852*8208Smckusick # endif 853*8208Smckusick # ifdef VIRUS 854*8208Smckusick stripfx("k",pperson); 855*8208Smckusick stripfx("virus",pperson); 856*8208Smckusick # endif 857*8208Smckusick # ifdef IMAGE 858*8208Smckusick stripfx("m",pperson); 859*8208Smckusick stripfx("image",pperson); 860*8208Smckusick # endif 861*8208Smckusick # ifdef KIM 862*8208Smckusick stripfx("n",pperson); 863*8208Smckusick stripfx("kim",pperson); 864*8208Smckusick # endif 865*8208Smckusick # ifdef ESVAX 866*8208Smckusick stripfx("o",pperson); 867*8208Smckusick stripfx("esvax",pperson); 868*8208Smckusick # endif 869*8208Smckusick # ifdef Q 870*8208Smckusick stripfx("q",pperson); 871*8208Smckusick # endif 872*8208Smckusick # ifdef ARPAVAX 873*8208Smckusick stripfx("r",pperson); 874*8208Smckusick stripfx("arpavax",pperson); 875*8208Smckusick # endif 876*8208Smckusick # ifdef SRC 877*8208Smckusick stripfx("s",pperson); 878*8208Smckusick stripfx("src",pperson); 879*8208Smckusick # endif 880*8208Smckusick # ifdef MATHSTAT 881*8208Smckusick stripfx("t",pperson); 882*8208Smckusick stripfx("mathstat",pperson); 883*8208Smckusick # endif 884*8208Smckusick # ifdef CSVAX 885*8208Smckusick stripfx("v",pperson); 886*8208Smckusick stripfx("vax",pperson); 887*8208Smckusick stripfx("csvax",pperson); 888*8208Smckusick # endif 889*8208Smckusick # ifdef CORY 890*8208Smckusick stripfx("y",pperson); 891*8208Smckusick stripfx("cory",pperson); 892*8208Smckusick # endif 893*8208Smckusick # ifdef EECS40 894*8208Smckusick stripfx("z",pperson); 895*8208Smckusick stripfx("eecs40",pperson); 896*8208Smckusick # endif 897*8208Smckusick /* end of berkeley defns */ 898*8208Smckusick # endif 899*8208Smckusick } 900*8208Smckusick /* 901*8208Smckusick this removes the mail file sfn by either truncating it, as required 902*8208Smckusick on OLDMAIL systems, or unlinking it. If the unlink fails, we truncate it. 903*8208Smckusick */ 904*8208Smckusick remove(sfn) 905*8208Smckusick char *sfn; 906*8208Smckusick { 907*8208Smckusick int i; 908*8208Smckusick # ifdef OLDMAIL 909*8208Smckusick i = creat(sfn,0666); 910*8208Smckusick if(i >= 0)close(i); 911*8208Smckusick # else 912*8208Smckusick if(unlink(sfn) < 0){ 913*8208Smckusick i = creat(sfn,MAILMODE); 914*8208Smckusick if(i >= 0)close(i); 915*8208Smckusick } 916*8208Smckusick # endif 917*8208Smckusick } 918