tc.sched.c revision 145479
11844Swollman/* $Header: /src/pub/tcsh/tc.sched.c,v 3.21 2004/11/23 02:10:50 christos Exp $ */ 250476Speter/* 31638Srgrimes * tc.sched.c: Scheduled command execution 494940Sru * 51638Srgrimes * Karl Kleinpaste: Computer Consoles Inc. 1984 6103713Smarkm */ 71638Srgrimes/*- 8133653Sru * Copyright (c) 1980, 1991 The Regents of the University of California. 9119607Sru * All rights reserved. 10298503Sngie * 11119607Sru * Redistribution and use in source and binary forms, with or without 12119607Sru * modification, are permitted provided that the following conditions 13119607Sru * are met: 14162210Simp * 1. Redistributions of source code must retain the above copyright 15162210Simp * notice, this list of conditions and the following disclaimer. 16162293Sobrien * 2. Redistributions in binary form must reproduce the above copyright 17162210Simp * notice, this list of conditions and the following disclaimer in the 18162210Simp * documentation and/or other materials provided with the distribution. 19119607Sru * 3. Neither the name of the University nor the names of its contributors 20119607Sru * may be used to endorse or promote products derived from this software 21204027Smarcel * without specific prior written permission. 22179184Sjb * 23228158Sfjoe * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24179184Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25119607Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26179184Sjb * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27119607Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28251512Semaste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29251512Semaste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30251512Semaste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31251512Semaste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32271274Semaste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33251512Semaste * SUCH DAMAGE. 34251512Semaste */ 35251512Semaste#include "sh.h" 36119607Sru 37117034SgordonRCSID("$Id: tc.sched.c,v 3.21 2004/11/23 02:10:50 christos Exp $") 38251512Semaste 39251512Semaste#include "ed.h" 40251512Semaste#include "tw.h" 41251512Semaste#include "tc.h" 42251512Semaste 43119607Sruextern int just_signaled; 44251512Semaste 451638Srgrimesstruct sched_event { 462827Sjkh struct sched_event *t_next; 471638Srgrimes time_t t_when; 482827Sjkh Char **t_lex; 491638Srgrimes}; 50139112Srustatic struct sched_event *sched_ptr = NULL; 511844Swollman 521844Swollman 531638Srgrimestime_t 54255384Sdessched_next() 55255384Sdes{ 56255384Sdes if (sched_ptr) 57255384Sdes return (sched_ptr->t_when); 58251512Semaste return ((time_t) - 1); 59251512Semaste} 60251512Semaste 61251512Semaste/*ARGSUSED*/ 62251512Semastevoid 63251512Semastedosched(v, c) 64251512Semaste Char **v; 65251512Semaste struct command *c; 66251512Semaste{ 67251512Semaste struct sched_event *tp, *tp1, *tp2; 68251512Semaste time_t cur_time; 69251512Semaste int count, hours, minutes, dif_hour, dif_min; 70251512Semaste Char *cp; 7194424Sru int relative; /* time specified as +hh:mm */ 72251512Semaste struct tm *ltp; 73251512Semaste 74251512Semaste USE(c); 7594424Sru/* This is a major kludge because of a gcc linker */ 761638Srgrimes/* Problem. It may or may not be needed for you */ 77248753Semaste#if defined(_MINIX) && !defined(_MINIX_VMD) 78251512Semaste char kludge[10]; 791638Srgrimes extern char *sprintf(); 801638Srgrimes sprintf(kludge, CGETS(24, 1, "kludge")); 811844Swollman#endif /* _MINIX && !_MINIX_VMD */ 821638Srgrimes 83212423Srpaulo v++; 84244915Smarkj cp = *v++; 85251512Semaste if (cp == NULL) { 86244224Semaste Char *fmt; 87251512Semaste if ((fmt = varval(STRsched)) == STRNULL) 8894518Sru fmt = str2short("%h\t%T\t%R\n"); 8994518Sru /* print list of scheduled events */ 9094518Sru for (count = 1, tp = sched_ptr; tp; count++, tp = tp->t_next) { 9194518Sru Char buf[BUFSIZE], sbuf[BUFSIZE]; 9294518Sru blkexpand(tp->t_lex, buf); 93228158Sfjoe tprintf(FMT_SCHED, sbuf, fmt, sizeof(sbuf), 94228124Sfjoe short2str(buf), tp->t_when, (ptr_t) &count); 95228124Sfjoe for (cp = sbuf; *cp;) 9694518Sru xputwchar(*cp++); 97144893Sharti } 981844Swollman return; 9994518Sru } 10094424Sru 10194424Sru if (*cp == '-') { 10294424Sru /* remove item from list */ 1032351Sbde if (!sched_ptr) 10494424Sru stderror(ERR_NOSCHED); 1051638Srgrimes if (*v) 1062351Sbde stderror(ERR_SCHEDUSAGE); 1072351Sbde count = atoi(short2str(++cp)); 1082351Sbde if (count <= 0) 1092351Sbde stderror(ERR_SCHEDUSAGE); 1102351Sbde tp = sched_ptr; 111248742Smarkj tp1 = 0; 11233624Seivind while (--count) { 113212423Srpaulo if (tp->t_next == 0) 114244915Smarkj break; 115251512Semaste else { 116244224Semaste tp1 = tp; 117251512Semaste tp = tp->t_next; 11894497Sru } 11994497Sru } 12094497Sru if (count) 12194410Sru stderror(ERR_SCHEDEV); 12233624Seivind if (tp1 == 0) 123228158Sfjoe sched_ptr = tp->t_next; 124228124Sfjoe else 12594518Sru tp1->t_next = tp->t_next; 126251512Semaste blkfree(tp->t_lex); 1271638Srgrimes xfree((ptr_t) tp); 128244224Semaste return; 1291638Srgrimes } 130251512Semaste 131251512Semaste /* else, add an item to the list */ 132251512Semaste if (!*v) 133251512Semaste stderror(ERR_SCHEDCOM); 134251512Semaste relative = 0; 135251512Semaste if (!Isdigit(*cp)) { /* not abs. time */ 136251512Semaste if (*cp != '+') 137251512Semaste stderror(ERR_SCHEDUSAGE); 138251512Semaste cp++, relative++; 139156813Sru } 14074806Sru minutes = 0; 1411638Srgrimes hours = atoi(short2str(cp)); 142245515Sbrooks while (*cp && *cp != ':' && *cp != 'a' && *cp != 'p') 14374941Sru cp++; 14474941Sru if (*cp && *cp == ':') 1451638Srgrimes minutes = atoi(short2str(++cp)); 146244224Semaste if ((hours < 0) || (minutes < 0) || 1471638Srgrimes (hours > 23) || (minutes > 59)) 148269946Srpaulo stderror(ERR_SCHEDTIME); 149269946Srpaulo while (*cp && *cp != 'p' && *cp != 'a') 150156813Sru cp++; 15196164Sru if (*cp && relative) 15274806Sru stderror(ERR_SCHEDREL); 1531638Srgrimes if (*cp == 'p') 154119607Sru hours += 12; 155119607Sru (void) time(&cur_time); 156251512Semaste ltp = localtime(&cur_time); 157251512Semaste if (relative) { 158119607Sru dif_hour = hours; 159251512Semaste dif_min = minutes; 1601638Srgrimes } 161119607Sru else { 162119607Sru if ((dif_hour = hours - ltp->tm_hour) < 0) 163119607Sru dif_hour += 24; 164119607Sru if ((dif_min = minutes - ltp->tm_min) < 0) { 165125620Sru dif_min += 60; 166125620Sru if ((--dif_hour) < 0) 16755670Sbde dif_hour = 23; 16824750Sbde } 169125620Sru } 170125620Sru tp = (struct sched_event *) xcalloc(1, sizeof *tp); 171279958Sjhb#ifdef _SX 172125620Sru tp->t_when = cur_time - ltp->tm_sec + dif_hour * 3600 + dif_min * 60; 173125620Sru#else /* _SX */ 174279958Sjhb tp->t_when = cur_time - ltp->tm_sec + dif_hour * 3600L + dif_min * 60L; 17594497Sru#endif /* _SX */ 176255431Sdes /* use of tm_sec: get to beginning of minute. */ 177279958Sjhb if (!sched_ptr || tp->t_when < sched_ptr->t_when) { 178239686Sdim tp->t_next = sched_ptr; 179279958Sjhb sched_ptr = tp; 18024750Sbde } 18128945Speter else { 182125620Sru tp1 = sched_ptr->t_next; 183239686Sdim tp2 = sched_ptr; 18424750Sbde while (tp1 && tp->t_when >= tp1->t_when) { 1851638Srgrimes tp2 = tp1; 1861638Srgrimes tp1 = tp1->t_next; 187137614Sru } 188139111Sru tp->t_next = tp1; 189137164Sru tp2->t_next = tp; 190137164Sru } 191137614Sru tp->t_lex = saveblk(v); 192137614Sru} 193137164Sru 19449328Shoek/* 19549328Shoek * Execute scheduled events 19649328Shoek */ 19749328Shoek/*ARGSUSED*/ 19849328Shoekvoid 199125620Srusched_run(n) 20096163Sru int n; 20199343Sru{ 20296163Sru time_t cur_time; 2031638Srgrimes struct sched_event *tp, *tp1; 204100872Sru struct wordent cmd, *nextword, *lastword; 20575083Sru struct command *t; 206251512Semaste Char **v, *cp; 207251512Semaste#ifdef BSDSIGS 208251512Semaste sigmask_t omask; 2091638Srgrimes 210251512Semaste omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); 211251512Semaste#else 212251512Semaste (void) sighold(SIGINT); 213251512Semaste#endif 214144893Sharti 2151638Srgrimes USE(n); 21675284Sru 21775284Sru (void) time(&cur_time); 21899343Sru tp = sched_ptr; 21975284Sru 22075284Sru /* bugfix by: Justin Bur at Universite de Montreal */ 22175284Sru /* 22275284Sru * this test wouldn't be necessary if this routine were not called before 22375284Sru * each prompt (in sh.c). But it is, to catch missed alarms. Someone 22475284Sru * ought to fix it all up. -jbb 22575284Sru */ 22675284Sru if (!(tp && tp->t_when < cur_time)) { 22775284Sru#ifdef BSDSIGS 22875284Sru (void) sigsetmask(omask); 22975284Sru#else 23075284Sru (void) sigrelse(SIGINT); 23175284Sru#endif 23275284Sru return; 23375284Sru } 23475284Sru 23588055Sru if (GettingInput) 23688055Sru (void) Cookedmode(); 237100872Sru 23875284Sru while (tp && tp->t_when < cur_time) { 23994954Sru if (seterr) { 24075284Sru xfree((ptr_t) seterr); 24175284Sru seterr = NULL; 24275284Sru } 24375284Sru cmd.word = STRNULL; 24499257Sru lastword = &cmd; 24599257Sru v = tp->t_lex; 24699257Sru for (cp = *v; cp; cp = *++v) { 24797769Sru nextword = (struct wordent *) xcalloc(1, sizeof cmd); 24896668Sru nextword->word = Strsave(cp); 24999256Sru lastword->next = nextword; 25096462Sru nextword->prev = lastword; 251156813Sru lastword = nextword; 25296164Sru } 25399343Sru lastword->next = &cmd; 25496163Sru cmd.prev = lastword; 25596163Sru tp1 = tp; 256289051Sbdrewery sched_ptr = tp = tp1->t_next; /* looping termination cond: */ 2571638Srgrimes blkfree(tp1->t_lex); /* straighten out in case of */ 2581638Srgrimes xfree((ptr_t) tp1); /* command blow-up. */ 259103713Smarkm 2601638Srgrimes /* expand aliases like process() does. */ 261103713Smarkm alias(&cmd); 2621638Srgrimes /* build a syntax tree for the command. */ 2631638Srgrimes t = syntax(cmd.next, &cmd, 0); 2641638Srgrimes if (seterr) 265156813Sru stderror(ERR_OLD); 2661638Srgrimes /* execute the parse tree. */ 26774842Sru execute(t, -1, NULL, NULL, TRUE); 2681844Swollman /* done. free the lex list and parse tree. */ 2691844Swollman freelex(&cmd), freesyn(t); 27034081Sbde } 27194113Sru if (GettingInput && !just_signaled) { /* PWP */ 27234087Sbde (void) Rawmode(); 27334081Sbde ClearLines(); /* do a real refresh since something may */ 27434081Sbde ClearDisp(); /* have printed to the screen */ 27516663Sjkh Refresh(); 27676861Skris } 27776861Skris just_signaled = 0; 278139068Spaul 279139068Spaul#ifdef BSDSIGS 280139068Spaul (void) sigsetmask(omask); 281139068Spaul#else 282 (void) sigrelse(SIGINT); 283#endif 284} 285