]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/clients/zleave/zleave.c
import zephyr 3.0~rc2544
[1ts-debian.git] / zephyr / clients / zleave / zleave.c
1 /* This file is part of the Project Athena Zephyr Notification System.
2  * It contains code for the "zleave" command.
3  *
4  *      Created by:     David Jedlinsky
5  *
6  *      $Id: zleave.c 2493 2009-07-13 05:17:23Z kcr@ATHENA.MIT.EDU $
7  *
8  *      Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
9  *      For copying and distribution information, see the file
10  *      "mit-copyright.h". 
11  */
12
13 #include <sysdep.h>
14 #include <zephyr/mit-copyright.h>
15 #include <zephyr/zephyr.h>
16
17 #ifndef lint
18 static const char rcsid_zlocate_c[] = "$Id: zleave.c 2493 2009-07-13 05:17:23Z kcr@ATHENA.MIT.EDU $";
19 #endif /* lint */
20
21 /*
22  * Copyright (c) 1980 Regents of the University of California.
23  * All rights reserved.
24  *
25  * Redistribution and use in source and binary forms are permitted
26  * provided that this notice is preserved and that due credit is given
27  * to the University of California at Berkeley. The name of the University
28  * may not be used to endorse or promote products derived from this
29  * software without specific written prior permission. This software
30  * is provided ``as is'' without express or implied warranty.
31  */
32
33 #ifndef lint
34 char copyright[] =
35 "@(#) Copyright (c) 1980 Regents of the University of California.\n\
36  All rights reserved.\n";
37 #endif /* not lint */
38
39 #define MESSAGE_CLASS "MESSAGE"
40 #define INSTANCE "LEAVE"
41 /*
42  * zleave [[+]hhmm [ -m "Reminder Message" ]]
43  *  or
44  * zleave can[cel]
45  *
46  * Reminds you when you have to leave.
47  * Leave prompts for input and goes away if you hit return.
48  * Messages are sent through Zephyr.  Subscriptions are handled automagically.
49  * It nags you like a mother hen.
50  */
51 char origlogin[20];
52 char tempfile[40];
53 char *whenleave;
54 char *reminder_message = NULL;
55 char buff[100];
56 int use_zephyr=1, oldpid;
57
58 void usage(void);
59 void doalarm(long);
60 void bother(long, char *);
61 void delay(long);
62 int gethm(char *, int *, int*);
63
64 int
65 main(int argc,
66      char **argv)
67 {
68         time_t now;
69         long when, diff;
70         int hours, minutes;
71         char *cp;
72         FILE *fp;
73         struct tm *nv;
74         int port, c;
75         ZSubscription_t sub;
76         
77         if (ZInitialize() != ZERR_NONE) {
78               fprintf(stderr,"No Zephyr! Will write directly to terminal.\n");
79               use_zephyr = 0;
80         }
81         (void) sprintf(tempfile, "/tmp/zleave.%d", (int) getuid());
82
83         if (use_zephyr) {
84                 if ((port = ZGetWGPort()) == -1) {
85                         fprintf(stderr,
86                                 "Can't find WindowGram subscription port.\n");
87                         fprintf(stderr,"Will write directly to terminal.\n");
88                         use_zephyr = 0;
89                 } else {
90                         sub.zsub_class = MESSAGE_CLASS;
91                         sub.zsub_classinst = INSTANCE;
92                         sub.zsub_recipient = ZGetSender();
93                         if (ZSubscribeToSansDefaults(&sub,1,(u_short)port)
94                             != ZERR_NONE) {
95                                 fprintf(stderr,
96                                         "Subscription error!  Writing to your terminal...\n");
97                                 use_zephyr = 0;
98                         } 
99                 }
100         }       
101         if (!use_zephyr) {
102             if ((cp = getlogin()) == NULL) {
103                 fputs("leave: You are not logged in.\n", stderr);
104                 exit(1);
105             }
106             (void) strcpy(origlogin, cp);
107         }
108
109         c = 1;
110         while ((c<argc) && (! reminder_message))
111             if (!strcmp(argv[c++],"-m")) {
112                 if (argv[c])
113                     reminder_message = argv[c];
114                 else
115                     usage();
116             }
117
118         if (!reminder_message)
119             reminder_message = "";
120
121         if (argc < 2) {
122                 printf("When do you have to leave? ");
123                 (void) fflush(stdout);
124                 buff[read(0, buff, sizeof buff)] = 0;
125                 cp = buff;
126         } else
127                 cp = argv[1];
128         if (*cp == '\n')
129                 exit(0);
130         if (*cp == '+') {
131                 cp++;
132                 if (!gethm(cp, &hours, &minutes))
133                         usage();
134                 if (minutes < 0 || minutes > 59)
135                         usage();
136                 diff = 60*hours+minutes;
137                 doalarm(diff);
138                 exit(0);
139         }
140         if (!strcmp(cp, "cancel") || !strcmp(cp, "can")) {
141               if (!(fp = fopen(tempfile,"r"))) {
142                     printf("No zleave is currently running.\n");
143                     exit(0);
144               }
145               if (fscanf(fp, "%d", &oldpid) != 1) {
146                       printf("The zleave pid file is corrupted.\n");
147                       (void) fclose(fp);
148                       exit(0);
149               }
150               (void) fclose(fp);
151               if (kill(oldpid,9))
152                     printf("No zleave is currently running.\n");
153               (void) unlink(tempfile);
154               exit(0);
155         }
156         if (!gethm(cp, &hours, &minutes))
157                 usage();
158         if (hours > 12)
159                 hours -= 12;
160         if (hours == 12)
161                 hours = 0;
162
163         if (hours < 0 || hours > 12 || minutes < 0 || minutes > 59)
164                 usage();
165
166         (void) time(&now);
167         nv = localtime(&now);
168         when = 60*hours+minutes;
169         if (nv->tm_hour > 12)
170                 nv->tm_hour -= 12;      /* do am/pm bit */
171         now = 60 * nv->tm_hour + nv->tm_min;
172         diff = when - now;
173         while (diff < 0)
174                 diff += 12*60;
175         if (diff > 11*60) {
176                 fprintf(stderr, "That time has already passed!\n");
177                 exit(1);
178         }
179
180         doalarm(diff);
181         exit(0);
182 }
183
184 void
185 usage(void)
186 {
187         fprintf(stderr, "usage: zleave [[+]hhmm [-m \"Reminder Message\"]]\n\
188 \tor: zleave can[cel]\n");
189         exit(1);
190 }
191
192 int
193 gethm(char *cp,
194       int *hp,
195       int *mp)
196 {
197         char c;
198         int tod;
199
200         tod = 0;
201         while ((c = *cp++) != '\0') {
202                 if (!isdigit(c))
203                         return(0);
204                 tod = tod * 10 + (c - '0');
205         }
206         *hp = tod / 100;
207         *mp = tod % 100;
208         return(1);
209 }
210
211 void
212 doalarm(long nmins)
213 {
214         time_t daytime;
215         char *msg1, *msg2, *msg3, *msg4;
216         register int i;
217         long slp1, slp2, slp3, slp4;
218         long seconds, gseconds;
219         FILE *fp;
220 #ifdef _POSIX_VERSION
221         struct sigaction sa;
222 #endif
223
224         seconds = 60 * nmins;
225         if (seconds <= 0)
226                 seconds = 1;
227         gseconds = seconds;
228
229         msg1 = "You have to leave in 5 minutes";
230         if (seconds <= 60*5) {
231                 slp1 = 0;
232         } else {
233                 slp1 = seconds - 60*5;
234                 seconds = 60*5;
235         }
236
237         msg2 = "Just one more minute!";
238         if (seconds <= 60) {
239                 slp2 = 0;
240         } else {
241                 slp2 = seconds - 60;
242                 seconds = 60;
243         }
244
245         msg3 = "Time to leave!";
246         slp3 = seconds;
247
248         msg4 = "You're going to be late!";
249         slp4 = 60L;
250
251         (void) time(&daytime);
252         daytime += gseconds;
253         whenleave = ctime(&daytime);
254
255         fp = fopen(tempfile,"r");
256         if (fp) {
257               if (fscanf(fp, "%d", &oldpid) == 1)
258                       if (!kill(oldpid,9))
259                               printf("Old zleave process killed.\n");
260               (void) fclose(fp);
261         }
262         printf("Alarm set for %s", whenleave);
263
264 /* Subscribe to MESSAGE.LEAVE here */
265
266         switch(fork()) {
267             case -1:
268               perror("fork");
269               exit(-1);
270               break;
271             case 0:
272               break;
273             default:
274               exit(0);
275               break;
276         }
277         if (!(fp = fopen(tempfile, "w")))
278           fprintf(stderr, "Cannot open pid file.\n");
279         else {
280               fprintf(fp, "%d\n", getpid());
281               if (fclose(fp) == EOF)
282                       (void) perror("fclose on pid file");
283         }
284
285 #ifdef _POSIX_VERSION
286         sigemptyset(&sa.sa_mask);
287         sa.sa_flags = 0;
288         sa.sa_handler = SIG_IGN;
289         sigaction(SIGINT, &sa, (struct sigaction *)0);
290         sigaction(SIGQUIT, &sa, (struct sigaction *)0);
291         sigaction(SIGTERM, &sa, (struct sigaction *)0);
292         sigaction(SIGTTOU, &sa, (struct sigaction *)0);
293 #else
294         (void) signal(SIGINT, SIG_IGN);
295         (void) signal(SIGQUIT, SIG_IGN);
296         (void) signal(SIGTERM, SIG_IGN);
297         (void) signal(SIGTTOU, SIG_IGN);
298 #endif
299
300         if (slp1)
301                 bother(slp1, msg1);
302         if (slp2)
303                 bother(slp2, msg2);
304         bother(slp3, msg3);
305         for (i = 0; i < 10; i++)
306                 bother(slp4, msg4);
307
308         bother(0L, "That was the last time I'll tell you. Bye.");
309         (void) unlink(tempfile);
310         exit(0);
311 }
312
313 void
314 bother(long slp,
315        char *msg)
316 {
317       ZNotice_t notice;
318       ZNotice_t retnotice;
319       int retval;
320       char *real_message;
321
322       delay(slp);
323
324       if (use_zephyr) {
325             real_message = (char *) malloc(strlen(msg) +
326                                            strlen(reminder_message) + 3);
327             if (real_message == NULL) {
328                 fprintf (stderr, "zleave: out of memory\n");
329                 exit (1);
330             }
331             sprintf(real_message,"%c%s\n%s",'\0',msg,reminder_message);
332
333             (void) memset((char *)&notice, 0, sizeof(notice));
334             notice.z_kind = ACKED;
335             notice.z_port = 0;
336             notice.z_charset = ZCHARSET_UNKNOWN;
337             notice.z_class = MESSAGE_CLASS;
338             notice.z_class_inst = INSTANCE;
339             notice.z_recipient = ZGetSender();
340             notice.z_opcode = "";
341             notice.z_sender = (char *) 0;
342             notice.z_default_format = "\n$2";
343             notice.z_message = real_message;
344             /* +3: initial null, newline, final null */
345             notice.z_message_len = strlen(msg)+strlen(reminder_message)+3;
346             
347             if (ZSendNotice(&notice, ZAUTH) != ZERR_NONE) {
348                   printf("\7\7\7%s\n%s", msg, reminder_message);
349                   use_zephyr = 0;
350             } else
351             if ((retval = ZIfNotice(&retnotice, (struct sockaddr_in *) 0,
352                                     ZCompareUIDPred, 
353                                     (char *)&notice.z_uid)) != ZERR_NONE) {
354                 fprintf(stderr,
355                         "zleave: %s while waiting for acknowledgement\n", 
356                         error_message(retval));
357                 use_zephyr = 0;
358             } else
359             if (retnotice.z_kind == SERVNAK) {
360                 fprintf(stderr,
361                         "zleave: authorization failure while sending\n");
362                 use_zephyr = 0;
363             } else
364             if (retnotice.z_kind != SERVACK || !retnotice.z_message_len) {
365                 fprintf(stderr, "zleave: Detected server failure while receiving acknowledgement\n");
366                 use_zephyr = 0;
367             } else
368             if (strcmp(retnotice.z_message, ZSRVACK_SENT)) {
369                 /* it wasn't sent */
370                 exit(0);
371             }
372             if (!use_zephyr)
373                 exit(1);
374             ZFreeNotice(&retnotice);
375             free(real_message);
376       } else
377 #ifdef __STDC__
378         printf("\a\a\a%s\n%s", msg, reminder_message);
379 #else
380         printf("\7\7\7%s\n%s", msg, reminder_message);
381 #endif
382 }
383
384 /*
385  * delay is like sleep but does it in 100 sec pieces and
386  * knows what zero means.
387  */
388 void
389 delay(long secs)
390 {
391         long n;
392         register char *l;
393
394         while (secs > 0) {
395                 n = 100;
396                 if (secs < n)
397                         n = secs;
398                 secs -= n;
399                 if (n > 0)
400                         sleep((unsigned) n);
401                 if (!use_zephyr) {
402                     l = getlogin();
403                     if (l == NULL)
404                         exit(0);
405                     if (strcmp(origlogin, l) != 0)
406                         exit(0);
407                 }
408         }
409 }
410
411 #ifndef HAVE_GETLOGIN
412 char *getlogin() {
413 #include <utmp.h>
414
415         static struct utmp ubuf;
416         int ufd;
417
418         ufd = open("/etc/utmp",0);
419         seek(ufd, ttyn(0)*sizeof(ubuf), 0);
420         read(ufd, &ubuf, sizeof(ubuf));
421         ubuf.ut_name[sizeof(ubuf.ut_name)] = 0;
422         return(&ubuf.ut_name);
423 }
424 #endif