|
|
1.1 root 1: # include <pwd.h>
2: # include <stdio.h>
3: # include <sysexits.h>
4: # include <ctype.h>
5: # include "useful.h"
6: # include "userdbm.h"
7:
8: SCCSID(@(#)vacation.c 4.1 7/25/83);
9:
10: /*
11: ** VACATION -- return a message to the sender when on vacation.
12: **
13: ** This program could be invoked as a message receiver
14: ** when someone is on vacation. It returns a message
15: ** specified by the user to whoever sent the mail, taking
16: ** care not to return a message too often to prevent
17: ** "I am on vacation" loops.
18: **
19: ** For best operation, this program should run setuid to
20: ** root or uucp or someone else that sendmail will believe
21: ** a -f flag from. Otherwise, the user must be careful
22: ** to include a header on his .vacation.msg file.
23: **
24: ** Positional Parameters:
25: ** the user to collect the vacation message from.
26: **
27: ** Flag Parameters:
28: ** -I initialize the database.
29: ** -tT set the timeout to T. messages arriving more
30: ** often than T will be ignored to avoid loops.
31: **
32: ** Side Effects:
33: ** A message is sent back to the sender.
34: **
35: ** Author:
36: ** Eric Allman
37: ** UCB/INGRES
38: */
39:
40: # define MAXLINE 256 /* max size of a line */
41: # define MAXNAME 128 /* max size of one name */
42:
43: # define ONEWEEK (60L*60L*24L*7L)
44:
45: time_t Timeout = ONEWEEK; /* timeout between notices per user */
46:
47: struct dbrec
48: {
49: long sentdate;
50: };
51:
52: main(argc, argv)
53: char **argv;
54: {
55: char *from;
56: register char *p;
57: struct passwd *pw;
58: char *homedir;
59: char *myname;
60: char buf[MAXLINE];
61: extern struct passwd *getpwnam();
62: extern char *newstr();
63: extern char *getfrom();
64: extern bool knows();
65: extern time_t convtime();
66:
67: /* process arguments */
68: while (--argc > 0 && (p = *++argv) != NULL && *p == '-')
69: {
70: switch (*++p)
71: {
72: case 'I': /* initialize */
73: initialize();
74: exit(EX_OK);
75:
76: case 't': /* set timeout */
77: Timeout = convtime(++p);
78: break;
79:
80: default:
81: usrerr("Unknown flag -%s", p);
82: exit(EX_USAGE);
83: }
84: }
85:
86: /* verify recipient argument */
87: if (argc != 1)
88: {
89: usrerr("Usage: vacation username (or) vacation -I");
90: exit(EX_USAGE);
91: }
92:
93: myname = p;
94:
95: /* find user's home directory */
96: pw = getpwnam(myname);
97: if (pw == NULL)
98: {
99: usrerr("Unknown user %s", myname);
100: exit(EX_NOUSER);
101: }
102: homedir = newstr(pw->pw_dir);
103: (void) strcpy(buf, homedir);
104: (void) strcat(buf, "/.vacation");
105: dbminit(buf);
106:
107: /* read message from standard input (just from line) */
108: from = getfrom();
109:
110: /* check if this person is already informed */
111: if (!knows(from))
112: {
113: /* mark this person as knowing */
114: setknows(from);
115:
116: /* send the message back */
117: (void) strcpy(buf, homedir);
118: (void) strcat(buf, "/.vacation.msg");
119: sendmessage(buf, from, myname);
120: /* never returns */
121: }
122: exit (EX_OK);
123: }
124: /*
125: ** GETFROM -- read message from standard input and return sender
126: **
127: ** Parameters:
128: ** none.
129: **
130: ** Returns:
131: ** pointer to the sender address.
132: **
133: ** Side Effects:
134: ** Reads first line from standard input.
135: */
136:
137: char *
138: getfrom()
139: {
140: static char line[MAXLINE];
141: register char *p;
142:
143: /* read the from line */
144: if (fgets(line, sizeof line, stdin) == NULL ||
145: strncmp(line, "From ", 5) != NULL)
146: {
147: usrerr("No initial From line");
148: exit(EX_USAGE);
149: }
150:
151: /* find the end of the sender address and terminate it */
152: p = index(&line[5], ' ');
153: if (p == NULL)
154: {
155: usrerr("Funny From line '%s'", line);
156: exit(EX_USAGE);
157: }
158: *p = '\0';
159:
160: /* return the sender address */
161: return (&line[5]);
162: }
163: /*
164: ** KNOWS -- predicate telling if user has already been informed.
165: **
166: ** Parameters:
167: ** user -- the user who sent this message.
168: **
169: ** Returns:
170: ** TRUE if 'user' has already been informed that the
171: ** recipient is on vacation.
172: ** FALSE otherwise.
173: **
174: ** Side Effects:
175: ** none.
176: */
177:
178: bool
179: knows(user)
180: char *user;
181: {
182: DATUM k, d;
183: long now;
184:
185: time(&now);
186: k.dptr = user;
187: k.dsize = strlen(user) + 1;
188: d = fetch(k);
189: if (d.dptr == NULL || ((struct dbrec *) d.dptr)->sentdate + Timeout < now)
190: return (FALSE);
191: return (TRUE);
192: }
193: /*
194: ** SETKNOWS -- set that this user knows about the vacation.
195: **
196: ** Parameters:
197: ** user -- the user who should be marked.
198: **
199: ** Returns:
200: ** none.
201: **
202: ** Side Effects:
203: ** The dbm file is updated as appropriate.
204: */
205:
206: setknows(user)
207: char *user;
208: {
209: DATUM k, d;
210: struct dbrec xrec;
211:
212: k.dptr = user;
213: k.dsize = strlen(user) + 1;
214: time(&xrec.sentdate);
215: d.dptr = (char *) &xrec;
216: d.dsize = sizeof xrec;
217: store(k, d);
218: }
219: /*
220: ** SENDMESSAGE -- send a message to a particular user.
221: **
222: ** Parameters:
223: ** msgf -- filename containing the message.
224: ** user -- user who should receive it.
225: **
226: ** Returns:
227: ** none.
228: **
229: ** Side Effects:
230: ** sends mail to 'user' using /usr/lib/sendmail.
231: */
232:
233: sendmessage(msgf, user, myname)
234: char *msgf;
235: char *user;
236: char *myname;
237: {
238: FILE *f;
239:
240: /* find the message to send */
241: f = freopen(msgf, "r", stdin);
242: if (f == NULL)
243: {
244: f = freopen("/usr/lib/vacation.def", "r", stdin);
245: if (f == NULL)
246: syserr("No message to send");
247: }
248:
249: execl("/usr/lib/sendmail", "sendmail", "-f", myname, user, NULL);
250: syserr("Cannot exec /usr/lib/sendmail");
251: }
252: /*
253: ** INITIALIZE -- initialize the database before leaving for vacation
254: **
255: ** Parameters:
256: ** none.
257: **
258: ** Returns:
259: ** none.
260: **
261: ** Side Effects:
262: ** Initializes the files .vacation.{pag,dir} in the
263: ** caller's home directory.
264: */
265:
266: initialize()
267: {
268: char *homedir;
269: char buf[MAXLINE];
270:
271: setgid(getgid());
272: setuid(getuid());
273: homedir = getenv("HOME");
274: if (homedir == NULL)
275: syserr("No home!");
276: (void) strcpy(buf, homedir);
277: (void) strcat(buf, "/.vacation.dir");
278: if (close(creat(buf, 0644)) < 0)
279: syserr("Cannot create %s", buf);
280: (void) strcpy(buf, homedir);
281: (void) strcat(buf, "/.vacation.pag");
282: if (close(creat(buf, 0644)) < 0)
283: syserr("Cannot create %s", buf);
284: }
285: /*
286: ** USRERR -- print user error
287: **
288: ** Parameters:
289: ** f -- format.
290: ** p -- first parameter.
291: **
292: ** Returns:
293: ** none.
294: **
295: ** Side Effects:
296: ** none.
297: */
298:
299: usrerr(f, p)
300: char *f;
301: char *p;
302: {
303: fprintf(stderr, "vacation: ");
304: _doprnt(f, &p, stderr);
305: fprintf(stderr, "\n");
306: }
307: /*
308: ** SYSERR -- print system error
309: **
310: ** Parameters:
311: ** f -- format.
312: ** p -- first parameter.
313: **
314: ** Returns:
315: ** none.
316: **
317: ** Side Effects:
318: ** none.
319: */
320:
321: syserr(f, p)
322: char *f;
323: char *p;
324: {
325: fprintf(stderr, "vacation: ");
326: _doprnt(f, &p, stderr);
327: fprintf(stderr, "\n");
328: exit(EX_USAGE);
329: }
330: /*
331: ** NEWSTR -- copy a string
332: **
333: ** Parameters:
334: ** s -- the string to copy.
335: **
336: ** Returns:
337: ** A copy of the string.
338: **
339: ** Side Effects:
340: ** none.
341: */
342:
343: char *
344: newstr(s)
345: char *s;
346: {
347: char *p;
348:
349: p = malloc(strlen(s) + 1);
350: if (p == NULL)
351: {
352: syserr("newstr: cannot alloc memory");
353: exit(EX_OSERR);
354: }
355: strcpy(p, s);
356: return (p);
357: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.