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