[9] | 1 | /* Usage: leave [ [+] hh[:]mm ]
|
---|
| 2 | *
|
---|
| 3 | * Author: Terrence W. Holm
|
---|
| 4 | *
|
---|
| 5 | * Revision:
|
---|
| 6 | * Fred van Kempen, MINIX User Group Holland
|
---|
| 7 | * -adapted to MSS
|
---|
| 8 | * -adapted to new utmp database
|
---|
| 9 | * -adapted to POSIX (MINIX 1.5)
|
---|
| 10 | * Michael Temari, <temari@ix.netcom.com>
|
---|
| 11 | * -use localtime/mktime to fix bug with DST
|
---|
| 12 | */
|
---|
| 13 |
|
---|
| 14 | #include <sys/types.h>
|
---|
| 15 | #include <signal.h>
|
---|
| 16 | #include <time.h>
|
---|
| 17 | #include <utmp.h>
|
---|
| 18 | #include <stdlib.h>
|
---|
| 19 | #include <string.h>
|
---|
| 20 | #include <unistd.h>
|
---|
| 21 | #include <stdio.h>
|
---|
| 22 |
|
---|
| 23 |
|
---|
| 24 | #define Min(a,b) ((a<b) ? a : b)
|
---|
| 25 |
|
---|
| 26 | #define STRING 80 /* lots of room for an argument */
|
---|
| 27 | #define MIN 60L /* seconds per minute */
|
---|
| 28 | #define HOUR (60L*60L) /* seconds per hour */
|
---|
| 29 |
|
---|
| 30 | /* Set the following to your personal preferences for the
|
---|
| 31 | * time and contents of warnings.
|
---|
| 32 | */
|
---|
| 33 | #define INTERVALS 13 /* size of intervals[] */
|
---|
| 34 | #define WARNINGS 4 /* size of warnings[] */
|
---|
| 35 |
|
---|
| 36 |
|
---|
| 37 | static char *Version = "@(#) LEAVE 1.4 (01/09/90)";
|
---|
| 38 | static int intervals[INTERVALS] = {
|
---|
| 39 | -5 * MIN,
|
---|
| 40 | -1 * MIN,
|
---|
| 41 | 0,
|
---|
| 42 | MIN,
|
---|
| 43 | 2 * MIN,
|
---|
| 44 | 3 * MIN,
|
---|
| 45 | 4 * MIN,
|
---|
| 46 | 5 * MIN,
|
---|
| 47 | 6 * MIN,
|
---|
| 48 | 7 * MIN,
|
---|
| 49 | 8 * MIN,
|
---|
| 50 | 9 * MIN,
|
---|
| 51 | 10 * MIN
|
---|
| 52 | };
|
---|
| 53 | static char *warnings[WARNINGS] = {
|
---|
| 54 | "You have to leave within 5 minutes",
|
---|
| 55 | "Just one more minute!",
|
---|
| 56 | "Time to leave!",
|
---|
| 57 | "You're going to be late!" /* for all subsequent warnings */
|
---|
| 58 | };
|
---|
| 59 |
|
---|
| 60 |
|
---|
| 61 | _PROTOTYPE(int main, (int argc, char **argv));
|
---|
| 62 | _PROTOTYPE(void Usage, (void));
|
---|
| 63 | _PROTOTYPE(void Get_Hour_Min, (char *when, int *hour, int *min));
|
---|
| 64 | _PROTOTYPE(int Still_Logged_On, (char *user, char *tty));
|
---|
| 65 |
|
---|
| 66 | void Usage()
|
---|
| 67 | {
|
---|
| 68 | fprintf(stderr, "Usage: leave [[+]hh[:]mm]\n");
|
---|
| 69 | exit(1);
|
---|
| 70 | }
|
---|
| 71 |
|
---|
| 72 |
|
---|
| 73 | void Get_Hour_Min(when, hour, min)
|
---|
| 74 | char *when;
|
---|
| 75 | int *hour;
|
---|
| 76 | int *min;
|
---|
| 77 | {
|
---|
| 78 | int hour_min;
|
---|
| 79 | int just_min = 0;
|
---|
| 80 |
|
---|
| 81 | switch (sscanf(when, "%d:%d", &hour_min, &just_min)) {
|
---|
| 82 | case 1:
|
---|
| 83 | *hour = hour_min / 100;
|
---|
| 84 | *min = hour_min % 100;
|
---|
| 85 | break;
|
---|
| 86 | case 2:
|
---|
| 87 | *hour = hour_min;
|
---|
| 88 | *min = just_min;
|
---|
| 89 | break;
|
---|
| 90 | default:
|
---|
| 91 | Usage();
|
---|
| 92 | }
|
---|
| 93 |
|
---|
| 94 | if (hour_min < 0 || just_min < 0 || *min > 59) Usage();
|
---|
| 95 | }
|
---|
| 96 |
|
---|
| 97 |
|
---|
| 98 | int Still_Logged_On(user, tty)
|
---|
| 99 | char *user;
|
---|
| 100 | char *tty;
|
---|
| 101 | {
|
---|
| 102 | FILE *f;
|
---|
| 103 | struct utmp login;
|
---|
| 104 |
|
---|
| 105 | if ((f = fopen(UTMP, "r")) == NULL)
|
---|
| 106 | /* no login/logout records kept */
|
---|
| 107 | return(1);
|
---|
| 108 |
|
---|
| 109 | while (fread(&login, sizeof(struct utmp), (size_t)1, f) == 1) {
|
---|
| 110 | if (!strncmp(login.ut_line, tty, (size_t)8))
|
---|
| 111 | if (!strncmp(login.ut_name, user, (size_t)8)) {
|
---|
| 112 | fclose(f);
|
---|
| 113 | return(1);
|
---|
| 114 | } else {
|
---|
| 115 | fclose(f);
|
---|
| 116 | return(0);
|
---|
| 117 | }
|
---|
| 118 | }
|
---|
| 119 | fclose(f);
|
---|
| 120 | return(0);
|
---|
| 121 | }
|
---|
| 122 |
|
---|
| 123 |
|
---|
| 124 | int main(argc, argv)
|
---|
| 125 | int argc;
|
---|
| 126 | char *argv[];
|
---|
| 127 | {
|
---|
| 128 | char when[STRING];
|
---|
| 129 | time_t now = time((time_t *)0);
|
---|
| 130 | time_t leave, delta;
|
---|
| 131 | struct tm *tm;
|
---|
| 132 | int hour, min;
|
---|
| 133 | int pid, i;
|
---|
| 134 | char *user = cuserid( (char *)NULL);
|
---|
| 135 | char *tty = ttyname(0) + 5;
|
---|
| 136 |
|
---|
| 137 | /* get the argument string "when" either from stdin, or argv */
|
---|
| 138 | if (argc <= 1) {
|
---|
| 139 | printf("When do you have to leave? ");
|
---|
| 140 | fflush(stdout);
|
---|
| 141 | if (fgets(when, STRING, stdin) == NULL || when[0] == '\n') exit(0);
|
---|
| 142 | } else {
|
---|
| 143 | strcpy(when, argv[1]);
|
---|
| 144 | if (argc > 2) strcat(when, argv[2]);
|
---|
| 145 | }
|
---|
| 146 |
|
---|
| 147 | /* determine the leave time from the current time and "when" */
|
---|
| 148 | tm = localtime(&now);
|
---|
| 149 | if (when[0] == '+') {
|
---|
| 150 | Get_Hour_Min(&when[1], &hour, &min);
|
---|
| 151 | tm->tm_hour += hour;
|
---|
| 152 | tm->tm_min += min;
|
---|
| 153 | leave = mktime(tm);
|
---|
| 154 | } else {
|
---|
| 155 | /* user entered an absolute time */
|
---|
| 156 | Get_Hour_Min(&when[0], &hour, &min);
|
---|
| 157 | tm->tm_hour = hour;
|
---|
| 158 | tm->tm_min = min;
|
---|
| 159 | leave = mktime(tm);
|
---|
| 160 | if (leave < now) {
|
---|
| 161 | printf("That time has already passed!\n");
|
---|
| 162 | exit(1);
|
---|
| 163 | }
|
---|
| 164 | }
|
---|
| 165 |
|
---|
| 166 | printf("Alarm set for %s", ctime(&leave));
|
---|
| 167 |
|
---|
| 168 | if ((pid = fork()) == -1) {
|
---|
| 169 | fprintf(stderr, "leave: can not fork\n");
|
---|
| 170 | exit(1);
|
---|
| 171 | }
|
---|
| 172 | if (pid != 0) exit(0);
|
---|
| 173 |
|
---|
| 174 | /* only the child continues on */
|
---|
| 175 | if (user == NULL || tty == NULL) {
|
---|
| 176 | fprintf(stderr, "leave: Can not determine user and terminal name\n");
|
---|
| 177 | exit(1);
|
---|
| 178 | }
|
---|
| 179 | signal(SIGINT, SIG_IGN);
|
---|
| 180 | signal(SIGQUIT, SIG_IGN);
|
---|
| 181 | signal(SIGTERM, SIG_IGN);
|
---|
| 182 |
|
---|
| 183 | for (;;) {
|
---|
| 184 | if (!Still_Logged_On(user, tty)) exit(0);
|
---|
| 185 |
|
---|
| 186 | /* how much longer until the leave time? */
|
---|
| 187 | /* XXX - use difftime all over. */
|
---|
| 188 | delta = leave - time((time_t *)0);
|
---|
| 189 |
|
---|
| 190 | /* which interval are we currently in? */
|
---|
| 191 | for (i = 0; i < INTERVALS; ++i)
|
---|
| 192 | if (delta + intervals[i] > 0) break;
|
---|
| 193 |
|
---|
| 194 | /* if we are within intervals[0] then print a warning If
|
---|
| 195 | * there are more intervals than messages, then use/
|
---|
| 196 | * warnings[WARNINGS-1] for all subsequent messages. */
|
---|
| 197 | if (i > 0)
|
---|
| 198 | printf("\007\r%s\r\n",
|
---|
| 199 | warnings[i > WARNINGS ? WARNINGS - 1 : i - 1]);
|
---|
| 200 |
|
---|
| 201 | if (i == INTERVALS) {
|
---|
| 202 | printf("That was the last time I'll tell you. Bye.\r\n");
|
---|
| 203 | exit(0);
|
---|
| 204 | }
|
---|
| 205 | /* Sleep until the next interval. For long periods, wake up
|
---|
| 206 | * every hour to check if the user is still on (also required
|
---|
| 207 | * because 16 bit ints don't allow long waits). */
|
---|
| 208 | sleep((unsigned) Min(delta + intervals[i], HOUR));
|
---|
| 209 | }
|
---|
| 210 | }
|
---|