]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/clients/zleave/zleave.c
44831384df400820855a783f4f12a4fbf5f51457
[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 *whenleave;
56 char *reminder_message = NULL;
57 char buff[100];
58 int use_zephyr=1, oldpid;
59
60 void usage(void);
61 void doalarm(long);
62 void bother(long, char *);
63 void delay(long);
64 int gethm(char *, int *, int*);
65
66 int
67 main(int argc,
68      char **argv)
69 {
70         time_t now;
71         long when, diff;
72         int hours, minutes;
73         char *cp;
74         FILE *fp;
75         struct tm *nv;
76         int port, c;
77         ZSubscription_t sub;
78         
79         if (ZInitialize() != ZERR_NONE) {
80               fprintf(stderr,"No Zephyr! Will write directly to terminal.\n");
81               use_zephyr = 0;
82         }
83         (void) sprintf(tempfile, "/tmp/zleave.%d", (int) getuid());
84
85         if (use_zephyr) {
86                 if ((port = ZGetWGPort()) == -1) {
87                         fprintf(stderr,
88                                 "Can't find WindowGram subscription port.\n");
89                         fprintf(stderr,"Will write directly to terminal.\n");
90                         use_zephyr = 0;
91                 } else {
92                         sub.zsub_class = MESSAGE_CLASS;
93                         sub.zsub_classinst = INSTANCE;
94                         sub.zsub_recipient = ZGetSender();
95                         if (ZSubscribeToSansDefaults(&sub,1,(u_short)port)
96                             != ZERR_NONE) {
97                                 fprintf(stderr,
98                                         "Subscription error!  Writing to your terminal...\n");
99                                 use_zephyr = 0;
100                         } 
101                 }
102         }       
103         if (!use_zephyr) {
104             if ((cp = getlogin()) == NULL) {
105                 fputs("leave: You are not logged in.\n", stderr);
106                 exit(1);
107             }
108             (void) strcpy(origlogin, cp);
109         }
110
111         c = 1;
112         while ((c<argc) && (! reminder_message))
113             if (!strcmp(argv[c++],"-m")) {
114                 if (argv[c])
115                     reminder_message = argv[c];
116                 else
117                     usage();
118             }
119
120         if (!reminder_message)
121             reminder_message = "";
122
123         if (argc < 2) {
124                 printf("When do you have to leave? ");
125                 (void) fflush(stdout);
126                 buff[read(0, buff, sizeof buff)] = 0;
127                 cp = buff;
128         } else
129                 cp = argv[1];
130         if (*cp == '\n')
131                 exit(0);
132         if (*cp == '+') {
133                 cp++;
134                 if (!gethm(cp, &hours, &minutes))
135                         usage();
136                 if (minutes < 0 || minutes > 59)
137                         usage();
138                 diff = 60*hours+minutes;
139                 doalarm(diff);
140                 exit(0);
141         }
142         if (!strcmp(cp, "cancel") || !strcmp(cp, "can")) {
143               if (!(fp = fopen(tempfile,"r"))) {
144                     printf("No zleave is currently running.\n");
145                     exit(0);
146               }
147               if (fscanf(fp, "%d", &oldpid) != 1) {
148                       printf("The zleave pid file is corrupted.\n");
149                       (void) fclose(fp);
150                       exit(0);
151               }
152               (void) fclose(fp);
153               if (kill(oldpid,9))
154                     printf("No zleave is currently running.\n");
155               (void) unlink(tempfile);
156               exit(0);
157         }
158         if (!gethm(cp, &hours, &minutes))
159                 usage();
160         if (hours > 12)
161                 hours -= 12;
162         if (hours == 12)
163                 hours = 0;
164
165         if (hours < 0 || hours > 12 || minutes < 0 || minutes > 59)
166                 usage();
167
168         (void) time(&now);
169         nv = localtime(&now);
170         when = 60*hours+minutes;
171         if (nv->tm_hour > 12)
172                 nv->tm_hour -= 12;      /* do am/pm bit */
173         now = 60 * nv->tm_hour + nv->tm_min;
174         diff = when - now;
175         while (diff < 0)
176                 diff += 12*60;
177         if (diff > 11*60) {
178                 fprintf(stderr, "That time has already passed!\n");
179                 exit(1);
180         }
181
182         doalarm(diff);
183         exit(0);
184 }
185
186 void
187 usage(void)
188 {
189         fprintf(stderr, "usage: zleave [[+]hhmm [-m \"Reminder Message\"]]\n\
190 \tor: zleave can[cel]\n");
191         exit(1);
192 }
193
194 int
195 gethm(char *cp,
196       int *hp,
197       int *mp)
198 {
199         char c;
200         int tod;
201
202         tod = 0;
203         while ((c = *cp++) != '\0') {
204                 if (!isdigit(c))
205                         return(0);
206                 tod = tod * 10 + (c - '0');
207         }
208         *hp = tod / 100;
209         *mp = tod % 100;
210         return(1);
211 }
212
213 void
214 doalarm(long nmins)
215 {
216         time_t daytime;
217         char *msg1, *msg2, *msg3, *msg4;
218         register int i;
219         long slp1, slp2, slp3, slp4;
220         long seconds, gseconds;
221         FILE *fp;
222 #ifdef _POSIX_VERSION
223         struct sigaction sa;
224 #endif
225
226         seconds = 60 * nmins;
227         if (seconds <= 0)
228                 seconds = 1;
229         gseconds = seconds;
230
231         msg1 = "You have to leave in 5 minutes";
232         if (seconds <= 60*5) {
233                 slp1 = 0;
234         } else {
235                 slp1 = seconds - 60*5;
236                 seconds = 60*5;
237         }
238
239         msg2 = "Just one more minute!";
240         if (seconds <= 60) {
241                 slp2 = 0;
242         } else {
243                 slp2 = seconds - 60;
244                 seconds = 60;
245         }
246
247         msg3 = "Time to leave!";
248         slp3 = seconds;
249
250         msg4 = "You're going to be late!";
251         slp4 = 60L;
252
253         (void) time(&daytime);
254         daytime += gseconds;
255         whenleave = ctime(&daytime);
256
257         if (fp = fopen(tempfile,"r")) {
258               if (fscanf(fp, "%d", &oldpid) == 1)
259                       if (!kill(oldpid,9))
260                               printf("Old zleave process killed.\n");
261               (void) fclose(fp);
262         }
263         printf("Alarm set for %s", whenleave);
264
265 /* Subscribe to MESSAGE.LEAVE here */
266
267         switch(fork()) {
268             case -1:
269               perror("fork");
270               exit(-1);
271               break;
272             case 0:
273               break;
274             default:
275               exit(0);
276               break;
277         }
278         if (!(fp = fopen(tempfile, "w")))
279           fprintf(stderr, "Cannot open pid file.\n");
280         else {
281               fprintf(fp, "%d\n", getpid());
282               if (fclose(fp) == EOF)
283                       (void) perror("fclose on pid file");
284         }
285
286 #ifdef _POSIX_VERSION
287         sigemptyset(&sa.sa_mask);
288         sa.sa_flags = 0;
289         sa.sa_handler = SIG_IGN;
290         sigaction(SIGINT, &sa, (struct sigaction *)0);
291         sigaction(SIGQUIT, &sa, (struct sigaction *)0);
292         sigaction(SIGTERM, &sa, (struct sigaction *)0);
293         sigaction(SIGTTOU, &sa, (struct sigaction *)0);
294 #else
295         (void) signal(SIGINT, SIG_IGN);
296         (void) signal(SIGQUIT, SIG_IGN);
297         (void) signal(SIGTERM, SIG_IGN);
298         (void) signal(SIGTTOU, SIG_IGN);
299 #endif
300
301         if (slp1)
302                 bother(slp1, msg1);
303         if (slp2)
304                 bother(slp2, msg2);
305         bother(slp3, msg3);
306         for (i = 0; i < 10; i++)
307                 bother(slp4, msg4);
308
309         bother(0L, "That was the last time I'll tell you. Bye.");
310         (void) unlink(tempfile);
311         exit(0);
312 }
313
314 void
315 bother(long slp,
316        char *msg)
317 {
318       ZNotice_t notice;
319       ZNotice_t retnotice;
320       int retval;
321       char *real_message;
322
323       delay(slp);
324
325       if (use_zephyr) {
326             real_message = (char *) malloc(strlen(msg) +
327                                            strlen(reminder_message) + 3);
328             if (real_message == NULL) {
329                 fprintf (stderr, "zleave: out of memory\n");
330                 exit (1);
331             }
332             sprintf(real_message,"%c%s\n%s",'\0',msg,reminder_message);
333
334             (void) memset((char *)&notice, 0, sizeof(notice));
335             notice.z_kind = ACKED;
336             notice.z_port = 0;
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