Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/ksh93/bltins/alarm.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1982-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* David Korn <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* alarm [-r] [varname [+]when]
23
*
24
* David Korn
25
* AT&T Labs
26
*
27
*/
28
29
#include "defs.h"
30
#include <error.h>
31
#include <stak.h>
32
#include "builtins.h"
33
#include "FEATURE/time"
34
35
#define R_FLAG 1
36
#define L_FLAG 2
37
38
struct tevent
39
{
40
Namfun_t fun;
41
Namval_t *node;
42
Namval_t *action;
43
struct tevent *next;
44
long milli;
45
int flags;
46
void *timeout;
47
Shell_t *sh;
48
};
49
50
static const char ALARM[] = "alarm";
51
52
static void trap_timeout(void*);
53
54
/*
55
* insert timeout item on current given list in sorted order
56
*/
57
static void *time_add(struct tevent *item, void *list)
58
{
59
register struct tevent *tp = (struct tevent*)list;
60
if(!tp || item->milli < tp->milli)
61
{
62
item->next = tp;
63
list = (void*)item;
64
}
65
else
66
{
67
while(tp->next && item->milli > tp->next->milli)
68
tp = tp->next;
69
item->next = tp->next;
70
tp->next = item;
71
}
72
tp = item;
73
tp->timeout = (void*)sh_timeradd(tp->milli,tp->flags&R_FLAG,trap_timeout,(void*)tp);
74
return(list);
75
}
76
77
/*
78
* delete timeout item from current given list, delete timer
79
*/
80
static void *time_delete(register struct tevent *item, void *list)
81
{
82
register struct tevent *tp = (struct tevent*)list;
83
if(item==tp)
84
list = (void*)tp->next;
85
else
86
{
87
while(tp && tp->next != item)
88
tp = tp->next;
89
if(tp)
90
tp->next = item->next;
91
}
92
if(item->timeout)
93
timerdel((void*)item->timeout);
94
return(list);
95
}
96
97
static void print_alarms(void *list)
98
{
99
register struct tevent *tp = (struct tevent*)list;
100
while(tp)
101
{
102
if(tp->timeout)
103
{
104
register char *name = nv_name(tp->node);
105
if(tp->flags&R_FLAG)
106
{
107
double d = tp->milli;
108
sfprintf(sfstdout,e_alrm1,name,d/1000.);
109
}
110
else
111
sfprintf(sfstdout,e_alrm2,name,nv_getnum(tp->node));
112
}
113
tp = tp->next;
114
}
115
}
116
117
static void trap_timeout(void* handle)
118
{
119
register struct tevent *tp = (struct tevent*)handle;
120
tp->sh->trapnote |= SH_SIGALRM;
121
if(!(tp->flags&R_FLAG))
122
tp->timeout = 0;
123
tp->flags |= L_FLAG;
124
tp->sh->sigflag[SIGALRM] |= SH_SIGALRM;
125
if(sh_isstate(SH_TTYWAIT))
126
sh_timetraps(tp->sh);
127
}
128
129
void sh_timetraps(Shell_t *shp)
130
{
131
register struct tevent *tp, *tpnext;
132
register struct tevent *tptop;
133
while(1)
134
{
135
shp->sigflag[SIGALRM] &= ~SH_SIGALRM;
136
tptop= (struct tevent*)shp->st.timetrap;
137
for(tp=tptop;tp;tp=tpnext)
138
{
139
tpnext = tp->next;
140
if(tp->flags&L_FLAG)
141
{
142
tp->flags &= ~L_FLAG;
143
if(tp->action)
144
sh_fun(tp->action,tp->node,(char**)0);
145
tp->flags &= ~L_FLAG;
146
if(!tp->flags)
147
{
148
nv_unset(tp->node);
149
nv_close(tp->node);
150
}
151
}
152
}
153
if(!(shp->sigflag[SIGALRM]&SH_SIGALRM))
154
break;
155
}
156
}
157
158
159
/*
160
* This trap function catches "alarm" actions only
161
*/
162
static char *setdisc(Namval_t *np, const char *event, Namval_t* action, Namfun_t
163
*fp)
164
{
165
register struct tevent *tp = (struct tevent*)fp;
166
if(!event)
167
return(action?"":(char*)ALARM);
168
if(strcmp(event,ALARM)!=0)
169
{
170
/* try the next level */
171
return(nv_setdisc(np, event, action, fp));
172
}
173
if(action==np)
174
action = tp->action;
175
else
176
tp->action = action;
177
return(action?(char*)action:"");
178
}
179
180
/*
181
* catch assignments and set alarm traps
182
*/
183
static void putval(Namval_t* np, const char* val, int flag, Namfun_t* fp)
184
{
185
register struct tevent *tp = (struct tevent*)fp;
186
register double d;
187
Shell_t *shp = tp->sh;
188
if(val)
189
{
190
double now;
191
#ifdef timeofday
192
struct timeval tmp;
193
timeofday(&tmp);
194
now = tmp.tv_sec + 1.e-6*tmp.tv_usec;
195
#else
196
now = (double)time(NIL(time_t*));
197
#endif /* timeofday */
198
nv_putv(np,val,flag,fp);
199
d = nv_getnum(np);
200
if(*val=='+')
201
{
202
double x = d + now;
203
nv_putv(np,(char*)&x,NV_INTEGER|NV_DOUBLE,fp);
204
}
205
else
206
d -= now;
207
tp->milli = 1000*(d+.0005);
208
if(tp->timeout)
209
shp->st.timetrap = time_delete(tp,shp->st.timetrap);
210
if(tp->milli > 0)
211
shp->st.timetrap = time_add(tp,shp->st.timetrap);
212
}
213
else
214
{
215
tp = (struct tevent*)nv_stack(np, (Namfun_t*)0);
216
shp->st.timetrap = time_delete(tp,shp->st.timetrap);
217
if(tp->action)
218
nv_close(tp->action);
219
nv_unset(np);
220
free((void*)fp);
221
}
222
}
223
224
static const Namdisc_t alarmdisc =
225
{
226
sizeof(struct tevent),
227
putval,
228
0,
229
0,
230
setdisc,
231
};
232
233
int b_alarm(int argc,char *argv[],Shbltin_t *context)
234
{
235
register int n,rflag=0;
236
register Namval_t *np;
237
register struct tevent *tp;
238
register Shell_t *shp = context->shp;
239
while (n = optget(argv, sh_optalarm)) switch (n)
240
{
241
case 'r':
242
rflag = R_FLAG;
243
break;
244
case ':':
245
errormsg(SH_DICT,2, "%s", opt_info.arg);
246
break;
247
case '?':
248
errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
249
break;
250
}
251
argc -= opt_info.index;
252
argv += opt_info.index;
253
if(error_info.errors)
254
errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
255
if(argc==0)
256
{
257
print_alarms(shp->st.timetrap);
258
return(0);
259
}
260
if(argc!=2)
261
errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
262
np = nv_open(argv[0],shp->var_tree,NV_NOARRAY|NV_VARNAME|NV_NOASSIGN);
263
if(!nv_isnull(np))
264
nv_unset(np);
265
nv_setattr(np, NV_DOUBLE);
266
if(!(tp = newof(NIL(struct tevent*),struct tevent,1,0)))
267
errormsg(SH_DICT,ERROR_exit(1),e_nospace);
268
tp->fun.disc = &alarmdisc;
269
tp->flags = rflag;
270
tp->node = np;
271
tp->sh = shp;
272
nv_stack(np,(Namfun_t*)tp);
273
nv_putval(np, argv[1], 0);
274
return(0);
275
}
276
277
278