|
|
1.1 root 1: /*
2: * calendar
3: * Reminder utililty: read calendar files and lines with dates matching
4: * the current date or the date specified in the option string.
5: */
6:
7: #include <stdio.h>
8: #include <sys/types.h>
9: #include <time.h>
10: #include <sys/timeb.h>
11: #include <string.h>
12: #include <ctype.h>
13:
14: char *message =
15: "Usage: calendar [ -a ] [ -ffile ]... [ -d[date] ] [ -w[date] ] [ -m[month] ]\n\
16: Options:\n\
17: -a Search calendars of all users and send mail.\n\
18: -ffile Search each \"file\" in order given.\n\
19: -d[date] Print all entries matching \"date\".\n\
20: -w[date] Print entries in the week beginning with \"date\".\n\
21: -m[month] Print entries in the given \"month\".\n\
22: The default calendar is $HOME/.calendar. The default date is today.\n\
23: ";
24:
25: char *argv0;
26: int all = 0;
27: int wday;
28: int advance;
29: char CurLine[512];
30: char *CurLinep;
31: char *getenv();
32:
33: enum {NONE, DAY, WEEK, MONTH} mflag;
34:
35: #define CALFILE "/.calendar"
36:
37: main(argc, argv)
38: int argc;
39: char *argv[];
40: {
41: register int arg = 1;
42: register char *cp;
43: char *thisline;
44: char *matchstr;
45: char *filename[10];
46: FILE *fp[10];
47: int matchdate;
48: int foundfiles;
49: int nfiles;
50: int thismonth, thisday, thisyear;
51: int thisdate;
52: char *atsign;
53:
54: argv0 = argv[0];
55: mflag = NONE; /* Default to no match */
56: for (arg = 1; arg < argc; arg++) { /* Read option string */
57: cp = argv[arg];
58: sw: switch (*cp) {
59: case '-':
60: cp++;
61: goto sw;
62: case 'a':
63: all = 1;
64: break;
65: case 'f':
66: filename[arg-1] = ++cp;
67: nfiles++;
68: continue;
69: case 'd':
70: matchstr = ++cp;
71: mflag = DAY;
72: continue;
73: case 'w':
74: matchstr = ++cp;
75: mflag = WEEK;
76: continue;
77: case 'm':
78: matchstr = ++cp;
79: mflag = MONTH;
80: continue;
81: default:
82: fprintf(stderr, "%s: unrecognized option '%c'\n", argv0, *cp);
83: usage();
84: }
85: }
86: if (all)
87: doall();
88: /*
89: * Open files.
90: */
91: if (nfiles) {
92: for (arg = 0; arg < nfiles; arg++ ) {
93: if ((fp[arg] = fopen(filename[arg], "r")) == NULL)
94: fprintf(stderr, "cannot open file %s\n", filename[arg]);
95: else
96: foundfiles++;
97: }
98: if (!foundfiles)
99: fatal("cannot open any files specified");
100: } else {
101: char *hp;
102:
103: nfiles = 1;
104: if ((hp = getenv("HOME")) == NULL)
105: fatal("can't find my way back HOME");
106: filename[0] = malloc(strlen(hp) + strlen(CALFILE) + 1);
107: if (filename[0] == NULL)
108: fatal("out of memory");
109: strcpy(filename[0], hp);
110: strcat(filename[0], CALFILE);
111: if ((fp[0] = fopen(filename[0], "r")) == NULL)
112: fatal("cannot open file $HOME/.calendar");
113: }
114: /*
115: * Find match condition from options or current date
116: */
117: switch (mflag) {
118: case NONE:
119: matchdate = current(0);
120: break;
121: case DAY:
122: case WEEK:
123: if (*matchstr == '\0')
124: matchdate = current(0);
125: else {
126: strncpy(CurLine, matchstr, sizeof(CurLine));
127: CurLinep = &CurLine[0];
128: if ((thismonth = findmon()) == -1)
129: fatal("invalid month in match date");
130: if ((thisday = findday()) == -1)
131: fatal("invalid day in match date");
132: if ((thisyear = findyear()) == -1)
133: thisyear = current(1);
134: matchdate = date(thisday, thismonth, thisyear);
135: }
136: break;
137: case MONTH:
138: if (*matchstr == '\0')
139: matchdate = current(2);
140: else {
141: strncpy(CurLine, matchstr, sizeof(CurLine));
142: CurLinep = &CurLine[0];
143: if ((matchdate = findmon()) == -1)
144: fatal("invalid month in match date");
145: }
146: break;
147: }
148: /*
149: * Read the calendar files, print matched lines.
150: */
151: for (arg = 0; arg < nfiles; arg++) {
152: if (fp[arg] == NULL)
153: continue;
154: while ((thisline = fgets(CurLine,sizeof(CurLine),fp[arg]))!=NULL) {
155: CurLinep = &CurLine[0];
156: advance = 0;
157: if ((atsign = strchr(CurLinep, '@')) != NULL)
158: advance = atoi(atsign + 1);
159: if ((thismonth = findmon()) == -1)
160: thismonth = 0;
161: if ((thisday = findday()) == -1)
162: thisday = 0;
163: if ((thisyear = findyear()) == -1)
164: thisyear = current(1);
165: thisdate = date(thisday, thismonth, thisyear);
166: if (thisdate >= matchdate &&
167: thisdate <= matchdate + advance)
168: printf("%s", thisline);
169: else switch (mflag) {
170: case NONE:
171: if (wday == 6)
172: if (thisdate == matchdate ||
173: thisdate == matchdate + 1 ||
174: thisdate == matchdate + 2 ||
175: thisdate == matchdate + 3)
176: printf("%s", thisline);
177: if (wday == 7)
178: if (thisdate == matchdate ||
179: thisdate == matchdate + 1 ||
180: thisdate == matchdate + 2)
181: printf("%s", thisline);
182: if (0 <= wday && wday < 6)
183: if (thisdate == matchdate ||
184: thisdate == matchdate + 1)
185: printf("%s", thisline);
186: break;
187: case DAY:
188: if (thisdate == matchdate)
189: printf("%s", thisline);
190: break;
191: case WEEK:
192: if (matchdate <= thisdate &&
193: thisdate <= matchdate+7)
194: printf("%s", thisline);
195: break;
196: case MONTH:
197: if (thismonth == matchdate)
198: printf("%s", thisline);
199: break;
200: }
201: thisline = NULL;
202: }
203: }
204: }
205:
206: usage()
207: {
208: fprintf(stderr, "%s", message);
209: exit(1);
210: }
211:
212: fatal(str)
213: char *str;
214: {
215: fprintf(stderr, "%s: %r\n", argv0, &str);
216: exit(1);
217: }
218:
219: int
220: findmon()
221: {
222: register int i;
223: register int month;
224: register char *t;
225: static char tbuf[100];
226: static char *mon[12] = {
227: "[Jj][Aa][Nn][Uu. :1-9]",
228: "[Ff][Ee][Bb][Rr. :1-9]",
229: "[Mm][Aa][Rr][Cc. :1-9]",
230: "[Aa][Pp][Rr][Ii. :1-9]",
231: "[Mm][Aa][Yy][ :1-9]",
232: "[Jj][Uu][Nn][Ee. :1-9]",
233: "[Jj][Uu][Ll][Yy. :1-9]",
234: "[Aa][Uu][Gg][Uu. :1-9]",
235: "[Ss][Ee][Pp][Tt. :1-9]",
236: "[Oo][Cc][Tt][Oo. :1-9]",
237: "[Nn][Oo][Vv][Ee. :1-9]",
238: "[Dd][Ee][Cc][Ee. :1-9]"
239: };
240:
241: t = &tbuf[0];
242: for (i = 0;
243: ((*t = CurLinep[i]) != ':') && (*t != '\n') && (*t != '\0');
244: i++)
245: ++t;
246: t[1] = '\0';
247: t = &tbuf[0];
248:
249: month = 0;
250: for (i = 0; i <= 11; i++) /* Look for month in word form. */
251: if (pnmatch(t, mon[i], 1)) {
252: month = i+1;
253: break;
254: }
255: if (month == 0) { /* Month must be in numerical form */
256: for (; *t && !isdigit(*t); t++)
257: CurLinep++;
258: while (*t && isdigit(*t)) {
259: month = 10*month + *t++ - '0';
260: CurLinep++;
261: }
262: CurLinep++; /* Truncate global line pointer */
263: }
264: if (month == 0 || month > 12)
265: month = -1;
266: return (month);
267: }
268:
269: findday()
270: {
271: register int day = 0;
272:
273: for (; *CurLinep && !isdigit(*CurLinep); CurLinep++);
274: ;
275: while (*CurLinep && isdigit(*CurLinep))
276: day = 10*day + *CurLinep++ - '0';
277: if (day == 0 || day > 31) /* Invalid day of the month */
278: day = -1;
279: return (day);
280: }
281:
282: findyear()
283: {
284: register int c;
285: register int year;
286:
287: year = 0;
288: for (; (c = *CurLinep) != '\0' && !isdigit(c); CurLinep++)
289: if (c == '\n' || c == ':' || c == '\0')
290: break;
291: while (isdigit(*CurLinep))
292: year = 10*year + *CurLinep++ -'0';
293: if (year >= 83 && year <= 99)
294: year += 1900;
295: else if (year < 1990 || year > 3000)
296: year = -1;
297: return(year);
298: }
299:
300: int
301: current(opt)
302: int opt;
303: {
304: struct tm *stimep;
305: time_t timep;
306: int retval;
307:
308: time(&timep);
309: stimep = localtime(&timep);
310: switch (opt) {
311: case 0:
312: retval = date(stimep->tm_mday, stimep->tm_mon+1, stimep
313: ->tm_year+1900);
314: wday = stimep->tm_wday;
315: break;
316: case 1:
317: retval = stimep->tm_year+1900;
318: break;
319: case 2:
320: retval = stimep->tm_mon+1;
321: break;
322: default:
323: fatal("bad opt to current");
324: }
325: return (retval);
326: }
327:
328: int
329: date(day, month, year)
330: int day, month, year;
331: {
332: int date=0;
333: register int i;
334: static int m[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
335:
336: if (year == 0)
337: year = current(1);
338: for (i = 0; i < month-1; i++)
339: date += m[i];
340: date += day;
341: if ((year%4) == 0 && month > 2 && (year%100) != 0)
342: date++;
343: for (i = 1984; i < year; i++) {
344: if ((i%4) == 0)
345: date += 366;
346: else
347: date += 365;
348: }
349: return (date);
350: }
351:
352: doall()
353: {
354: register FILE *fp;
355: static char pline[256]; /* Current line in passwd file */
356: static char uname[32];
357: static char ucalfile[128];
358: static char cmd[128];
359: register char *cp1;
360: char *cp2, *cp3;
361: int i;
362:
363: if ((fp = fopen("/etc/passwd", "r")) == NULL)
364: fatal("cannot open /etc/passwd");
365: while ((fgets(&pline[0],sizeof(pline),fp) != NULL) && *pline) {
366: for (cp1 = &pline[0]; *cp1 != '\0'; cp1++)
367: if (*cp1 == '\n') {
368: *cp1 = '\0';
369: break;
370: }
371: cp1 = &pline[0];
372: for (cp2 = &uname[0]; *cp1 != '\0' && *cp1 != ':'; )
373: *cp2++ = *cp1++;
374: *cp2 = '\0';
375: for (i = 0; i < 4 && *cp1 != '\0'; i++)
376: for (cp1++; *cp1 != '\0' && *cp1 != ':'; cp1++)
377: ;
378: cp1++;
379: cp3 = &ucalfile[0];
380: for (; *cp1 != '\0' && *cp1 != ':'; )
381: *cp3++ = *cp1++;
382: *cp3 = '\0';
383: if (ucalfile[0] == '\0')
384: continue;
385: strcat(ucalfile, "/.calendar");
386: if (open(ucalfile, 0) >= 0) { /* file is readable */
387: strcpy(cmd, argv0);
388: strcat(cmd, " -f");
389: strcat(cmd, ucalfile);
390: strcat(cmd, " | /bin/mail ");
391: strcat(cmd, uname);
392: system(cmd);
393: }
394: }
395: exit(0);
396: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.