leave.c

Go to the documentation of this file.
00001 /* Usage:       leave [ [+] hh[:]mm ]
00002  *
00003  * Author:      Terrence W. Holm
00004  *
00005  * Revision:
00006  *              Fred van Kempen, MINIX User Group Holland
00007  *               -adapted to MSS
00008  *               -adapted to new utmp database
00009  *               -adapted to POSIX (MINIX 1.5)
00010  *              Michael Temari, <temari@ix.netcom.com>
00011  *               -use localtime/mktime to fix bug with DST
00012  */
00013 
00014 #include <sys/types.h>
00015 #include <signal.h>
00016 #include <time.h>
00017 #include <utmp.h>
00018 #include <stdlib.h>
00019 #include <string.h>
00020 #include <unistd.h>
00021 #include <stdio.h>
00022 
00023 
00024 #define Min(a,b)  ((a<b) ? a : b)
00025 
00026 #define STRING     80           /* lots of room for an argument */
00027 #define MIN        60L          /* seconds per minute */
00028 #define HOUR      (60L*60L)     /* seconds per hour */
00029 
00030 /* Set the following to your personal preferences for the
00031  * time and contents of warnings.
00032  */
00033 #define INTERVALS 13            /* size of intervals[] */
00034 #define WARNINGS  4             /* size of warnings[] */
00035 
00036 
00037 static char *Version = "@(#) LEAVE 1.4 (01/09/90)";
00038 static int intervals[INTERVALS] = {
00039   -5 * MIN,
00040   -1 * MIN,
00041   0,
00042   MIN,
00043   2 * MIN,
00044   3 * MIN,
00045   4 * MIN,
00046   5 * MIN,
00047   6 * MIN,
00048   7 * MIN,
00049   8 * MIN,
00050   9 * MIN,
00051   10 * MIN
00052 };
00053 static char *warnings[WARNINGS] = {
00054   "You have to leave within 5 minutes",
00055   "Just one more minute!",
00056   "Time to leave!",
00057   "You're going to be late!"    /* for all subsequent warnings */
00058 };
00059 
00060 
00061 _PROTOTYPE(int main, (int argc, char **argv));
00062 _PROTOTYPE(void Usage, (void));
00063 _PROTOTYPE(void Get_Hour_Min, (char *when, int *hour, int *min));
00064 _PROTOTYPE(int Still_Logged_On, (char *user, char *tty));
00065 
00066 void Usage()
00067 {
00068    fprintf(stderr, "Usage: leave [[+]hh[:]mm]\n");
00069   exit(1);
00070 }
00071 
00072 
00073 void Get_Hour_Min(when, hour, min)
00074 char *when;
00075 int *hour;
00076 int *min;
00077 {
00078   int hour_min;
00079   int just_min = 0;
00080 
00081   switch (sscanf(when, "%d:%d", &hour_min, &just_min)) {
00082       case 1:
00083         *hour = hour_min / 100;
00084         *min = hour_min % 100;
00085         break;
00086       case 2:
00087         *hour = hour_min;
00088         *min = just_min;
00089         break;
00090       default:
00091         Usage();
00092   }
00093 
00094   if (hour_min < 0 || just_min < 0 || *min > 59) Usage();
00095 }
00096 
00097 
00098 int Still_Logged_On(user, tty)
00099 char *user;
00100 char *tty;
00101 {
00102   FILE *f;
00103   struct utmp login;
00104 
00105   if ((f = fopen(UTMP, "r")) == NULL)
00106         /* no login/logout records kept */
00107         return(1);
00108 
00109   while (fread(&login, sizeof(struct utmp), (size_t)1, f) == 1) {
00110         if (!strncmp(login.ut_line, tty, (size_t)8))
00111                 if (!strncmp(login.ut_name, user, (size_t)8)) {
00112                         fclose(f);
00113                         return(1);
00114                 } else {
00115                         fclose(f);
00116                         return(0);
00117                 }
00118   }
00119   fclose(f);
00120   return(0);
00121 }
00122 
00123 
00124 int main(argc, argv)
00125 int argc;
00126 char *argv[];
00127 {
00128   char when[STRING];
00129   time_t now = time((time_t *)0);
00130   time_t leave, delta;
00131   struct tm *tm;
00132   int hour, min;
00133   int pid, i;
00134   char *user = cuserid( (char *)NULL);
00135   char *tty = ttyname(0) + 5;
00136 
00137   /* get the argument string "when" either from stdin, or argv */
00138   if (argc <= 1) {
00139         printf("When do you have to leave? ");
00140         fflush(stdout);
00141         if (fgets(when, STRING, stdin) == NULL || when[0] == '\n') exit(0);
00142   } else {
00143         strcpy(when, argv[1]);
00144         if (argc > 2) strcat(when, argv[2]);
00145   }
00146 
00147   /* determine the leave time from the current time and "when" */
00148   tm = localtime(&now);
00149   if (when[0] == '+') {
00150         Get_Hour_Min(&when[1], &hour, &min);
00151         tm->tm_hour += hour;
00152         tm->tm_min += min;
00153         leave = mktime(tm);
00154   } else {
00155         /* user entered an absolute time */
00156         Get_Hour_Min(&when[0], &hour, &min);
00157         tm->tm_hour = hour;
00158         tm->tm_min = min;
00159         leave = mktime(tm);
00160         if (leave < now) {
00161                 printf("That time has already passed!\n");
00162                 exit(1);
00163         }
00164   }
00165 
00166   printf("Alarm set for %s", ctime(&leave));
00167 
00168   if ((pid = fork()) == -1) {
00169         fprintf(stderr, "leave: can not fork\n");
00170         exit(1);
00171   }
00172   if (pid != 0) exit(0);
00173 
00174   /* only the child continues on */
00175   if (user == NULL || tty == NULL) {
00176         fprintf(stderr, "leave: Can not determine user and terminal name\n");
00177         exit(1);
00178   }
00179   signal(SIGINT, SIG_IGN);
00180   signal(SIGQUIT, SIG_IGN);
00181   signal(SIGTERM, SIG_IGN);
00182 
00183   for (;;) {
00184         if (!Still_Logged_On(user, tty)) exit(0);
00185 
00186         /* how much longer until the leave time? */
00187         /* XXX - use difftime all over. */
00188         delta = leave - time((time_t *)0);
00189 
00190         /* which interval are we currently in? */
00191         for (i = 0; i < INTERVALS; ++i)
00192                 if (delta + intervals[i] > 0) break;
00193 
00194         /* if we are within intervals[0] then print a warning If
00195          * there are more intervals than messages, then use/
00196          * warnings[WARNINGS-1] for all subsequent messages. */
00197         if (i > 0)
00198                 printf("\007\r%s\r\n",
00199                         warnings[i > WARNINGS ? WARNINGS - 1 : i - 1]);
00200 
00201         if (i == INTERVALS) {
00202                 printf("That was the last time I'll tell you. Bye.\r\n");
00203                 exit(0);
00204         }
00205         /* Sleep until the next interval. For long periods, wake up
00206          * every hour to check if the user is still on (also required
00207          * because 16 bit ints don't allow long waits). */
00208         sleep((unsigned) Min(delta + intervals[i], HOUR));
00209   }
00210 }

Generated on Fri Apr 14 22:57:08 2006 for minix by  doxygen 1.4.6