145e5710bSMark Peek /* $Header: /p/tcsh/cvsroot/tcsh/tc.sched.c,v 3.25 2006/03/02 18:46:45 christos Exp $ */ 2c80476e4SDavid E. O'Brien /* 3c80476e4SDavid E. O'Brien * tc.sched.c: Scheduled command execution 4c80476e4SDavid E. O'Brien * 5c80476e4SDavid E. O'Brien * Karl Kleinpaste: Computer Consoles Inc. 1984 6c80476e4SDavid E. O'Brien */ 7c80476e4SDavid E. O'Brien /*- 8c80476e4SDavid E. O'Brien * Copyright (c) 1980, 1991 The Regents of the University of California. 9c80476e4SDavid E. O'Brien * All rights reserved. 10c80476e4SDavid E. O'Brien * 11c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without 12c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions 13c80476e4SDavid E. O'Brien * are met: 14c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright 15c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer. 16c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright 17c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the 18c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution. 1929301572SMark Peek * 3. Neither the name of the University nor the names of its contributors 20c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software 21c80476e4SDavid E. O'Brien * without specific prior written permission. 22c80476e4SDavid E. O'Brien * 23c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33c80476e4SDavid E. O'Brien * SUCH DAMAGE. 34c80476e4SDavid E. O'Brien */ 35c80476e4SDavid E. O'Brien #include "sh.h" 36c80476e4SDavid E. O'Brien 3745e5710bSMark Peek RCSID("$tcsh: tc.sched.c,v 3.25 2006/03/02 18:46:45 christos Exp $") 38c80476e4SDavid E. O'Brien 39c80476e4SDavid E. O'Brien #include "ed.h" 4029301572SMark Peek #include "tw.h" 41c80476e4SDavid E. O'Brien #include "tc.h" 42c80476e4SDavid E. O'Brien 43c80476e4SDavid E. O'Brien extern int just_signaled; 44c80476e4SDavid E. O'Brien 45c80476e4SDavid E. O'Brien struct sched_event { 46c80476e4SDavid E. O'Brien struct sched_event *t_next; 47c80476e4SDavid E. O'Brien time_t t_when; 48c80476e4SDavid E. O'Brien Char **t_lex; 49c80476e4SDavid E. O'Brien }; 50c80476e4SDavid E. O'Brien static struct sched_event *sched_ptr = NULL; 51c80476e4SDavid E. O'Brien 52c80476e4SDavid E. O'Brien 53c80476e4SDavid E. O'Brien time_t 5445e5710bSMark Peek sched_next(void) 55c80476e4SDavid E. O'Brien { 56c80476e4SDavid E. O'Brien if (sched_ptr) 57c80476e4SDavid E. O'Brien return (sched_ptr->t_when); 58c80476e4SDavid E. O'Brien return ((time_t) - 1); 59c80476e4SDavid E. O'Brien } 60c80476e4SDavid E. O'Brien 61c80476e4SDavid E. O'Brien /*ARGSUSED*/ 62c80476e4SDavid E. O'Brien void 6345e5710bSMark Peek dosched(Char **v, struct command *c) 64c80476e4SDavid E. O'Brien { 6545e5710bSMark Peek struct sched_event *tp, **pp; 66c80476e4SDavid E. O'Brien time_t cur_time; 67c80476e4SDavid E. O'Brien int count, hours, minutes, dif_hour, dif_min; 68c80476e4SDavid E. O'Brien Char *cp; 6923338178SMark Peek int relative; /* time specified as +hh:mm */ 70c80476e4SDavid E. O'Brien struct tm *ltp; 71c80476e4SDavid E. O'Brien 72c80476e4SDavid E. O'Brien USE(c); 73c80476e4SDavid E. O'Brien /* This is a major kludge because of a gcc linker */ 74c80476e4SDavid E. O'Brien /* Problem. It may or may not be needed for you */ 753b6eaa7bSAndrey A. Chernov #if defined(_MINIX) && !defined(_MINIX_VMD) 76c80476e4SDavid E. O'Brien char kludge[10]; 77c80476e4SDavid E. O'Brien extern char *sprintf(); 78c80476e4SDavid E. O'Brien sprintf(kludge, CGETS(24, 1, "kludge")); 793b6eaa7bSAndrey A. Chernov #endif /* _MINIX && !_MINIX_VMD */ 80c80476e4SDavid E. O'Brien 81c80476e4SDavid E. O'Brien v++; 82c80476e4SDavid E. O'Brien cp = *v++; 83c80476e4SDavid E. O'Brien if (cp == NULL) { 8445e5710bSMark Peek const Char *fmt; 85c80476e4SDavid E. O'Brien if ((fmt = varval(STRsched)) == STRNULL) 86c80476e4SDavid E. O'Brien fmt = str2short("%h\t%T\t%R\n"); 87c80476e4SDavid E. O'Brien /* print list of scheduled events */ 88c80476e4SDavid E. O'Brien for (count = 1, tp = sched_ptr; tp; count++, tp = tp->t_next) { 8945e5710bSMark Peek Char *buf, *str; 9045e5710bSMark Peek 9145e5710bSMark Peek buf = blkexpand(tp->t_lex); 9245e5710bSMark Peek cleanup_push(buf, xfree); 9345e5710bSMark Peek str = tprintf(FMT_SCHED, fmt, short2str(buf), tp->t_when, &count); 9445e5710bSMark Peek cleanup_until(buf); 9545e5710bSMark Peek cleanup_push(str, xfree); 9645e5710bSMark Peek for (cp = str; *cp;) 9723338178SMark Peek xputwchar(*cp++); 9845e5710bSMark Peek cleanup_until(str); 99c80476e4SDavid E. O'Brien } 100c80476e4SDavid E. O'Brien return; 101c80476e4SDavid E. O'Brien } 102c80476e4SDavid E. O'Brien 103c80476e4SDavid E. O'Brien if (*cp == '-') { 104c80476e4SDavid E. O'Brien /* remove item from list */ 105c80476e4SDavid E. O'Brien if (!sched_ptr) 106c80476e4SDavid E. O'Brien stderror(ERR_NOSCHED); 107c80476e4SDavid E. O'Brien if (*v) 108c80476e4SDavid E. O'Brien stderror(ERR_SCHEDUSAGE); 109c80476e4SDavid E. O'Brien count = atoi(short2str(++cp)); 110c80476e4SDavid E. O'Brien if (count <= 0) 111c80476e4SDavid E. O'Brien stderror(ERR_SCHEDUSAGE); 11245e5710bSMark Peek pp = &sched_ptr; 113c80476e4SDavid E. O'Brien tp = sched_ptr; 114c80476e4SDavid E. O'Brien while (--count) { 115c80476e4SDavid E. O'Brien if (tp->t_next == 0) 116c80476e4SDavid E. O'Brien break; 117c80476e4SDavid E. O'Brien else { 11845e5710bSMark Peek pp = &tp->t_next; 119c80476e4SDavid E. O'Brien tp = tp->t_next; 120c80476e4SDavid E. O'Brien } 121c80476e4SDavid E. O'Brien } 122c80476e4SDavid E. O'Brien if (count) 123c80476e4SDavid E. O'Brien stderror(ERR_SCHEDEV); 12445e5710bSMark Peek *pp = tp->t_next; 125c80476e4SDavid E. O'Brien blkfree(tp->t_lex); 12645e5710bSMark Peek xfree(tp); 127c80476e4SDavid E. O'Brien return; 128c80476e4SDavid E. O'Brien } 129c80476e4SDavid E. O'Brien 130c80476e4SDavid E. O'Brien /* else, add an item to the list */ 131c80476e4SDavid E. O'Brien if (!*v) 132c80476e4SDavid E. O'Brien stderror(ERR_SCHEDCOM); 133c80476e4SDavid E. O'Brien relative = 0; 134c80476e4SDavid E. O'Brien if (!Isdigit(*cp)) { /* not abs. time */ 135c80476e4SDavid E. O'Brien if (*cp != '+') 136c80476e4SDavid E. O'Brien stderror(ERR_SCHEDUSAGE); 137c80476e4SDavid E. O'Brien cp++, relative++; 138c80476e4SDavid E. O'Brien } 139c80476e4SDavid E. O'Brien minutes = 0; 140c80476e4SDavid E. O'Brien hours = atoi(short2str(cp)); 141c80476e4SDavid E. O'Brien while (*cp && *cp != ':' && *cp != 'a' && *cp != 'p') 142c80476e4SDavid E. O'Brien cp++; 143c80476e4SDavid E. O'Brien if (*cp && *cp == ':') 144c80476e4SDavid E. O'Brien minutes = atoi(short2str(++cp)); 145c80476e4SDavid E. O'Brien if ((hours < 0) || (minutes < 0) || 146c80476e4SDavid E. O'Brien (hours > 23) || (minutes > 59)) 147c80476e4SDavid E. O'Brien stderror(ERR_SCHEDTIME); 148c80476e4SDavid E. O'Brien while (*cp && *cp != 'p' && *cp != 'a') 149c80476e4SDavid E. O'Brien cp++; 150c80476e4SDavid E. O'Brien if (*cp && relative) 151c80476e4SDavid E. O'Brien stderror(ERR_SCHEDREL); 152c80476e4SDavid E. O'Brien if (*cp == 'p') 153c80476e4SDavid E. O'Brien hours += 12; 154c80476e4SDavid E. O'Brien (void) time(&cur_time); 155c80476e4SDavid E. O'Brien ltp = localtime(&cur_time); 156c80476e4SDavid E. O'Brien if (relative) { 157c80476e4SDavid E. O'Brien dif_hour = hours; 158c80476e4SDavid E. O'Brien dif_min = minutes; 159c80476e4SDavid E. O'Brien } 160c80476e4SDavid E. O'Brien else { 161c80476e4SDavid E. O'Brien if ((dif_hour = hours - ltp->tm_hour) < 0) 162c80476e4SDavid E. O'Brien dif_hour += 24; 163c80476e4SDavid E. O'Brien if ((dif_min = minutes - ltp->tm_min) < 0) { 164c80476e4SDavid E. O'Brien dif_min += 60; 165c80476e4SDavid E. O'Brien if ((--dif_hour) < 0) 166c80476e4SDavid E. O'Brien dif_hour = 23; 167c80476e4SDavid E. O'Brien } 168c80476e4SDavid E. O'Brien } 16945e5710bSMark Peek tp = xcalloc(1, sizeof *tp); 170c80476e4SDavid E. O'Brien #ifdef _SX 171c80476e4SDavid E. O'Brien tp->t_when = cur_time - ltp->tm_sec + dif_hour * 3600 + dif_min * 60; 172c80476e4SDavid E. O'Brien #else /* _SX */ 173c80476e4SDavid E. O'Brien tp->t_when = cur_time - ltp->tm_sec + dif_hour * 3600L + dif_min * 60L; 174c80476e4SDavid E. O'Brien #endif /* _SX */ 175c80476e4SDavid E. O'Brien /* use of tm_sec: get to beginning of minute. */ 17645e5710bSMark Peek for (pp = &sched_ptr; *pp != NULL && tp->t_when >= (*pp)->t_when; 17745e5710bSMark Peek pp = &(*pp)->t_next) 17845e5710bSMark Peek ; 17945e5710bSMark Peek tp->t_next = *pp; 18045e5710bSMark Peek *pp = tp; 181c80476e4SDavid E. O'Brien tp->t_lex = saveblk(v); 182c80476e4SDavid E. O'Brien } 183c80476e4SDavid E. O'Brien 184c80476e4SDavid E. O'Brien /* 185c80476e4SDavid E. O'Brien * Execute scheduled events 186c80476e4SDavid E. O'Brien */ 187c80476e4SDavid E. O'Brien void 18845e5710bSMark Peek sched_run(void) 189c80476e4SDavid E. O'Brien { 190c80476e4SDavid E. O'Brien time_t cur_time; 19145e5710bSMark Peek struct sched_event *tp; 192c80476e4SDavid E. O'Brien struct wordent cmd, *nextword, *lastword; 193c80476e4SDavid E. O'Brien struct command *t; 194c80476e4SDavid E. O'Brien Char **v, *cp; 195c80476e4SDavid E. O'Brien 19645e5710bSMark Peek pintr_disabled++; 19745e5710bSMark Peek cleanup_push(&pintr_disabled, disabled_cleanup); 198c80476e4SDavid E. O'Brien 199c80476e4SDavid E. O'Brien (void) time(&cur_time); 200c80476e4SDavid E. O'Brien 201c80476e4SDavid E. O'Brien /* bugfix by: Justin Bur at Universite de Montreal */ 202c80476e4SDavid E. O'Brien /* 203c80476e4SDavid E. O'Brien * this test wouldn't be necessary if this routine were not called before 204c80476e4SDavid E. O'Brien * each prompt (in sh.c). But it is, to catch missed alarms. Someone 205c80476e4SDavid E. O'Brien * ought to fix it all up. -jbb 206c80476e4SDavid E. O'Brien */ 20745e5710bSMark Peek if (!(sched_ptr && sched_ptr->t_when < cur_time)) { 20845e5710bSMark Peek cleanup_until(&pintr_disabled); 209c80476e4SDavid E. O'Brien return; 210c80476e4SDavid E. O'Brien } 211c80476e4SDavid E. O'Brien 212c80476e4SDavid E. O'Brien if (GettingInput) 213c80476e4SDavid E. O'Brien (void) Cookedmode(); 214c80476e4SDavid E. O'Brien 21545e5710bSMark Peek while ((tp = sched_ptr) != NULL && tp->t_when < cur_time) { 216c80476e4SDavid E. O'Brien if (seterr) { 21745e5710bSMark Peek xfree(seterr); 218c80476e4SDavid E. O'Brien seterr = NULL; 219c80476e4SDavid E. O'Brien } 220c80476e4SDavid E. O'Brien cmd.word = STRNULL; 221c80476e4SDavid E. O'Brien lastword = &cmd; 222c80476e4SDavid E. O'Brien v = tp->t_lex; 223c80476e4SDavid E. O'Brien for (cp = *v; cp; cp = *++v) { 22445e5710bSMark Peek nextword = xcalloc(1, sizeof cmd); 225c80476e4SDavid E. O'Brien nextword->word = Strsave(cp); 226c80476e4SDavid E. O'Brien lastword->next = nextword; 227c80476e4SDavid E. O'Brien nextword->prev = lastword; 228c80476e4SDavid E. O'Brien lastword = nextword; 229c80476e4SDavid E. O'Brien } 230c80476e4SDavid E. O'Brien lastword->next = &cmd; 231c80476e4SDavid E. O'Brien cmd.prev = lastword; 23245e5710bSMark Peek sched_ptr = tp->t_next; /* looping termination cond: */ 23345e5710bSMark Peek blkfree(tp->t_lex); /* straighten out in case of */ 23445e5710bSMark Peek xfree(tp); /* command blow-up. */ 235c80476e4SDavid E. O'Brien 23645e5710bSMark Peek cleanup_push(&cmd, lex_cleanup); 237c80476e4SDavid E. O'Brien /* expand aliases like process() does. */ 238c80476e4SDavid E. O'Brien alias(&cmd); 239c80476e4SDavid E. O'Brien /* build a syntax tree for the command. */ 240c80476e4SDavid E. O'Brien t = syntax(cmd.next, &cmd, 0); 24145e5710bSMark Peek cleanup_push(t, syntax_cleanup); 242c80476e4SDavid E. O'Brien if (seterr) 243c80476e4SDavid E. O'Brien stderror(ERR_OLD); 244c80476e4SDavid E. O'Brien /* execute the parse tree. */ 24529301572SMark Peek execute(t, -1, NULL, NULL, TRUE); 246c80476e4SDavid E. O'Brien /* done. free the lex list and parse tree. */ 24745e5710bSMark Peek cleanup_until(&cmd); 248c80476e4SDavid E. O'Brien } 249c80476e4SDavid E. O'Brien if (GettingInput && !just_signaled) { /* PWP */ 250c80476e4SDavid E. O'Brien (void) Rawmode(); 251c80476e4SDavid E. O'Brien ClearLines(); /* do a real refresh since something may */ 252c80476e4SDavid E. O'Brien ClearDisp(); /* have printed to the screen */ 253c80476e4SDavid E. O'Brien Refresh(); 254c80476e4SDavid E. O'Brien } 255c80476e4SDavid E. O'Brien just_signaled = 0; 256c80476e4SDavid E. O'Brien 25745e5710bSMark Peek cleanup_until(&pintr_disabled); 258c80476e4SDavid E. O'Brien } 259