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: }

Defined functions

getfrom defined in line 165; used 2 times
initialize defined in line 369; used 1 times
  • in line 96
junkmail defined in line 209; used 2 times
knows defined in line 275; used 2 times
main defined in line 74; never used
newstr defined in line 447; used 2 times
sameword defined in line 479; used 6 times
sendmessage defined in line 336; used 1 times
setknows defined in line 309; used 1 times
syserr defined in line 425; used 6 times
usrerr defined in line 403; used 5 times

Defined variables

Debug defined in line 72; used 2 times
SccsId defined in line 12; never used

Defined struct's

dbrec defined in line 57; used 4 times

Defined typedef's

bool defined in line 45; used 7 times

Defined macros

FALSE defined in line 48; used 4 times
MAXLINE defined in line 50; used 5 times
MAXNAME defined in line 51; never used
ONEWEEK defined in line 53; used 1 times
  • in line 55
TRUE defined in line 47; used 4 times
Last modified: 1985-07-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2242
Valid CSS Valid XHTML 1.0 Strict