1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/tc.sched.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */ 2: /* 3: * tc.sched.c: Scheduled command execution 4: * 5: * Karl Kleinpaste: Computer Consoles Inc. 1984 6: */ 7: /*- 8: * Copyright (c) 1980, 1991 The Regents of the University of California. 9: * All rights reserved. 10: * 11: * Redistribution and use in source and binary forms, with or without 12: * modification, are permitted provided that the following conditions 13: * are met: 14: * 1. Redistributions of source code must retain the above copyright 15: * notice, this list of conditions and the following disclaimer. 16: * 2. Redistributions in binary form must reproduce the above copyright 17: * notice, this list of conditions and the following disclaimer in the 18: * documentation and/or other materials provided with the distribution. 19: * 3. All advertising materials mentioning features or use of this software 20: * must display the following acknowledgement: 21: * This product includes software developed by the University of 22: * California, Berkeley and its contributors. 23: * 4. Neither the name of the University nor the names of its contributors 24: * may be used to endorse or promote products derived from this software 25: * without specific prior written permission. 26: * 27: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37: * SUCH DAMAGE. 38: */ 39: #include "config.h" 40: #if !defined(lint) && !defined(pdp11) 41: static char *rcsid() 42: { return "$Id: tc.sched.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; } 43: #endif 44: 45: #include "sh.h" 46: #include "ed.h" 47: 48: extern int just_signaled; 49: 50: struct sched_event { 51: struct sched_event *t_next; 52: long t_when; 53: Char **t_lex; 54: }; 55: static struct sched_event *sched_ptr = NULL; 56: 57: 58: time_t 59: sched_next() 60: { 61: if (sched_ptr) 62: return (sched_ptr->t_when); 63: return ((time_t) - 1); 64: } 65: 66: void 67: dosched(v) 68: register Char **v; 69: { 70: register struct sched_event *tp, *tp1, *tp2; 71: long cur_time; 72: int count, hours, minutes, dif_hour, dif_min; 73: Char *cp; 74: bool relative; /* time specified as +hh:mm */ 75: struct tm *ltp; 76: char *timeline; 77: char *ctime(); 78: 79: v++; 80: cp = *v++; 81: if (cp == NOSTR) { 82: /* print list of scheduled events */ 83: for (count = 1, tp = sched_ptr; tp; count++, tp = tp->t_next) { 84: timeline = ctime(&tp->t_when); 85: timeline[16] = '\0'; 86: xprintf("%6d\t%s\t", count, timeline); 87: blkpr(tp->t_lex); 88: xprintf("\n"); 89: } 90: return; 91: } 92: 93: if (*cp == '-') { 94: /* remove item from list */ 95: if (!sched_ptr) 96: stderror(ERR_NOSCHED); 97: if (*v) 98: stderror(ERR_SCHEDUSAGE); 99: count = atoi(short2str(++cp)); 100: if (count <= 0) 101: stderror(ERR_SCHEDUSAGE); 102: tp = sched_ptr; 103: tp1 = 0; 104: while (--count) { 105: if (tp->t_next == 0) 106: break; 107: else { 108: tp1 = tp; 109: tp = tp->t_next; 110: } 111: } 112: if (count) 113: stderror(ERR_SCHEDEV); 114: if (tp1 == 0) 115: sched_ptr = tp->t_next; 116: else 117: tp1->t_next = tp->t_next; 118: blkfree(tp->t_lex); 119: xfree((ptr_t) tp); 120: return; 121: } 122: 123: /* else, add an item to the list */ 124: if (!*v) 125: stderror(ERR_SCHEDCOM); 126: relative = 0; 127: if (!Isdigit(*cp)) { /* not abs. time */ 128: if (*cp != '+') 129: stderror(ERR_SCHEDUSAGE); 130: cp++, relative++; 131: } 132: minutes = 0; 133: hours = atoi(short2str(cp)); 134: while (*cp && *cp != ':' && *cp != 'a' && *cp != 'p') 135: cp++; 136: if (*cp && *cp == ':') 137: minutes = atoi(short2str(++cp)); 138: if ((hours < 0) || (minutes < 0) || 139: (hours > 23) || (minutes > 59)) 140: stderror(ERR_SCHEDTIME); 141: while (*cp && *cp != 'p' && *cp != 'a') 142: cp++; 143: if (*cp && relative) 144: stderror(ERR_SCHEDREL); 145: if (*cp == 'p') 146: hours += 12; 147: (void) time(&cur_time); 148: ltp = localtime(&cur_time); 149: if (relative) { 150: dif_hour = hours; 151: dif_min = minutes; 152: } 153: else { 154: if ((dif_hour = hours - ltp->tm_hour) < 0) 155: dif_hour += 24; 156: if ((dif_min = minutes - ltp->tm_min) < 0) { 157: dif_min += 60; 158: if ((--dif_hour) < 0) 159: dif_hour = 23; 160: } 161: } 162: tp = (struct sched_event *) xcalloc(1, sizeof *tp); 163: tp->t_when = cur_time - ltp->tm_sec + dif_hour * 3600L + dif_min * 60L; 164: /* use of tm_sec: get to beginning of minute. */ 165: if (!sched_ptr || tp->t_when < sched_ptr->t_when) { 166: tp->t_next = sched_ptr; 167: sched_ptr = tp; 168: } 169: else { 170: tp1 = sched_ptr->t_next; 171: tp2 = sched_ptr; 172: while (tp1 && tp->t_when >= tp1->t_when) { 173: tp2 = tp1; 174: tp1 = tp1->t_next; 175: } 176: tp->t_next = tp1; 177: tp2->t_next = tp; 178: } 179: tp->t_lex = saveblk(v); 180: } 181: 182: /* 183: * Execute scheduled events 184: */ 185: void 186: sched_run() 187: { 188: long cur_time; 189: register struct sched_event *tp, *tp1; 190: struct wordent cmd, *nextword, *lastword; 191: struct command *t; 192: Char **v, *cp; 193: extern Char GettingInput; 194: 195: #ifdef BSDSIGS 196: sigmask_t omask; 197: 198: omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); 199: #else 200: (void) sighold(SIGINT); 201: #endif 202: 203: (void) time(&cur_time); 204: tp = sched_ptr; 205: 206: /* bugfix by: Justin Bur at Universite de Montreal */ 207: /* 208: * this test wouldn't be necessary if this routine were not called before 209: * each prompt (in sh.c). But it is, to catch missed alarms. Someone 210: * ought to fix it all up. -jbb 211: */ 212: if (!(tp && tp->t_when < cur_time)) { 213: #ifdef BSDSIGS 214: (void) sigsetmask(omask); 215: #else 216: (void) sigrelse(SIGINT); 217: #endif 218: return; 219: } 220: 221: if (GettingInput) 222: (void) Cookedmode(); 223: 224: while (tp && tp->t_when < cur_time) { 225: if (seterr) { 226: xfree((char *) seterr); 227: seterr = NULL; 228: } 229: cmd.word = STRNULL; 230: lastword = &cmd; 231: v = tp->t_lex; 232: for (cp = *v; cp; cp = *++v) { 233: nextword = (struct wordent *) xcalloc(1, sizeof cmd); 234: nextword->word = Strsave(cp); 235: lastword->next = nextword; 236: nextword->prev = lastword; 237: lastword = nextword; 238: } 239: lastword->next = &cmd; 240: cmd.prev = lastword; 241: tp1 = tp; 242: sched_ptr = tp = tp1->t_next; /* looping termination cond: */ 243: blkfree(tp1->t_lex); /* straighten out in case of */ 244: xfree((ptr_t) tp1); /* command blow-up. */ 245: 246: /* expand aliases like process() does. */ 247: alias(&cmd); 248: /* build a syntax tree for the command. */ 249: t = syntax(cmd.next, &cmd, 0); 250: if (seterr) 251: stderror(ERR_OLD); 252: /* execute the parse tree. */ 253: execute(t, -1, NULL, NULL); 254: /* done. free the lex list and parse tree. */ 255: freelex(&cmd), freesyn(t); 256: } 257: if (GettingInput && !just_signaled) { /* PWP */ 258: (void) Rawmode(); 259: ClearLines(); /* do a real refresh since something may */ 260: ClearDisp(); /* have printed to the screen */ 261: Refresh(); 262: } 263: just_signaled = 0; 264: 265: #ifdef BSDSIGS 266: (void) sigsetmask(omask); 267: #else 268: (void) sigrelse(SIGINT); 269: #endif 270: }