|
|
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.