1 /* $OpenBSD: leave.c,v 1.11 2004/02/02 09:36:12 otto Exp $ */ 2 /* $NetBSD: leave.c,v 1.4 1995/07/03 16:50:13 phil Exp $ */ 3 4 /* 5 * Copyright (c) 1980, 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #ifndef lint 34 static const char copyright[] = 35 "@(#) Copyright (c) 1980, 1988, 1993\n\ 36 The Regents of the University of California. All rights reserved.\n"; 37 #endif /* not lint */ 38 39 #ifndef lint 40 #if 0 41 static char sccsid[] = "@(#)leave.c 8.1 (Berkeley) 6/6/93"; 42 #endif 43 static const char rcsid[] = "$OpenBSD: leave.c,v 1.11 2004/02/02 09:36:12 otto Exp $"; 44 #endif /* not lint */ 45 46 #include <sys/param.h> 47 #include <sys/time.h> 48 #include <ctype.h> 49 #include <err.h> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <unistd.h> 53 54 static __dead void usage(void); 55 static void doalarm(u_int secs); 56 57 #define SECOND 1 58 #define MINUTE (SECOND * 60) 59 #define FIVEMIN (5 * MINUTE) 60 #define HOUR (MINUTE * 60) 61 62 /* 63 * leave [[+]hhmm] 64 * 65 * Reminds you when you have to leave. 66 * Leave prompts for input and goes away if you hit return. 67 * It nags you like a mother hen. 68 */ 69 int 70 main(int argc, char *argv[]) 71 { 72 u_int secs; 73 int hours, minutes; 74 char c, *cp; 75 struct tm *t; 76 time_t now; 77 int plusnow = 0, twentyfour; 78 char buf[50]; 79 80 if (setlinebuf(stdout) != 0) 81 errx(1, "Cannot set stdout to line buffered."); 82 83 if (argc < 2) { 84 (void)fputs("When do you have to leave? ", stdout); 85 cp = fgets(buf, sizeof(buf), stdin); 86 if (cp == NULL || *cp == '\n') 87 exit(0); 88 } else if (argc > 2) 89 usage(); 90 else 91 cp = argv[1]; 92 93 if (*cp == '+') { 94 plusnow = 1; 95 ++cp; 96 } 97 98 for (hours = 0; (c = *cp) && c != '\n'; ++cp) { 99 if (!isdigit(c)) 100 usage(); 101 hours = hours * 10 + (c - '0'); 102 } 103 minutes = hours % 100; 104 hours /= 100; 105 /* determine 24 hours mode */ 106 twentyfour = hours > 12; 107 108 if (minutes < 0 || minutes > 59) 109 usage(); 110 if (plusnow) 111 secs = (hours * HOUR) + (minutes * MINUTE); 112 else { 113 if (hours > 23) 114 usage(); 115 (void)time(&now); 116 t = localtime(&now); 117 while (t->tm_hour > hours || 118 (t->tm_hour == hours && t->tm_min >= minutes)) { 119 if (twentyfour) 120 hours += 24; 121 else 122 hours += 12; 123 } 124 125 secs = (hours - t->tm_hour) * HOUR; 126 secs += (minutes - t->tm_min) * MINUTE; 127 } 128 doalarm(secs); 129 exit(0); 130 } 131 132 static void 133 doalarm(u_int secs) 134 { 135 int bother; 136 time_t daytime; 137 pid_t pid; 138 139 switch (pid = fork()) { 140 case 0: 141 break; 142 case -1: 143 err(1, "Fork failed"); 144 /* NOTREACHED */ 145 default: 146 (void)time(&daytime); 147 daytime += secs; 148 printf("Alarm set for %.16s. (pid %ld)\n", 149 ctime(&daytime), (long)pid); 150 exit(0); 151 } 152 sleep(2); /* let parent print set message */ 153 154 /* 155 * if write fails, we've lost the terminal through someone else 156 * causing a vhangup by logging in. 157 */ 158 if (secs >= FIVEMIN) { 159 sleep(secs - FIVEMIN); 160 if (puts("\a\aYou have to leave in 5 minutes.") == EOF) 161 exit(0); 162 secs = FIVEMIN; 163 } 164 165 if (secs >= MINUTE) { 166 sleep(secs - MINUTE); 167 if (puts("\a\aJust one more minute!") == EOF) 168 exit(0); 169 } 170 171 for (bother = 10; bother--;) { 172 sleep(MINUTE); 173 if (puts("\a\aTime to leave!") == EOF) 174 exit(0); 175 } 176 177 puts("\a\aThat was the last time I'll tell you. Bye."); 178 exit(0); 179 } 180 181 static __dead void 182 usage(void) 183 { 184 fprintf(stderr, "usage: leave [[+]hhmm]\n"); 185 exit(1); 186 } 187