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

Defined functions

getfrom defined in line 166; used 2 times
initialize defined in line 370; used 1 times
  • in line 97
junkmail defined in line 210; used 2 times
knows defined in line 276; used 2 times
main defined in line 75; never used
newstr defined in line 448; used 2 times
sameword defined in line 480; used 6 times
sendmessage defined in line 337; used 1 times
setknows defined in line 310; used 1 times
syserr defined in line 426; used 6 times
usrerr defined in line 404; used 5 times

Defined variables

Debug defined in line 73; used 2 times
SccsId defined in line 12; never used
Timeout defined in line 56; used 1 times

Defined struct's

dbrec defined in line 58; used 4 times

Defined typedef's

bool defined in line 46; used 7 times

Defined macros

FALSE defined in line 49; used 4 times
MAXLINE defined in line 51; used 5 times
MAXNAME defined in line 52; never used
ONEWEEK defined in line 54; used 1 times
  • in line 56
TRUE defined in line 48; used 4 times
Last modified: 1996-10-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1316
Valid CSS Valid XHTML 1.0 Strict