|
|
1.1 ! root 1: /* ! 2: ** Vacation ! 3: ** Copyright (c) 1983 Eric P. Allman ! 4: ** Berkeley, California ! 5: ** ! 6: ** Copyright (c) 1983 Regents of the University of California. ! 7: ** All rights reserved. The Berkeley software License Agreement ! 8: ** specifies the terms and conditions for redistribution. ! 9: */ ! 10: ! 11: #ifndef lint ! 12: static char SccsId[] = "@(#)vacation.c 5.3 (Berkeley) 7/1/85"; ! 13: #endif not lint ! 14: ! 15: # include <sys/types.h> ! 16: # include <pwd.h> ! 17: # include <stdio.h> ! 18: # include <sysexits.h> ! 19: # include <ctype.h> ! 20: ! 21: /* ! 22: ** VACATION -- return a message to the sender when on vacation. ! 23: ** ! 24: ** This program could be invoked as a message receiver ! 25: ** when someone is on vacation. It returns a message ! 26: ** specified by the user to whoever sent the mail, taking ! 27: ** care not to return a message too often to prevent ! 28: ** "I am on vacation" loops. ! 29: ** ! 30: ** Positional Parameters: ! 31: ** the user to collect the vacation message from. ! 32: ** ! 33: ** Flag Parameters: ! 34: ** -I initialize the database. ! 35: ** -d turn on debugging. ! 36: ** ! 37: ** Side Effects: ! 38: ** A message is sent back to the sender. ! 39: ** ! 40: ** Author: ! 41: ** Eric Allman ! 42: ** UCB/INGRES ! 43: */ ! 44: ! 45: typedef int bool; ! 46: ! 47: # define TRUE 1 ! 48: # define FALSE 0 ! 49: ! 50: # define MAXLINE 256 /* max size of a line */ ! 51: # define MAXNAME 128 /* max size of one name */ ! 52: ! 53: # define ONEWEEK (60L*60L*24L*7L) ! 54: ! 55: time_t Timeout = ONEWEEK; /* timeout between notices per user */ ! 56: ! 57: struct dbrec ! 58: { ! 59: long sentdate; ! 60: }; ! 61: ! 62: typedef struct ! 63: { ! 64: char *dptr; ! 65: int dsize; ! 66: } DATUM; ! 67: ! 68: extern DATUM fetch(); ! 69: ! 70: ! 71: ! 72: bool Debug = FALSE; ! 73: ! 74: main(argc, argv) ! 75: char **argv; ! 76: { ! 77: char *from; ! 78: register char *p; ! 79: struct passwd *pw; ! 80: char *homedir; ! 81: char *myname; ! 82: char buf[MAXLINE]; ! 83: extern struct passwd *getpwnam(); ! 84: extern char *newstr(); ! 85: extern char *getfrom(); ! 86: extern bool knows(); ! 87: extern bool junkmail(); ! 88: extern time_t convtime(); ! 89: ! 90: /* process arguments */ ! 91: while (--argc > 0 && (p = *++argv) != NULL && *p == '-') ! 92: { ! 93: switch (*++p) ! 94: { ! 95: case 'I': /* initialize */ ! 96: initialize(); ! 97: exit(EX_OK); ! 98: ! 99: case 'd': /* debug */ ! 100: Debug = TRUE; ! 101: break; ! 102: ! 103: default: ! 104: usrerr("Unknown flag -%s", p); ! 105: exit(EX_USAGE); ! 106: } ! 107: } ! 108: ! 109: /* verify recipient argument */ ! 110: if (argc != 1) ! 111: { ! 112: usrerr("Usage: vacation username (or) vacation -I"); ! 113: exit(EX_USAGE); ! 114: } ! 115: ! 116: myname = p; ! 117: ! 118: /* find user's home directory */ ! 119: pw = getpwnam(myname); ! 120: if (pw == NULL) ! 121: { ! 122: usrerr("Unknown user %s", myname); ! 123: exit(EX_NOUSER); ! 124: } ! 125: homedir = newstr(pw->pw_dir); ! 126: (void) strcpy(buf, homedir); ! 127: (void) strcat(buf, "/.vacation"); ! 128: dbminit(buf); ! 129: ! 130: /* read message from standard input (just from line) */ ! 131: from = getfrom(); ! 132: ! 133: /* check if junk mail or this person is already informed */ ! 134: if (!junkmail(from) && !knows(from)) ! 135: { ! 136: /* mark this person as knowing */ ! 137: setknows(from); ! 138: ! 139: /* send the message back */ ! 140: (void) strcpy(buf, homedir); ! 141: (void) strcat(buf, "/.vacation.msg"); ! 142: if (Debug) ! 143: printf("Sending %s to %s\n", buf, from); ! 144: else ! 145: { ! 146: sendmessage(buf, from, myname); ! 147: /*NOTREACHED*/ ! 148: } ! 149: } ! 150: exit (EX_OK); ! 151: } ! 152: /* ! 153: ** GETFROM -- read message from standard input and return sender ! 154: ** ! 155: ** Parameters: ! 156: ** none. ! 157: ** ! 158: ** Returns: ! 159: ** pointer to the sender address. ! 160: ** ! 161: ** Side Effects: ! 162: ** Reads first line from standard input. ! 163: */ ! 164: ! 165: char * ! 166: getfrom() ! 167: { ! 168: static char line[MAXLINE]; ! 169: register char *p; ! 170: extern char *index(); ! 171: ! 172: /* read the from line */ ! 173: if (fgets(line, sizeof line, stdin) == NULL || ! 174: strncmp(line, "From ", 5) != NULL) ! 175: { ! 176: usrerr("No initial From line"); ! 177: exit(EX_USAGE); ! 178: } ! 179: ! 180: /* find the end of the sender address and terminate it */ ! 181: p = index(&line[5], ' '); ! 182: if (p == NULL) ! 183: { ! 184: usrerr("Funny From line '%s'", line); ! 185: exit(EX_USAGE); ! 186: } ! 187: *p = '\0'; ! 188: ! 189: /* return the sender address */ ! 190: return (&line[5]); ! 191: } ! 192: /* ! 193: ** JUNKMAIL -- read the header and tell us if this is junk/bulk mail. ! 194: ** ! 195: ** Parameters: ! 196: ** from -- the Return-Path of the sender. We assume that ! 197: ** anything from "*-REQUEST@*" is bulk mail. ! 198: ** ! 199: ** Returns: ! 200: ** TRUE -- if this is junk or bulk mail (that is, if the ! 201: ** sender shouldn't receive a response). ! 202: ** FALSE -- if the sender deserves a response. ! 203: ** ! 204: ** Side Effects: ! 205: ** May read the header from standard input. When this ! 206: ** returns the position on stdin is undefined. ! 207: */ ! 208: ! 209: bool ! 210: junkmail(from) ! 211: char *from; ! 212: { ! 213: register char *p; ! 214: char buf[MAXLINE+1]; ! 215: extern char *index(); ! 216: extern char *rindex(); ! 217: extern bool sameword(); ! 218: ! 219: /* test for inhuman sender */ ! 220: p = rindex(from, '@'); ! 221: if (p != NULL) ! 222: { ! 223: *p = '\0'; ! 224: if (sameword(&p[-8], "-REQUEST") || ! 225: sameword(&p[-10], "Postmaster") || ! 226: sameword(&p[-13], "MAILER-DAEMON")) ! 227: { ! 228: *p = '@'; ! 229: return (TRUE); ! 230: } ! 231: *p = '@'; ! 232: } ! 233: ! 234: /* read the header looking for a "Precedence:" line */ ! 235: while (fgets(buf, MAXLINE, stdin) != NULL && buf[0] != '\n') ! 236: { ! 237: /* should ignore case, but this is reasonably safe */ ! 238: if (strncmp(buf, "Precedence", 10) != 0 || ! 239: !(buf[10] == ':' || buf[10] == ' ' || buf[10] == '\t')) ! 240: { ! 241: continue; ! 242: } ! 243: ! 244: /* find the value of this field */ ! 245: p = index(buf, ':'); ! 246: if (p == NULL) ! 247: continue; ! 248: while (*++p != '\0' && isspace(*p)) ! 249: continue; ! 250: if (*p == '\0') ! 251: continue; ! 252: ! 253: /* see if it is "junk" or "bulk" */ ! 254: p[4] = '\0'; ! 255: if (sameword(p, "junk") || sameword(p, "bulk")) ! 256: return (TRUE); ! 257: } ! 258: return (FALSE); ! 259: } ! 260: /* ! 261: ** KNOWS -- predicate telling if user has already been informed. ! 262: ** ! 263: ** Parameters: ! 264: ** user -- the user who sent this message. ! 265: ** ! 266: ** Returns: ! 267: ** TRUE if 'user' has already been informed that the ! 268: ** recipient is on vacation. ! 269: ** FALSE otherwise. ! 270: ** ! 271: ** Side Effects: ! 272: ** none. ! 273: */ ! 274: ! 275: bool ! 276: knows(user) ! 277: char *user; ! 278: { ! 279: DATUM k, d; ! 280: long now; ! 281: auto long then; ! 282: ! 283: time(&now); ! 284: k.dptr = user; ! 285: k.dsize = strlen(user) + 1; ! 286: d = fetch(k); ! 287: if (d.dptr == NULL) ! 288: return (FALSE); ! 289: ! 290: /* be careful on 68k's and others with alignment restrictions */ ! 291: bcopy((char *) &((struct dbrec *) d.dptr)->sentdate, (char *) &then, sizeof then); ! 292: if (then + Timeout < now) ! 293: return (FALSE); ! 294: return (TRUE); ! 295: } ! 296: /* ! 297: ** SETKNOWS -- set that this user knows about the vacation. ! 298: ** ! 299: ** Parameters: ! 300: ** user -- the user who should be marked. ! 301: ** ! 302: ** Returns: ! 303: ** none. ! 304: ** ! 305: ** Side Effects: ! 306: ** The dbm file is updated as appropriate. ! 307: */ ! 308: ! 309: setknows(user) ! 310: char *user; ! 311: { ! 312: DATUM k, d; ! 313: struct dbrec xrec; ! 314: ! 315: k.dptr = user; ! 316: k.dsize = strlen(user) + 1; ! 317: time(&xrec.sentdate); ! 318: d.dptr = (char *) &xrec; ! 319: d.dsize = sizeof xrec; ! 320: store(k, d); ! 321: } ! 322: /* ! 323: ** SENDMESSAGE -- send a message to a particular user. ! 324: ** ! 325: ** Parameters: ! 326: ** msgf -- filename containing the message. ! 327: ** user -- user who should receive it. ! 328: ** ! 329: ** Returns: ! 330: ** none. ! 331: ** ! 332: ** Side Effects: ! 333: ** sends mail to 'user' using /usr/lib/sendmail. ! 334: */ ! 335: ! 336: sendmessage(msgf, user, myname) ! 337: char *msgf; ! 338: char *user; ! 339: char *myname; ! 340: { ! 341: FILE *f; ! 342: ! 343: /* find the message to send */ ! 344: f = freopen(msgf, "r", stdin); ! 345: if (f == NULL) ! 346: { ! 347: f = freopen("/usr/lib/vacation.def", "r", stdin); ! 348: if (f == NULL) ! 349: syserr("No message to send"); ! 350: } ! 351: ! 352: execl("/usr/lib/sendmail", "sendmail", "-f", myname, user, NULL); ! 353: syserr("Cannot exec /usr/lib/sendmail"); ! 354: } ! 355: /* ! 356: ** INITIALIZE -- initialize the database before leaving for vacation ! 357: ** ! 358: ** Parameters: ! 359: ** none. ! 360: ** ! 361: ** Returns: ! 362: ** none. ! 363: ** ! 364: ** Side Effects: ! 365: ** Initializes the files .vacation.{pag,dir} in the ! 366: ** caller's home directory. ! 367: */ ! 368: ! 369: initialize() ! 370: { ! 371: char *homedir; ! 372: char buf[MAXLINE]; ! 373: extern char *getenv(); ! 374: ! 375: setgid(getgid()); ! 376: setuid(getuid()); ! 377: homedir = getenv("HOME"); ! 378: if (homedir == NULL) ! 379: syserr("No home!"); ! 380: (void) strcpy(buf, homedir); ! 381: (void) strcat(buf, "/.vacation.dir"); ! 382: if (close(creat(buf, 0644)) < 0) ! 383: syserr("Cannot create %s", buf); ! 384: (void) strcpy(buf, homedir); ! 385: (void) strcat(buf, "/.vacation.pag"); ! 386: if (close(creat(buf, 0644)) < 0) ! 387: syserr("Cannot create %s", buf); ! 388: } ! 389: /* ! 390: ** USRERR -- print user error ! 391: ** ! 392: ** Parameters: ! 393: ** f -- format. ! 394: ** p -- first parameter. ! 395: ** ! 396: ** Returns: ! 397: ** none. ! 398: ** ! 399: ** Side Effects: ! 400: ** none. ! 401: */ ! 402: ! 403: usrerr(f, p) ! 404: char *f; ! 405: char *p; ! 406: { ! 407: fprintf(stderr, "vacation: "); ! 408: _doprnt(f, &p, stderr); ! 409: fprintf(stderr, "\n"); ! 410: } ! 411: /* ! 412: ** SYSERR -- print system error ! 413: ** ! 414: ** Parameters: ! 415: ** f -- format. ! 416: ** p -- first parameter. ! 417: ** ! 418: ** Returns: ! 419: ** none. ! 420: ** ! 421: ** Side Effects: ! 422: ** none. ! 423: */ ! 424: ! 425: syserr(f, p) ! 426: char *f; ! 427: char *p; ! 428: { ! 429: fprintf(stderr, "vacation: "); ! 430: _doprnt(f, &p, stderr); ! 431: fprintf(stderr, "\n"); ! 432: exit(EX_USAGE); ! 433: } ! 434: /* ! 435: ** NEWSTR -- copy a string ! 436: ** ! 437: ** Parameters: ! 438: ** s -- the string to copy. ! 439: ** ! 440: ** Returns: ! 441: ** A copy of the string. ! 442: ** ! 443: ** Side Effects: ! 444: ** none. ! 445: */ ! 446: ! 447: char * ! 448: newstr(s) ! 449: char *s; ! 450: { ! 451: char *p; ! 452: extern char *malloc(); ! 453: ! 454: p = malloc(strlen(s) + 1); ! 455: if (p == NULL) ! 456: { ! 457: syserr("newstr: cannot alloc memory"); ! 458: exit(EX_OSERR); ! 459: } ! 460: strcpy(p, s); ! 461: return (p); ! 462: } ! 463: /* ! 464: ** SAMEWORD -- return TRUE if the words are the same ! 465: ** ! 466: ** Ignores case. ! 467: ** ! 468: ** Parameters: ! 469: ** a, b -- the words to compare. ! 470: ** ! 471: ** Returns: ! 472: ** TRUE if a & b match exactly (modulo case) ! 473: ** FALSE otherwise. ! 474: ** ! 475: ** Side Effects: ! 476: ** none. ! 477: */ ! 478: ! 479: bool ! 480: sameword(a, b) ! 481: register char *a, *b; ! 482: { ! 483: char ca, cb; ! 484: ! 485: do ! 486: { ! 487: ca = *a++; ! 488: cb = *b++; ! 489: if (isascii(ca) && isupper(ca)) ! 490: ca = ca - 'A' + 'a'; ! 491: if (isascii(cb) && isupper(cb)) ! 492: cb = cb - 'A' + 'a'; ! 493: } while (ca != '\0' && ca == cb); ! 494: return (ca == cb); ! 495: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.