source: trunk/third/tcsh/tc.sched.c @ 12039

Revision 12039, 7.4 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12038, which included commits to RCS files with non-trunk default branches.
Line 
1/* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/tc.sched.c,v 1.1.1.2 1998-10-03 21:10:15 danw 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 "sh.h"
40
41RCSID("$Id: tc.sched.c,v 1.1.1.2 1998-10-03 21:10:15 danw Exp $")
42
43#include "ed.h"
44#include "tc.h"
45
46extern int just_signaled;
47
48struct sched_event {
49    struct sched_event *t_next;
50    time_t t_when;
51    Char  **t_lex;
52};
53static struct sched_event *sched_ptr = NULL;
54
55
56time_t
57sched_next()
58{
59    if (sched_ptr)
60        return (sched_ptr->t_when);
61    return ((time_t) - 1);
62}
63
64/*ARGSUSED*/
65void
66dosched(v, c)
67    register Char **v;
68    struct command *c;
69{
70    register struct sched_event *tp, *tp1, *tp2;
71    time_t  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
77    USE(c);
78/* This is a major kludge because of a gcc linker  */
79/* Problem.  It may or may not be needed for you   */
80#ifdef _MINIX
81    char kludge[10];
82    extern char *sprintf();
83    sprintf(kludge, CGETS(24, 1, "kludge"));
84#endif /* _MINIX */
85
86    v++;
87    cp = *v++;
88    if (cp == NULL) {
89        Char   *fmt;
90        if ((fmt = varval(STRsched)) == STRNULL)
91            fmt = str2short("%h\t%T\t%R\n");
92        /* print list of scheduled events */
93        for (count = 1, tp = sched_ptr; tp; count++, tp = tp->t_next) {
94            Char buf[BUFSIZE], sbuf[BUFSIZE];
95            blkexpand(tp->t_lex, buf);
96            tprintf(FMT_SCHED, sbuf, fmt, sizeof(sbuf),
97                    short2str(buf), tp->t_when, (ptr_t) &count);
98            for (cp = sbuf; *cp;)
99                xputchar(*cp++);
100        }
101        return;
102    }
103
104    if (*cp == '-') {
105        /* remove item from list */
106        if (!sched_ptr)
107            stderror(ERR_NOSCHED);
108        if (*v)
109            stderror(ERR_SCHEDUSAGE);
110        count = atoi(short2str(++cp));
111        if (count <= 0)
112            stderror(ERR_SCHEDUSAGE);
113        tp = sched_ptr;
114        tp1 = 0;
115        while (--count) {
116            if (tp->t_next == 0)
117                break;
118            else {
119                tp1 = tp;
120                tp = tp->t_next;
121            }
122        }
123        if (count)
124            stderror(ERR_SCHEDEV);
125        if (tp1 == 0)
126            sched_ptr = tp->t_next;
127        else
128            tp1->t_next = tp->t_next;
129        blkfree(tp->t_lex);
130        xfree((ptr_t) tp);
131        return;
132    }
133
134    /* else, add an item to the list */
135    if (!*v)
136        stderror(ERR_SCHEDCOM);
137    relative = 0;
138    if (!Isdigit(*cp)) {        /* not abs. time */
139        if (*cp != '+')
140            stderror(ERR_SCHEDUSAGE);
141        cp++, relative++;
142    }
143    minutes = 0;
144    hours = atoi(short2str(cp));
145    while (*cp && *cp != ':' && *cp != 'a' && *cp != 'p')
146        cp++;
147    if (*cp && *cp == ':')
148        minutes = atoi(short2str(++cp));
149    if ((hours < 0) || (minutes < 0) ||
150        (hours > 23) || (minutes > 59))
151        stderror(ERR_SCHEDTIME);
152    while (*cp && *cp != 'p' && *cp != 'a')
153        cp++;
154    if (*cp && relative)
155        stderror(ERR_SCHEDREL);
156    if (*cp == 'p')
157        hours += 12;
158    (void) time(&cur_time);
159    ltp = localtime(&cur_time);
160    if (relative) {
161        dif_hour = hours;
162        dif_min = minutes;
163    }
164    else {
165        if ((dif_hour = hours - ltp->tm_hour) < 0)
166            dif_hour += 24;
167        if ((dif_min = minutes - ltp->tm_min) < 0) {
168            dif_min += 60;
169            if ((--dif_hour) < 0)
170                dif_hour = 23;
171        }
172    }
173    tp = (struct sched_event *) xcalloc(1, sizeof *tp);
174    tp->t_when = cur_time - ltp->tm_sec + dif_hour * 3600L + dif_min * 60L;
175    /* use of tm_sec: get to beginning of minute. */
176    if (!sched_ptr || tp->t_when < sched_ptr->t_when) {
177        tp->t_next = sched_ptr;
178        sched_ptr = tp;
179    }
180    else {
181        tp1 = sched_ptr->t_next;
182        tp2 = sched_ptr;
183        while (tp1 && tp->t_when >= tp1->t_when) {
184            tp2 = tp1;
185            tp1 = tp1->t_next;
186        }
187        tp->t_next = tp1;
188        tp2->t_next = tp;
189    }
190    tp->t_lex = saveblk(v);
191}
192
193/*
194 * Execute scheduled events
195 */
196/*ARGSUSED*/
197void
198sched_run(n)
199    int n;
200{
201    time_t   cur_time;
202    register struct sched_event *tp, *tp1;
203    struct wordent cmd, *nextword, *lastword;
204    struct command *t;
205    Char  **v, *cp;
206    extern Char GettingInput;
207#ifdef BSDSIGS
208    sigmask_t omask;
209
210    omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
211#else
212    (void) sighold(SIGINT);
213#endif
214
215    USE(n);
216
217    (void) time(&cur_time);
218    tp = sched_ptr;
219
220    /* bugfix by: Justin Bur at Universite de Montreal */
221    /*
222     * this test wouldn't be necessary if this routine were not called before
223     * each prompt (in sh.c).  But it is, to catch missed alarms.  Someone
224     * ought to fix it all up.  -jbb
225     */
226    if (!(tp && tp->t_when < cur_time)) {
227#ifdef BSDSIGS
228        (void) sigsetmask(omask);
229#else
230        (void) sigrelse(SIGINT);
231#endif
232        return;
233    }
234
235    if (GettingInput)
236        (void) Cookedmode();
237
238    while (tp && tp->t_when < cur_time) {
239        if (seterr) {
240            xfree((ptr_t) seterr);
241            seterr = NULL;
242        }
243        cmd.word = STRNULL;
244        lastword = &cmd;
245        v = tp->t_lex;
246        for (cp = *v; cp; cp = *++v) {
247            nextword = (struct wordent *) xcalloc(1, sizeof cmd);
248            nextword->word = Strsave(cp);
249            lastword->next = nextword;
250            nextword->prev = lastword;
251            lastword = nextword;
252        }
253        lastword->next = &cmd;
254        cmd.prev = lastword;
255        tp1 = tp;
256        sched_ptr = tp = tp1->t_next;   /* looping termination cond: */
257        blkfree(tp1->t_lex);    /* straighten out in case of */
258        xfree((ptr_t) tp1);     /* command blow-up. */
259
260        /* expand aliases like process() does. */
261        alias(&cmd);
262        /* build a syntax tree for the command. */
263        t = syntax(cmd.next, &cmd, 0);
264        if (seterr)
265            stderror(ERR_OLD);
266        /* execute the parse tree. */
267        execute(t, -1, NULL, NULL);
268        /* done. free the lex list and parse tree. */
269        freelex(&cmd), freesyn(t);
270    }
271    if (GettingInput && !just_signaled) {       /* PWP */
272        (void) Rawmode();
273        ClearLines();           /* do a real refresh since something may */
274        ClearDisp();            /* have printed to the screen */
275        Refresh();
276    }
277    just_signaled = 0;
278
279#ifdef BSDSIGS
280    (void) sigsetmask(omask);
281#else
282    (void) sigrelse(SIGINT);
283#endif
284}
Note: See TracBrowser for help on using the repository browser.