]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/clients/zleave/zleave.c
r4275@bucket (orig r265): kcr | 2008-01-21 02:57:32 -0500
[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 const 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         fp = fopen(tempfile,"r");
258         if (fp) {
259               if (fscanf(fp, "%d", &oldpid) == 1)
260                       if (!kill(oldpid,9))
261                               printf("Old zleave process killed.\n");
262               (void) fclose(fp);
263         }
264         printf("Alarm set for %s", whenleave);
265
266 /* Subscribe to MESSAGE.LEAVE here */
267
268         switch(fork()) {
269             case -1:
270               perror("fork");
271               exit(-1);
272               break;
273             case 0:
274               break;
275             default:
276               exit(0);
277               break;
278         }
279         if (!(fp = fopen(tempfile, "w")))
280           fprintf(stderr, "Cannot open pid file.\n");
281         else {
282               fprintf(fp, "%d\n", getpid());
283               if (fclose(fp) == EOF)
284                       (void) perror("fclose on pid file");
285         }
286
287 #ifdef _POSIX_VERSION
288         sigemptyset(&sa.sa_mask);
289         sa.sa_flags = 0;
290         sa.sa_handler = SIG_IGN;
291         sigaction(SIGINT, &sa, (struct sigaction *)0);
292         sigaction(SIGQUIT, &sa, (struct sigaction *)0);
293         sigaction(SIGTERM, &sa, (struct sigaction *)0);
294         sigaction(SIGTTOU, &sa, (struct sigaction *)0);
295 #else
296         (void) signal(SIGINT, SIG_IGN);
297         (void) signal(SIGQUIT, SIG_IGN);
298         (void) signal(SIGTERM, SIG_IGN);
299         (void) signal(SIGTTOU, SIG_IGN);
300 #endif
301
302         if (slp1)
303                 bother(slp1, msg1);
304         if (slp2)
305                 bother(slp2, msg2);
306         bother(slp3, msg3);
307         for (i = 0; i < 10; i++)
308                 bother(slp4, msg4);
309
310         bother(0L, "That was the last time I'll tell you. Bye.");
311         (void) unlink(tempfile);
312         exit(0);
313 }
314
315 void
316 bother(long slp,
317        char *msg)
318 {
319       ZNotice_t notice;
320       ZNotice_t retnotice;
321       int retval;
322       char *real_message;
323
324       delay(slp);
325
326       if (use_zephyr) {
327             real_message = (char *) malloc(strlen(msg) +
328                                            strlen(reminder_message) + 3);
329             if (real_message == NULL) {
330                 fprintf (stderr, "zleave: out of memory\n");
331                 exit (1);
332             }
333             sprintf(real_message,"%c%s\n%s",'\0',msg,reminder_message);
334
335             (void) memset((char *)&notice, 0, sizeof(notice));
336             notice.z_kind = ACKED;
337             notice.z_port = 0;
338             notice.z_class = MESSAGE_CLASS;
339             notice.z_class_inst = INSTANCE;
340             notice.z_recipient = ZGetSender();
341             notice.z_opcode = "";
342             notice.z_sender = (char *) 0;
343             notice.z_default_format = "\n$2";
344             notice.z_message = real_message;
345             /* +3: initial null, newline, final null */
346             notice.z_message_len = strlen(msg)+strlen(reminder_message)+3;
347             
348             if (ZSendNotice(&notice, ZAUTH) != ZERR_NONE) {
349                   printf("\7\7\7%s\n%s", msg, reminder_message);
350                   use_zephyr = 0;
351             } else
352             if ((retval = ZIfNotice(&retnotice, (struct sockaddr_in *) 0,
353                                     ZCompareUIDPred, 
354                                     (char *)&notice.z_uid)) != ZERR_NONE) {
355                 fprintf(stderr,
356                         "zleave: %s while waiting for acknowledgement\n", 
357                         error_message(retval));
358                 use_zephyr = 0;
359             } else
360             if (retnotice.z_kind == SERVNAK) {
361                 fprintf(stderr,
362                         "zleave: authorization failure while sending\n");
363                 use_zephyr = 0;
364             } else
365             if (retnotice.z_kind != SERVACK || !retnotice.z_message_len) {
366                 fprintf(stderr, "zleave: Detected server failure while receiving acknowledgement\n");
367                 use_zephyr = 0;
368             } else
369             if (strcmp(retnotice.z_message, ZSRVACK_SENT)) {
370                 /* it wasn't sent */
371                 exit(0);
372             }
373             if (!use_zephyr)
374                 exit(1);
375             ZFreeNotice(&retnotice);
376             free(real_message);
377       } else
378 #ifdef __STDC__
379         printf("\a\a\a%s\n%s", msg, reminder_message);
380 #else
381         printf("\7\7\7%s\n%s", msg, reminder_message);
382 #endif
383 }
384
385 /*
386  * delay is like sleep but does it in 100 sec pieces and
387  * knows what zero means.
388  */
389 void
390 delay(long secs)
391 {
392         long n;
393         register char *l;
394
395         while (secs > 0) {
396                 n = 100;
397                 if (secs < n)
398                         n = secs;
399                 secs -= n;
400                 if (n > 0)
401                         sleep((unsigned) n);
402                 if (!use_zephyr) {
403                     l = getlogin();
404                     if (l == NULL)
405                         exit(0);
406                     if (strcmp(origlogin, l) != 0)
407                         exit(0);
408                 }
409         }
410 }
411
412 #ifndef HAVE_GETLOGIN
413 char *getlogin() {
414 #include <utmp.h>
415
416         static struct utmp ubuf;
417         int ufd;
418
419         ufd = open("/etc/utmp",0);
420         seek(ufd, ttyn(0)*sizeof(ubuf), 0);
421         read(ufd, &ubuf, sizeof(ubuf));
422         ubuf.ut_name[sizeof(ubuf.ut_name)] = 0;
423         return(&ubuf.ut_name);
424 }
425 #endif