1c80476e4SDavid E. O'Brien /*
2c80476e4SDavid E. O'Brien * tc.sched.c: Scheduled command execution
3c80476e4SDavid E. O'Brien *
4c80476e4SDavid E. O'Brien * Karl Kleinpaste: Computer Consoles Inc. 1984
5c80476e4SDavid E. O'Brien */
6c80476e4SDavid E. O'Brien /*-
7c80476e4SDavid E. O'Brien * Copyright (c) 1980, 1991 The Regents of the University of California.
8c80476e4SDavid E. O'Brien * All rights reserved.
9c80476e4SDavid E. O'Brien *
10c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without
11c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions
12c80476e4SDavid E. O'Brien * are met:
13c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright
14c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer.
15c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright
16c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the
17c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution.
1829301572SMark Peek * 3. Neither the name of the University nor the names of its contributors
19c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software
20c80476e4SDavid E. O'Brien * without specific prior written permission.
21c80476e4SDavid E. O'Brien *
22c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32c80476e4SDavid E. O'Brien * SUCH DAMAGE.
33c80476e4SDavid E. O'Brien */
34c80476e4SDavid E. O'Brien #include "sh.h"
35c80476e4SDavid E. O'Brien #include "ed.h"
3629301572SMark Peek #include "tw.h"
37c80476e4SDavid E. O'Brien #include "tc.h"
38c80476e4SDavid E. O'Brien
39c80476e4SDavid E. O'Brien extern int just_signaled;
40c80476e4SDavid E. O'Brien
41c80476e4SDavid E. O'Brien struct sched_event {
42c80476e4SDavid E. O'Brien struct sched_event *t_next;
43c80476e4SDavid E. O'Brien time_t t_when;
44c80476e4SDavid E. O'Brien Char **t_lex;
45c80476e4SDavid E. O'Brien };
46c80476e4SDavid E. O'Brien static struct sched_event *sched_ptr = NULL;
47c80476e4SDavid E. O'Brien
48c80476e4SDavid E. O'Brien
49c80476e4SDavid E. O'Brien time_t
sched_next(void)5045e5710bSMark Peek sched_next(void)
51c80476e4SDavid E. O'Brien {
52c80476e4SDavid E. O'Brien if (sched_ptr)
53c80476e4SDavid E. O'Brien return (sched_ptr->t_when);
54c80476e4SDavid E. O'Brien return ((time_t) - 1);
55c80476e4SDavid E. O'Brien }
56c80476e4SDavid E. O'Brien
57c80476e4SDavid E. O'Brien /*ARGSUSED*/
58c80476e4SDavid E. O'Brien void
dosched(Char ** v,struct command * c)5945e5710bSMark Peek dosched(Char **v, struct command *c)
60c80476e4SDavid E. O'Brien {
6145e5710bSMark Peek struct sched_event *tp, **pp;
62c80476e4SDavid E. O'Brien time_t cur_time;
63c80476e4SDavid E. O'Brien int count, hours, minutes, dif_hour, dif_min;
64c80476e4SDavid E. O'Brien Char *cp;
6523338178SMark Peek int relative; /* time specified as +hh:mm */
66c80476e4SDavid E. O'Brien struct tm *ltp;
67c80476e4SDavid E. O'Brien
68c80476e4SDavid E. O'Brien USE(c);
69c80476e4SDavid E. O'Brien /* This is a major kludge because of a gcc linker */
70c80476e4SDavid E. O'Brien /* Problem. It may or may not be needed for you */
713b6eaa7bSAndrey A. Chernov #if defined(_MINIX) && !defined(_MINIX_VMD)
72c80476e4SDavid E. O'Brien char kludge[10];
73c80476e4SDavid E. O'Brien extern char *sprintf();
74c80476e4SDavid E. O'Brien sprintf(kludge, CGETS(24, 1, "kludge"));
753b6eaa7bSAndrey A. Chernov #endif /* _MINIX && !_MINIX_VMD */
76c80476e4SDavid E. O'Brien
77c80476e4SDavid E. O'Brien v++;
78c80476e4SDavid E. O'Brien cp = *v++;
79c80476e4SDavid E. O'Brien if (cp == NULL) {
8045e5710bSMark Peek const Char *fmt;
81c80476e4SDavid E. O'Brien if ((fmt = varval(STRsched)) == STRNULL)
82c80476e4SDavid E. O'Brien fmt = str2short("%h\t%T\t%R\n");
83c80476e4SDavid E. O'Brien /* print list of scheduled events */
84c80476e4SDavid E. O'Brien for (count = 1, tp = sched_ptr; tp; count++, tp = tp->t_next) {
8545e5710bSMark Peek Char *buf, *str;
8645e5710bSMark Peek
8745e5710bSMark Peek buf = blkexpand(tp->t_lex);
8845e5710bSMark Peek cleanup_push(buf, xfree);
8945e5710bSMark Peek str = tprintf(FMT_SCHED, fmt, short2str(buf), tp->t_when, &count);
9045e5710bSMark Peek cleanup_until(buf);
9145e5710bSMark Peek cleanup_push(str, xfree);
9245e5710bSMark Peek for (cp = str; *cp;)
9323338178SMark Peek xputwchar(*cp++);
9445e5710bSMark Peek cleanup_until(str);
95c80476e4SDavid E. O'Brien }
96c80476e4SDavid E. O'Brien return;
97c80476e4SDavid E. O'Brien }
98c80476e4SDavid E. O'Brien
99c80476e4SDavid E. O'Brien if (*cp == '-') {
100c80476e4SDavid E. O'Brien /* remove item from list */
101c80476e4SDavid E. O'Brien if (!sched_ptr)
102c80476e4SDavid E. O'Brien stderror(ERR_NOSCHED);
103c80476e4SDavid E. O'Brien if (*v)
104c80476e4SDavid E. O'Brien stderror(ERR_SCHEDUSAGE);
105c80476e4SDavid E. O'Brien count = atoi(short2str(++cp));
106c80476e4SDavid E. O'Brien if (count <= 0)
107c80476e4SDavid E. O'Brien stderror(ERR_SCHEDUSAGE);
10845e5710bSMark Peek pp = &sched_ptr;
109c80476e4SDavid E. O'Brien tp = sched_ptr;
110c80476e4SDavid E. O'Brien while (--count) {
111c80476e4SDavid E. O'Brien if (tp->t_next == 0)
112c80476e4SDavid E. O'Brien break;
113c80476e4SDavid E. O'Brien else {
11445e5710bSMark Peek pp = &tp->t_next;
115c80476e4SDavid E. O'Brien tp = tp->t_next;
116c80476e4SDavid E. O'Brien }
117c80476e4SDavid E. O'Brien }
118c80476e4SDavid E. O'Brien if (count)
119c80476e4SDavid E. O'Brien stderror(ERR_SCHEDEV);
12045e5710bSMark Peek *pp = tp->t_next;
121c80476e4SDavid E. O'Brien blkfree(tp->t_lex);
12245e5710bSMark Peek xfree(tp);
123c80476e4SDavid E. O'Brien return;
124c80476e4SDavid E. O'Brien }
125c80476e4SDavid E. O'Brien
126c80476e4SDavid E. O'Brien /* else, add an item to the list */
127c80476e4SDavid E. O'Brien if (!*v)
128c80476e4SDavid E. O'Brien stderror(ERR_SCHEDCOM);
129c80476e4SDavid E. O'Brien relative = 0;
130c80476e4SDavid E. O'Brien if (!Isdigit(*cp)) { /* not abs. time */
131c80476e4SDavid E. O'Brien if (*cp != '+')
132c80476e4SDavid E. O'Brien stderror(ERR_SCHEDUSAGE);
133c80476e4SDavid E. O'Brien cp++, relative++;
134c80476e4SDavid E. O'Brien }
135c80476e4SDavid E. O'Brien minutes = 0;
136c80476e4SDavid E. O'Brien hours = atoi(short2str(cp));
137c80476e4SDavid E. O'Brien while (*cp && *cp != ':' && *cp != 'a' && *cp != 'p')
138c80476e4SDavid E. O'Brien cp++;
139c80476e4SDavid E. O'Brien if (*cp && *cp == ':')
140c80476e4SDavid E. O'Brien minutes = atoi(short2str(++cp));
141c80476e4SDavid E. O'Brien if ((hours < 0) || (minutes < 0) ||
142c80476e4SDavid E. O'Brien (hours > 23) || (minutes > 59))
143c80476e4SDavid E. O'Brien stderror(ERR_SCHEDTIME);
144c80476e4SDavid E. O'Brien while (*cp && *cp != 'p' && *cp != 'a')
145c80476e4SDavid E. O'Brien cp++;
146c80476e4SDavid E. O'Brien if (*cp && relative)
147c80476e4SDavid E. O'Brien stderror(ERR_SCHEDREL);
148c80476e4SDavid E. O'Brien if (*cp == 'p')
149c80476e4SDavid E. O'Brien hours += 12;
150c80476e4SDavid E. O'Brien (void) time(&cur_time);
151c80476e4SDavid E. O'Brien ltp = localtime(&cur_time);
152c80476e4SDavid E. O'Brien if (relative) {
153c80476e4SDavid E. O'Brien dif_hour = hours;
154c80476e4SDavid E. O'Brien dif_min = minutes;
155c80476e4SDavid E. O'Brien }
156c80476e4SDavid E. O'Brien else {
157c80476e4SDavid E. O'Brien if ((dif_hour = hours - ltp->tm_hour) < 0)
158c80476e4SDavid E. O'Brien dif_hour += 24;
159c80476e4SDavid E. O'Brien if ((dif_min = minutes - ltp->tm_min) < 0) {
160c80476e4SDavid E. O'Brien dif_min += 60;
161c80476e4SDavid E. O'Brien if ((--dif_hour) < 0)
162c80476e4SDavid E. O'Brien dif_hour = 23;
163c80476e4SDavid E. O'Brien }
164c80476e4SDavid E. O'Brien }
16545e5710bSMark Peek tp = xcalloc(1, sizeof *tp);
166c80476e4SDavid E. O'Brien #ifdef _SX
167c80476e4SDavid E. O'Brien tp->t_when = cur_time - ltp->tm_sec + dif_hour * 3600 + dif_min * 60;
168c80476e4SDavid E. O'Brien #else /* _SX */
169c80476e4SDavid E. O'Brien tp->t_when = cur_time - ltp->tm_sec + dif_hour * 3600L + dif_min * 60L;
170c80476e4SDavid E. O'Brien #endif /* _SX */
171c80476e4SDavid E. O'Brien /* use of tm_sec: get to beginning of minute. */
17245e5710bSMark Peek for (pp = &sched_ptr; *pp != NULL && tp->t_when >= (*pp)->t_when;
17345e5710bSMark Peek pp = &(*pp)->t_next)
17445e5710bSMark Peek ;
17545e5710bSMark Peek tp->t_next = *pp;
17645e5710bSMark Peek *pp = tp;
177c80476e4SDavid E. O'Brien tp->t_lex = saveblk(v);
178c80476e4SDavid E. O'Brien }
179c80476e4SDavid E. O'Brien
180c80476e4SDavid E. O'Brien /*
181c80476e4SDavid E. O'Brien * Execute scheduled events
182c80476e4SDavid E. O'Brien */
183c80476e4SDavid E. O'Brien void
sched_run(void)18445e5710bSMark Peek sched_run(void)
185c80476e4SDavid E. O'Brien {
186c80476e4SDavid E. O'Brien time_t cur_time;
18745e5710bSMark Peek struct sched_event *tp;
188c80476e4SDavid E. O'Brien struct wordent cmd, *nextword, *lastword;
189c80476e4SDavid E. O'Brien struct command *t;
190c80476e4SDavid E. O'Brien Char **v, *cp;
191c80476e4SDavid E. O'Brien
19245e5710bSMark Peek pintr_disabled++;
19345e5710bSMark Peek cleanup_push(&pintr_disabled, disabled_cleanup);
194c80476e4SDavid E. O'Brien
195c80476e4SDavid E. O'Brien (void) time(&cur_time);
196c80476e4SDavid E. O'Brien
197c80476e4SDavid E. O'Brien /* bugfix by: Justin Bur at Universite de Montreal */
198c80476e4SDavid E. O'Brien /*
199c80476e4SDavid E. O'Brien * this test wouldn't be necessary if this routine were not called before
200c80476e4SDavid E. O'Brien * each prompt (in sh.c). But it is, to catch missed alarms. Someone
201c80476e4SDavid E. O'Brien * ought to fix it all up. -jbb
202c80476e4SDavid E. O'Brien */
20345e5710bSMark Peek if (!(sched_ptr && sched_ptr->t_when < cur_time)) {
20445e5710bSMark Peek cleanup_until(&pintr_disabled);
205c80476e4SDavid E. O'Brien return;
206c80476e4SDavid E. O'Brien }
207c80476e4SDavid E. O'Brien
208c80476e4SDavid E. O'Brien if (GettingInput)
209c80476e4SDavid E. O'Brien (void) Cookedmode();
210c80476e4SDavid E. O'Brien
21145e5710bSMark Peek while ((tp = sched_ptr) != NULL && tp->t_when < cur_time) {
212c80476e4SDavid E. O'Brien if (seterr) {
21345e5710bSMark Peek xfree(seterr);
214c80476e4SDavid E. O'Brien seterr = NULL;
215c80476e4SDavid E. O'Brien }
216c80476e4SDavid E. O'Brien cmd.word = STRNULL;
217c80476e4SDavid E. O'Brien lastword = &cmd;
218c80476e4SDavid E. O'Brien v = tp->t_lex;
219c80476e4SDavid E. O'Brien for (cp = *v; cp; cp = *++v) {
22045e5710bSMark Peek nextword = xcalloc(1, sizeof cmd);
221c80476e4SDavid E. O'Brien nextword->word = Strsave(cp);
222c80476e4SDavid E. O'Brien lastword->next = nextword;
223c80476e4SDavid E. O'Brien nextword->prev = lastword;
224c80476e4SDavid E. O'Brien lastword = nextword;
225c80476e4SDavid E. O'Brien }
226c80476e4SDavid E. O'Brien lastword->next = &cmd;
227c80476e4SDavid E. O'Brien cmd.prev = lastword;
22845e5710bSMark Peek sched_ptr = tp->t_next; /* looping termination cond: */
22945e5710bSMark Peek blkfree(tp->t_lex); /* straighten out in case of */
23045e5710bSMark Peek xfree(tp); /* command blow-up. */
231c80476e4SDavid E. O'Brien
23245e5710bSMark Peek cleanup_push(&cmd, lex_cleanup);
233c80476e4SDavid E. O'Brien /* expand aliases like process() does. */
234c80476e4SDavid E. O'Brien alias(&cmd);
235c80476e4SDavid E. O'Brien /* build a syntax tree for the command. */
236c80476e4SDavid E. O'Brien t = syntax(cmd.next, &cmd, 0);
23745e5710bSMark Peek cleanup_push(t, syntax_cleanup);
238c80476e4SDavid E. O'Brien if (seterr)
239c80476e4SDavid E. O'Brien stderror(ERR_OLD);
240c80476e4SDavid E. O'Brien /* execute the parse tree. */
24129301572SMark Peek execute(t, -1, NULL, NULL, TRUE);
242c80476e4SDavid E. O'Brien /* done. free the lex list and parse tree. */
24345e5710bSMark Peek cleanup_until(&cmd);
244c80476e4SDavid E. O'Brien }
245c80476e4SDavid E. O'Brien if (GettingInput && !just_signaled) { /* PWP */
246c80476e4SDavid E. O'Brien (void) Rawmode();
247c80476e4SDavid E. O'Brien ClearLines(); /* do a real refresh since something may */
248c80476e4SDavid E. O'Brien ClearDisp(); /* have printed to the screen */
249c80476e4SDavid E. O'Brien Refresh();
250c80476e4SDavid E. O'Brien }
251c80476e4SDavid E. O'Brien just_signaled = 0;
252c80476e4SDavid E. O'Brien
25345e5710bSMark Peek cleanup_until(&pintr_disabled);
254c80476e4SDavid E. O'Brien }
255