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