|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983, 1987 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that the above copyright notice and this paragraph are ! 7: * duplicated in all such forms and that any documentation, ! 8: * advertising materials, and other materials related to such ! 9: * distribution and use acknowledge that the software was developed ! 10: * by the University of California, Berkeley. The name of the ! 11: * University may not be used to endorse or promote products derived ! 12: * from this software without specific prior written permission. ! 13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 16: */ ! 17: ! 18: #ifndef lint ! 19: char copyright[] = ! 20: "@(#) Copyright (c) 1983, 1987 Regents of the University of California.\n\ ! 21: All rights reserved.\n"; ! 22: #endif /* not lint */ ! 23: ! 24: #ifndef lint ! 25: static char sccsid[] = "@(#)vacation.c 5.10 (Berkeley) 6/29/88"; ! 26: #endif /* not lint */ ! 27: ! 28: /* ! 29: ** Vacation ! 30: ** Copyright (c) 1983 Eric P. Allman ! 31: ** Berkeley, California ! 32: */ ! 33: ! 34: #include <sys/param.h> ! 35: #include <sys/file.h> ! 36: #include <pwd.h> ! 37: #include <stdio.h> ! 38: #include <ctype.h> ! 39: #include <syslog.h> ! 40: ! 41: /* ! 42: ** VACATION -- return a message to the sender when on vacation. ! 43: ** ! 44: ** This program could be invoked as a message receiver when someone is ! 45: ** on vacation. It returns a message specified by the user to whoever ! 46: ** sent the mail, taking care not to return a message too often to ! 47: ** prevent "I am on vacation" loops. ! 48: */ ! 49: ! 50: #define MAXLINE 500 /* max line from mail header */ ! 51: #define PERIOD (60L*60L*24L*7L) /* week between notifications */ ! 52: #define VMSG ".vacation.msg" /* vacation message */ ! 53: #define VACAT ".vacation" /* dbm's database prefix */ ! 54: #define VDIR ".vacation.dir" /* dbm's DB prefix, part 1 */ ! 55: #define VPAG ".vacation.pag" /* dbm's DB prefix, part 2 */ ! 56: ! 57: typedef struct alias { ! 58: struct alias *next; ! 59: char *name; ! 60: } ALIAS; ! 61: ALIAS *names; ! 62: ! 63: static char from[MAXLINE]; /* sender's address */ ! 64: ! 65: main(argc, argv) ! 66: int argc; ! 67: char **argv; ! 68: { ! 69: extern int optind; ! 70: extern char *optarg; ! 71: struct passwd *pw; ! 72: ALIAS *cur; ! 73: int ch, iflag; ! 74: char *malloc(); ! 75: uid_t getuid(); ! 76: ! 77: iflag = 0; ! 78: while ((ch = getopt(argc, argv, "a:Ii")) != EOF) ! 79: switch((char)ch) { ! 80: case 'a': /* alias */ ! 81: if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS)))) ! 82: break; ! 83: cur->name = optarg; ! 84: cur->next = names; ! 85: names = cur; ! 86: break; ! 87: case 'i': /* init the database */ ! 88: case 'I': /* backward compatible */ ! 89: iflag = 1; ! 90: break; ! 91: case '?': ! 92: default: ! 93: goto usage; ! 94: } ! 95: argc -= optind; ! 96: argv += optind; ! 97: ! 98: if (argc != 1) { ! 99: if (!iflag) { ! 100: usage: syslog(LOG_ERR, "uid %u: usage: vacation [-i] [-a alias] login\n", getuid()); ! 101: exit(1); ! 102: } ! 103: if (!(pw = getpwuid(getuid()))) { ! 104: syslog(LOG_ERR, "vacation: no such user uid %u.\n", getuid()); ! 105: exit(1); ! 106: } ! 107: } ! 108: else if (!(pw = getpwnam(*argv))) { ! 109: syslog(LOG_ERR, "vacation: no such user %s.\n", *argv); ! 110: exit(1); ! 111: } ! 112: if (chdir(pw->pw_dir)) { ! 113: syslog(LOG_ERR, "vacation: no such directory %s.\n", pw->pw_dir); ! 114: exit(1); ! 115: } ! 116: ! 117: if (iflag) { ! 118: initialize(); ! 119: exit(0); ! 120: } ! 121: ! 122: if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS)))) ! 123: exit(1); ! 124: cur->name = pw->pw_name; ! 125: cur->next = names; ! 126: names = cur; ! 127: ! 128: readheaders(); ! 129: ! 130: if (access(VDIR, F_OK)) ! 131: initialize(); ! 132: else ! 133: dbminit(VACAT); ! 134: ! 135: if (!recent()) { ! 136: setreply(); ! 137: sendmessage(pw->pw_name); ! 138: } ! 139: exit(0); ! 140: } ! 141: ! 142: /* ! 143: * readheaders -- ! 144: * read mail headers ! 145: */ ! 146: static ! 147: readheaders() ! 148: { ! 149: register ALIAS *cur; ! 150: register char *p; ! 151: int tome, cont; ! 152: char buf[MAXLINE], *strcpy(), *index(); ! 153: ! 154: cont = tome = 0; ! 155: while (fgets(buf, sizeof(buf), stdin) && *buf != '\n') ! 156: switch(*buf) { ! 157: case 'F': /* "From " */ ! 158: cont = 0; ! 159: if (!strncmp(buf, "From ", 5)) { ! 160: for (p = buf + 5; *p && *p != ' '; ++p); ! 161: *p = '\0'; ! 162: (void)strcpy(from, buf + 5); ! 163: if (junkmail()) ! 164: exit(0); ! 165: } ! 166: break; ! 167: case 'P': /* "Precedence:" */ ! 168: cont = 0; ! 169: if (strncasecmp(buf, "Precedence", 10) || buf[10] != ':' && buf[10] != ' ' && buf[10] != '\t') ! 170: break; ! 171: if (!(p = index(buf, ':'))) ! 172: break; ! 173: while (*++p && isspace(*p)); ! 174: if (!*p) ! 175: break; ! 176: if (!strncasecmp(p, "junk", 4) || !strncasecmp(p, "bulk", 4)) ! 177: exit(0); ! 178: break; ! 179: case 'C': /* "Cc:" */ ! 180: if (strncmp(buf, "Cc:", 3)) ! 181: break; ! 182: cont = 1; ! 183: goto findme; ! 184: case 'T': /* "To:" */ ! 185: if (strncmp(buf, "To:", 3)) ! 186: break; ! 187: cont = 1; ! 188: goto findme; ! 189: default: ! 190: if (!isspace(*buf) || !cont || tome) { ! 191: cont = 0; ! 192: break; ! 193: } ! 194: findme: for (cur = names; !tome && cur; cur = cur->next) ! 195: tome += nsearch(cur->name, buf); ! 196: } ! 197: if (!tome) ! 198: exit(0); ! 199: if (!*from) { ! 200: syslog(LOG_ERR, "vacation: no initial \"From\" line.\n"); ! 201: exit(1); ! 202: } ! 203: } ! 204: ! 205: /* ! 206: * nsearch -- ! 207: * do a nice, slow, search of a string for a substring. ! 208: */ ! 209: static ! 210: nsearch(name, str) ! 211: register char *name, *str; ! 212: { ! 213: register int len; ! 214: ! 215: for (len = strlen(name); *str; ++str) ! 216: if (*str == *name && !strncasecmp(name, str, len)) ! 217: return(1); ! 218: return(0); ! 219: } ! 220: ! 221: /* ! 222: * junkmail -- ! 223: * read the header and return if automagic/junk/bulk mail ! 224: */ ! 225: static ! 226: junkmail() ! 227: { ! 228: static struct ignore { ! 229: char *name; ! 230: int len; ! 231: } ignore[] = { ! 232: "-REQUEST", 8, "Postmaster", 10, ! 233: "uucp", 4, "MAILER-DAEMON", 13, ! 234: "MAILER", 6, NULL, NULL, ! 235: }; ! 236: register struct ignore *cur; ! 237: register int len; ! 238: register char *p; ! 239: char *index(), *rindex(); ! 240: ! 241: /* ! 242: * This is mildly amusing, and I'm not positive it's right; trying ! 243: * to find the "real" name of the sender, assuming that addresses ! 244: * will be some variant of: ! 245: * ! 246: * From site!site!SENDER%site.domain%[email protected] ! 247: */ ! 248: if (!(p = index(from, '%'))) ! 249: if (!(p = index(from, '@'))) { ! 250: if (p = rindex(from, '!')) ! 251: ++p; ! 252: else ! 253: p = from; ! 254: for (; *p; ++p); ! 255: } ! 256: len = p - from; ! 257: for (cur = ignore; cur->name; ++cur) ! 258: if (len >= cur->len && !strncasecmp(cur->name, p - cur->len, cur->len)) ! 259: return(1); ! 260: return(0); ! 261: } ! 262: ! 263: typedef struct { ! 264: char *dptr; ! 265: int dsize; ! 266: } DATUM; ! 267: ! 268: typedef struct { ! 269: time_t sentdate; ! 270: } DBREC; ! 271: ! 272: /* ! 273: * recent -- ! 274: * find out if user has gotten a vacation message recently. ! 275: */ ! 276: static ! 277: recent() ! 278: { ! 279: DATUM k, d, fetch(); ! 280: time_t now, then, time(); ! 281: ! 282: k.dptr = from; ! 283: k.dsize = strlen(from) + 1; ! 284: d = fetch(k); ! 285: if (d.dptr) { ! 286: /* be careful on machines with alignment restrictions */ ! 287: bcopy((char *)&((DBREC *)d.dptr)->sentdate, (char *)&then, sizeof(then)); ! 288: (void)time(&now); ! 289: if (!then || then + PERIOD > now) ! 290: return(1); ! 291: } ! 292: return(0); ! 293: } ! 294: ! 295: /* ! 296: * setreply -- ! 297: * store that this user knows about the vacation. ! 298: */ ! 299: static ! 300: setreply() ! 301: { ! 302: DBREC xrec; ! 303: DATUM k, d; ! 304: time_t time(); ! 305: ! 306: k.dptr = from; ! 307: k.dsize = strlen(from) + 1; ! 308: (void)time(&xrec.sentdate); ! 309: d.dptr = (char *)&xrec; ! 310: d.dsize = sizeof(xrec); ! 311: store(k, d); ! 312: } ! 313: ! 314: /* ! 315: * sendmessage -- ! 316: * exec sendmail to send the vacation file to sender ! 317: */ ! 318: static ! 319: sendmessage(myname) ! 320: char *myname; ! 321: { ! 322: if (!freopen(VMSG, "r", stdin)) { ! 323: syslog(LOG_ERR, "vacation: no ~%s/%s file.\n", myname, VMSG); ! 324: exit(1); ! 325: } ! 326: execl("/usr/lib/sendmail", "sendmail", "-f", myname, from, NULL); ! 327: syslog(LOG_ERR, "vacation: can't exec /usr/lib/sendmail.\n"); ! 328: exit(1); ! 329: } ! 330: ! 331: /* ! 332: * initialize -- ! 333: * initialize the dbm database ! 334: */ ! 335: static ! 336: initialize() ! 337: { ! 338: extern int errno; ! 339: extern char *sys_errlist[]; ! 340: int fd; ! 341: ! 342: if ((fd = open(VDIR, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) { ! 343: syslog(LOG_ERR, "vacation: %s: %s\n", VDIR, sys_errlist[errno]); ! 344: exit(1); ! 345: } ! 346: (void)close(fd); ! 347: if ((fd = open(VPAG, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) { ! 348: syslog(LOG_ERR, "vacation: %s: %s\n", VPAG, sys_errlist[errno]); ! 349: exit(1); ! 350: } ! 351: (void)close(fd); ! 352: dbminit(VACAT); ! 353: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.