~ubuntu-branches/ubuntu/utopic/9base/utopic

« back to all changes in this revision

Viewing changes to rc/exec.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-08-20 17:34:06 UTC
  • mfrom: (6.2.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090820173406-xpwqa9ruyevvc0ut
* Updating maintainer field.
* Updating vcs fields.
* Updating package to standards version 3.8.3.
* Updatin variables writing in rules to consistent style.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include <u.h>
2
 
#include <signal.h>
3
 
#if defined(PLAN9PORT) && defined(__sun__)
4
 
#       define BSD_COMP /* sigh.  for TIOCNOTTY */
5
 
#endif
6
 
#ifdef __sun__
7
 
#include <sys/termios.h>
8
 
#endif
9
 
#include <sys/ioctl.h>
10
1
#include "rc.h"
11
2
#include "getflags.h"
12
3
#include "exec.h"
16
7
 * Start executing the given code at the given pc with the given redirection
17
8
 */
18
9
char *argv0="rc";
19
 
void start(code *c, int pc, var *local)
 
10
 
 
11
void
 
12
start(code *c, int pc, var *local)
20
13
{
21
 
        struct thread *p=new(struct thread);
22
 
        p->code=codecopy(c);
23
 
        p->pc=pc;
24
 
        p->argv=0;
25
 
        p->redir=p->startredir=runq?runq->redir:0;
26
 
        p->local=local;
27
 
        p->cmdfile=0;
28
 
        p->cmdfd=0;
29
 
        p->eof=0;
30
 
        p->iflag=0;
31
 
        p->lineno=1;
32
 
        p->pid=-1;
33
 
        p->ret=runq;
34
 
        runq=p;
 
14
        struct thread *p = new(struct thread);
 
15
 
 
16
        p->code = codecopy(c);
 
17
        p->pc = pc;
 
18
        p->argv = 0;
 
19
        p->redir = p->startredir = runq?runq->redir:0;
 
20
        p->local = local;
 
21
        p->cmdfile = 0;
 
22
        p->cmdfd = 0;
 
23
        p->eof = 0;
 
24
        p->iflag = 0;
 
25
        p->lineno = 1;
 
26
        p->ret = runq;
 
27
        runq = p;
35
28
}
36
 
word *newword(char *wd, word *next)
 
29
 
 
30
word*
 
31
newword(char *wd, word *next)
37
32
{
38
 
        word *p=new(word);
39
 
        p->word=strdup(wd);
40
 
        p->next=next;
 
33
        word *p = new(word);
 
34
        p->word = strdup(wd);
 
35
        p->next = next;
41
36
        return p;
42
37
}
43
 
void pushword(char *wd)
 
38
 
 
39
void
 
40
pushword(char *wd)
44
41
{
45
 
        if(runq->argv==0) panic("pushword but no argv!", 0);
46
 
        runq->argv->words=newword(wd, runq->argv->words);
 
42
        if(runq->argv==0)
 
43
                panic("pushword but no argv!", 0);
 
44
        runq->argv->words = newword(wd, runq->argv->words);
47
45
}
48
 
void popword(void){
 
46
 
 
47
void
 
48
popword(void)
 
49
{
49
50
        word *p;
50
 
        if(runq->argv==0) panic("popword but no argv!", 0);
51
 
        p=runq->argv->words;
52
 
        if(p==0) panic("popword but no word!", 0);
53
 
        runq->argv->words=p->next;
 
51
        if(runq->argv==0)
 
52
                panic("popword but no argv!", 0);
 
53
        p = runq->argv->words;
 
54
        if(p==0)
 
55
                panic("popword but no word!", 0);
 
56
        runq->argv->words = p->next;
54
57
        efree(p->word);
55
58
        efree((char *)p);
56
59
}
57
 
void freelist(word *w)
 
60
 
 
61
void
 
62
freelist(word *w)
58
63
{
59
64
        word *nw;
60
65
        while(w){
61
 
                nw=w->next;
 
66
                nw = w->next;
62
67
                efree(w->word);
63
68
                efree((char *)w);
64
 
                w=nw;
 
69
                w = nw;
65
70
        }
66
71
}
67
 
void pushlist(void){
68
 
        list *p=new(list);
69
 
        p->next=runq->argv;
70
 
        p->words=0;
71
 
        runq->argv=p;
 
72
 
 
73
void
 
74
pushlist(void)
 
75
{
 
76
        list *p = new(list);
 
77
        p->next = runq->argv;
 
78
        p->words = 0;
 
79
        runq->argv = p;
72
80
}
73
 
void poplist(void){
74
 
        list *p=runq->argv;
75
 
        if(p==0) panic("poplist but no argv", 0);
 
81
 
 
82
void
 
83
poplist(void)
 
84
{
 
85
        list *p = runq->argv;
 
86
        if(p==0)
 
87
                panic("poplist but no argv", 0);
76
88
        freelist(p->words);
77
 
        runq->argv=p->next;
 
89
        runq->argv = p->next;
78
90
        efree((char *)p);
79
91
}
80
 
int count(word *w)
 
92
 
 
93
int
 
94
count(word *w)
81
95
{
82
96
        int n;
83
 
        for(n=0;w;n++) w=w->next;
 
97
        for(n = 0;w;n++) w = w->next;
84
98
        return n;
85
99
}
86
 
void pushredir(int type, int from, int to){
87
 
        redir * rp=new(redir);
88
 
        rp->type=type;
89
 
        rp->from=from;
90
 
        rp->to=to;
91
 
        rp->next=runq->redir;
92
 
        runq->redir=rp;
 
100
 
 
101
void
 
102
pushredir(int type, int from, int to)
 
103
{
 
104
        redir * rp = new(redir);
 
105
        rp->type = type;
 
106
        rp->from = from;
 
107
        rp->to = to;
 
108
        rp->next = runq->redir;
 
109
        runq->redir = rp;
93
110
}
94
 
var *newvar(char *name, var *next)
 
111
 
 
112
var*
 
113
newvar(char *name, var *next)
95
114
{
96
 
        var *v=new(var);
97
 
        v->name=name;
98
 
        v->val=0;
99
 
        v->fn=0;
100
 
        v->changed=0;
101
 
        v->fnchanged=0;
102
 
        v->next=next;
 
115
        var *v = new(var);
 
116
        v->name = name;
 
117
        v->val = 0;
 
118
        v->fn = 0;
 
119
        v->changed = 0;
 
120
        v->fnchanged = 0;
 
121
        v->next = next;
103
122
        v->changefn = 0;
104
123
        return v;
105
124
}
117
136
        char num[12], *rcmain;
118
137
        int i;
119
138
        
120
 
        argc=getflags(argc, argv, "srdiIlxepvVc:1m:1[command]", 1);
121
 
        if(argc==-1) usage("[file [arg ...]]");
122
 
        if(argv[0][0]=='-') flag['l']=flagset;
123
 
        if(flag['I']) flag['i'] = 0;
 
139
        /* needed for rcmain later */
 
140
        putenv("PLAN9", unsharp("#9"));
 
141
 
 
142
        argc = getflags(argc, argv, "SsrdiIlxepvVc:1m:1[command]", 1);
 
143
        if(argc==-1)
 
144
                usage("[file [arg ...]]");
 
145
        if(argv[0][0]=='-')
 
146
                flag['l'] = flagset;
 
147
        if(flag['I'])
 
148
                flag['i'] = 0;
124
149
        else if(flag['i']==0 && argc==1 && Isatty(0)) flag['i'] = flagset;
125
 
        rcmain=flag['m']?flag['m'][0]:Rcmain(); 
126
 
        err=openfd(2);
 
150
        rcmain = flag['m'] ? flag['m'][0] : Rcmain();
 
151
        err = openfd(2);
127
152
        kinit();
128
153
        Trapinit();
129
154
        Vinit();
130
 
        itoa(num, mypid=getpid());
 
155
        inttoascii(num, mypid = getpid());
131
156
        pathinit();
132
157
        setvar("pid", newword(num, (word *)0));
133
158
        setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0)
134
159
                                :(word *)0);
135
160
        setvar("rcname", newword(argv[0], (word *)0));
136
 
        i=0;
137
 
        bootstrap[i++].i=1;
138
 
        bootstrap[i++].f=Xmark;
139
 
        bootstrap[i++].f=Xword;
140
 
        bootstrap[i++].s="*";
141
 
        bootstrap[i++].f=Xassign;
142
 
        bootstrap[i++].f=Xmark;
143
 
        bootstrap[i++].f=Xmark;
144
 
        bootstrap[i++].f=Xword;
145
 
        bootstrap[i++].s="*";
146
 
        bootstrap[i++].f=Xdol;
147
 
        bootstrap[i++].f=Xword;
148
 
        bootstrap[i++].s=rcmain;
149
 
        bootstrap[i++].f=Xword;
 
161
        i = 0;
 
162
        bootstrap[i++].i = 1;
 
163
        bootstrap[i++].f = Xmark;
 
164
        bootstrap[i++].f = Xword;
 
165
        bootstrap[i++].s="*";
 
166
        bootstrap[i++].f = Xassign;
 
167
        bootstrap[i++].f = Xmark;
 
168
        bootstrap[i++].f = Xmark;
 
169
        bootstrap[i++].f = Xword;
 
170
        bootstrap[i++].s="*";
 
171
        bootstrap[i++].f = Xdol;
 
172
        bootstrap[i++].f = Xword;
 
173
        bootstrap[i++].s = rcmain;
 
174
        bootstrap[i++].f = Xword;
150
175
        bootstrap[i++].s=".";
151
 
        bootstrap[i++].f=Xsimple;
152
 
        bootstrap[i++].f=Xexit;
153
 
        bootstrap[i].i=0;
 
176
        bootstrap[i++].f = Xsimple;
 
177
        bootstrap[i++].f = Xexit;
 
178
        bootstrap[i].i = 0;
154
179
        start(bootstrap, 1, (var *)0);
155
180
        /* prime bootstrap argv */
156
181
        pushlist();
157
182
        argv0 = strdup(argv[0]);
158
 
        for(i=argc-1;i!=0;--i) pushword(argv[i]);
 
183
        for(i = argc-1;i!=0;--i) pushword(argv[i]);
159
184
        for(;;){
160
 
                if(flag['r']) pfnc(err, runq);
 
185
                if(flag['r'])
 
186
                        pfnc(err, runq);
161
187
                runq->pc++;
162
188
                (*runq->code[runq->pc-1].f)();
163
 
                if(ntrap) dotrap();
 
189
                if(ntrap)
 
190
                        dotrap();
164
191
        }
165
 
    return 0;
166
192
}
167
193
/*
168
194
 * Opcode routines
198
224
 * Xpipefd[type]{... Xreturn}           connect {} to pipe (input or output,
199
225
 *                                      depending on type), push /dev/fd/??
200
226
 * Xpopm(value)                         pop value from stack
 
227
 * Xrdwr(file)[fd]                      open file for reading and writing
201
228
 * Xread(file)[fd]                      open file to read
202
229
 * Xsettraps(names){... Xreturn}                define trap functions
203
230
 * Xshowtraps                           print trap list
209
236
 * Xword[string]                        push string
210
237
 * Xwrite(file)[fd]                     open file to write
211
238
 */
212
 
void Xappend(void){
 
239
 
 
240
void
 
241
Xappend(void)
 
242
{
213
243
        char *file;
214
244
        int f;
215
245
        switch(count(runq->argv->words)){
216
 
        default: Xerror1(">> requires singleton"); return;
217
 
        case 0: Xerror1(">> requires file"); return;
218
 
        case 1: break;
 
246
        default:
 
247
                Xerror1(">> requires singleton");
 
248
                return;
 
249
        case 0:
 
250
                Xerror1(">> requires file");
 
251
                return;
 
252
        case 1:
 
253
                break;
219
254
        }
220
 
        file=runq->argv->words->word;
221
 
        if((f=open(file, 1))<0 && (f=Creat(file))<0){
 
255
        file = runq->argv->words->word;
 
256
        if((f = open(file, 1))<0 && (f = Creat(file))<0){
222
257
                pfmt(err, "%s: ", file);
223
258
                Xerror("can't open");
224
259
                return;
228
263
        runq->pc++;
229
264
        poplist();
230
265
}
231
 
void Xasync(void){
232
 
        int null=open("/dev/null", 0);
233
 
        int tty;
234
 
        int pid;
235
 
        char npid[10];
236
 
        if(null<0){
237
 
                Xerror("Can't open /dev/null\n");
238
 
                return;
239
 
        }
240
 
        switch(pid=rfork(RFFDG|RFPROC|RFNOTEG)){
241
 
        case -1:
242
 
                close(null);
243
 
                Xerror("try again");
244
 
                break;
245
 
        case 0:
246
 
                /*
247
 
                 * I don't know what the right thing to do here is,
248
 
                 * so this is all experimentally determined.
249
 
                 * If we just dup /dev/null onto 0, then running
250
 
                 * ssh foo & will reopen /dev/tty, try to read a password,
251
 
                 * get a signal, and repeat, in a tight loop, forever.
252
 
                 * Arguably this is a bug in ssh (it behaves the same
253
 
                 * way under bash as under rc) but I'm fixing it here 
254
 
                 * anyway.  If we dissociate the process from the tty,
255
 
                 * then it won't be able to open /dev/tty ever again.
256
 
                 * The SIG_IGN on SIGTTOU makes writing the tty
257
 
                 * (via fd 1 or 2, for example) succeed even though 
258
 
                 * our pgrp is not the terminal's controlling pgrp.
259
 
                 */
260
 
                if((tty=open("/dev/tty", OREAD)) >= 0){
261
 
                        /*
262
 
                         * Should make reads of tty fail, writes succeed.
263
 
                         */
264
 
                        signal(SIGTTIN, SIG_IGN);
265
 
                        signal(SIGTTOU, SIG_IGN);
266
 
                        ioctl(tty, TIOCNOTTY);
267
 
                        close(tty);
268
 
                }
269
 
                if(isatty(0))
270
 
                        pushredir(ROPEN, null, 0);
271
 
                else
272
 
                        close(null);
273
 
                start(runq->code, runq->pc+1, runq->local);
274
 
                runq->ret=0;
275
 
                break;
276
 
        default:
277
 
                close(null);
278
 
                runq->pc=runq->code[runq->pc].i;
279
 
                itoa(npid, pid);
280
 
                setvar("apid", newword(npid, (word *)0));
281
 
                break;
282
 
        }
283
 
}
284
 
void Xsettrue(void){
 
266
 
 
267
void
 
268
Xsettrue(void)
 
269
{
285
270
        setstatus("");
286
271
}
287
 
void Xbang(void){
 
272
 
 
273
void
 
274
Xbang(void)
 
275
{
288
276
        setstatus(truestatus()?"false":"");
289
277
}
290
 
void Xclose(void){
 
278
 
 
279
void
 
280
Xclose(void)
 
281
{
291
282
        pushredir(RCLOSE, runq->code[runq->pc].i, 0);
292
283
        runq->pc++;
293
284
}
294
 
void Xdup(void){
 
285
 
 
286
void
 
287
Xdup(void)
 
288
{
295
289
        pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc+1].i);
296
290
        runq->pc+=2;
297
291
}
298
 
void Xeflag(void){
 
292
 
 
293
void
 
294
Xeflag(void)
 
295
{
299
296
        if(eflagok && !truestatus()) Xexit();
300
297
}
301
 
void Xexit(void){
 
298
 
 
299
void
 
300
Xexit(void)
 
301
{
302
302
        struct var *trapreq;
303
303
        struct word *starval;
304
 
        static int beenhere=0;
 
304
        static int beenhere = 0;
305
305
        if(getpid()==mypid && !beenhere){
306
 
                trapreq=vlook("sigexit");
 
306
                trapreq = vlook("sigexit");
307
307
                if(trapreq->fn){
308
 
                        beenhere=1;
 
308
                        beenhere = 1;
309
309
                        --runq->pc;
310
 
                        starval=vlook("*")->val;
 
310
                        starval = vlook("*")->val;
311
311
                        start(trapreq->fn, trapreq->pc, (struct var *)0);
312
 
                        runq->local=newvar(strdup("*"), runq->local);
313
 
                        runq->local->val=copywords(starval, (struct word *)0);
314
 
                        runq->local->changed=1;
315
 
                        runq->redir=runq->startredir=0;
 
312
                        runq->local = newvar(strdup("*"), runq->local);
 
313
                        runq->local->val = copywords(starval, (struct word *)0);
 
314
                        runq->local->changed = 1;
 
315
                        runq->redir = runq->startredir = 0;
316
316
                        return;
317
317
                }
318
318
        }
319
319
        Exit(getstatus());
320
320
}
321
 
void Xfalse(void){
322
 
        if(truestatus()) runq->pc=runq->code[runq->pc].i;
 
321
 
 
322
void
 
323
Xfalse(void)
 
324
{
 
325
        if(truestatus()) runq->pc = runq->code[runq->pc].i;
323
326
        else runq->pc++;
324
327
}
325
328
int ifnot;              /* dynamic if not flag */
326
 
void Xifnot(void){
 
329
 
 
330
void
 
331
Xifnot(void)
 
332
{
327
333
        if(ifnot)
328
334
                runq->pc++;
329
335
        else
330
 
                runq->pc=runq->code[runq->pc].i;
331
 
}
332
 
void Xjump(void){
333
 
        runq->pc=runq->code[runq->pc].i;
334
 
}
335
 
void Xmark(void){
 
336
                runq->pc = runq->code[runq->pc].i;
 
337
}
 
338
 
 
339
void
 
340
Xjump(void)
 
341
{
 
342
        runq->pc = runq->code[runq->pc].i;
 
343
}
 
344
 
 
345
void
 
346
Xmark(void)
 
347
{
336
348
        pushlist();
337
349
}
338
 
void Xpopm(void){
339
 
        poplist();
340
 
}
341
 
void Xread(void){
342
 
        char *file;
343
 
        int f;
344
 
        switch(count(runq->argv->words)){
345
 
        default: Xerror1("< requires singleton\n"); return;
346
 
        case 0: Xerror1("< requires file\n"); return;
347
 
        case 1: break;
348
 
        }
349
 
        file=runq->argv->words->word;
350
 
        if((f=open(file, 0))<0){
351
 
                pfmt(err, "%s: ", file);
352
 
                Xerror("can't open");
353
 
                return;
354
 
        }
355
 
        pushredir(ROPEN, f, runq->code[runq->pc].i);
356
 
        runq->pc++;
357
 
        poplist();
358
 
}
359
 
void turfredir(void){
 
350
 
 
351
void
 
352
Xpopm(void)
 
353
{
 
354
        poplist();
 
355
}
 
356
 
 
357
void
 
358
Xread(void)
 
359
{
 
360
        char *file;
 
361
        int f;
 
362
        switch(count(runq->argv->words)){
 
363
        default:
 
364
                Xerror1("< requires singleton\n");
 
365
                return;
 
366
        case 0:
 
367
                Xerror1("< requires file\n");
 
368
                return;
 
369
        case 1:
 
370
                break;
 
371
        }
 
372
        file = runq->argv->words->word;
 
373
        if((f = open(file, 0))<0){
 
374
                pfmt(err, "%s: ", file);
 
375
                Xerror("can't open");
 
376
                return;
 
377
        }
 
378
        pushredir(ROPEN, f, runq->code[runq->pc].i);
 
379
        runq->pc++;
 
380
        poplist();
 
381
}
 
382
 
 
383
void
 
384
Xrdwr(void)
 
385
{
 
386
        char *file;
 
387
        int f;
 
388
 
 
389
        switch(count(runq->argv->words)){
 
390
        default:
 
391
                Xerror1("<> requires singleton\n");
 
392
                return;
 
393
        case 0:
 
394
                Xerror1("<> requires file\n");
 
395
                return;
 
396
        case 1:
 
397
                break;
 
398
        }
 
399
        file = runq->argv->words->word;
 
400
        if((f = open(file, ORDWR))<0){
 
401
                pfmt(err, "%s: ", file);
 
402
                Xerror("can't open");
 
403
                return;
 
404
        }
 
405
        pushredir(ROPEN, f, runq->code[runq->pc].i);
 
406
        runq->pc++;
 
407
        poplist();
 
408
}
 
409
 
 
410
void
 
411
turfredir(void)
 
412
{
360
413
        while(runq->redir!=runq->startredir)
361
414
                Xpopredir();
362
415
}
363
 
void Xpopredir(void){
364
 
        struct redir *rp=runq->redir;
365
 
        if(rp==0) panic("turfredir null!", 0);
366
 
        runq->redir=rp->next;
367
 
        if(rp->type==ROPEN) close(rp->from);
 
416
 
 
417
void
 
418
Xpopredir(void)
 
419
{
 
420
        struct redir *rp = runq->redir;
 
421
        if(rp==0)
 
422
                panic("turfredir null!", 0);
 
423
        runq->redir = rp->next;
 
424
        if(rp->type==ROPEN)
 
425
                close(rp->from);
368
426
        efree((char *)rp);
369
427
}
370
 
void Xreturn(void){
371
 
        struct thread *p=runq;
 
428
 
 
429
void
 
430
Xreturn(void)
 
431
{
 
432
        struct thread *p = runq;
372
433
        turfredir();
373
434
        while(p->argv) poplist();
374
435
        codefree(p->code);
375
 
        runq=p->ret;
 
436
        runq = p->ret;
376
437
        efree((char *)p);
377
 
        if(runq==0) Exit(getstatus());
378
 
}
379
 
void Xtrue(void){
380
 
        if(truestatus()) runq->pc++;
381
 
        else runq->pc=runq->code[runq->pc].i;
382
 
}
383
 
void Xif(void){
384
 
        ifnot=1;
385
 
        if(truestatus()) runq->pc++;
386
 
        else runq->pc=runq->code[runq->pc].i;
387
 
}
388
 
void Xwastrue(void){
389
 
        ifnot=0;
390
 
}
391
 
void Xword(void){
 
438
        if(runq==0)
 
439
                Exit(getstatus());
 
440
}
 
441
 
 
442
void
 
443
Xtrue(void)
 
444
{
 
445
        if(truestatus()) runq->pc++;
 
446
        else runq->pc = runq->code[runq->pc].i;
 
447
}
 
448
 
 
449
void
 
450
Xif(void)
 
451
{
 
452
        ifnot = 1;
 
453
        if(truestatus()) runq->pc++;
 
454
        else runq->pc = runq->code[runq->pc].i;
 
455
}
 
456
 
 
457
void
 
458
Xwastrue(void)
 
459
{
 
460
        ifnot = 0;
 
461
}
 
462
 
 
463
void
 
464
Xword(void)
 
465
{
392
466
        pushword(runq->code[runq->pc++].s);
393
467
}
394
 
void Xwrite(void){
 
468
 
 
469
void
 
470
Xwrite(void)
 
471
{
395
472
        char *file;
396
473
        int f;
397
474
        switch(count(runq->argv->words)){
398
 
        default: Xerror1("> requires singleton\n"); return;
399
 
        case 0: Xerror1("> requires file\n"); return;
400
 
        case 1: break;
 
475
        default:
 
476
                Xerror1("> requires singleton\n");
 
477
                return;
 
478
        case 0:
 
479
                Xerror1("> requires file\n");
 
480
                return;
 
481
        case 1:
 
482
                break;
401
483
        }
402
 
        file=runq->argv->words->word;
403
 
        if((f=Creat(file))<0){
 
484
        file = runq->argv->words->word;
 
485
        if((f = Creat(file))<0){
404
486
                pfmt(err, "%s: ", file);
405
487
                Xerror("can't open");
406
488
                return;
409
491
        runq->pc++;
410
492
        poplist();
411
493
}
412
 
char *_list2str(word *words, int c){
 
494
 
 
495
char*
 
496
list2str(word *words)
 
497
{
413
498
        char *value, *s, *t;
414
 
        int len=0;
 
499
        int len = 0;
415
500
        word *ap;
416
 
        for(ap=words;ap;ap=ap->next)
 
501
        for(ap = words;ap;ap = ap->next)
417
502
                len+=1+strlen(ap->word);
418
 
        value=emalloc(len+1);
419
 
        s=value;
420
 
        for(ap=words;ap;ap=ap->next){
421
 
                for(t=ap->word;*t;) *s++=*t++;
422
 
                *s++=c;
 
503
        value = emalloc(len+1);
 
504
        s = value;
 
505
        for(ap = words;ap;ap = ap->next){
 
506
                for(t = ap->word;*t;) *s++=*t++;
 
507
                *s++=' ';
423
508
        }
424
 
        if(s==value) *s='\0';
 
509
        if(s==value)
 
510
                *s='\0';
425
511
        else s[-1]='\0';
426
512
        return value;
427
513
}
428
 
char *list2str(word *words){
429
 
        return _list2str(words, ' ');
430
 
}
431
 
void Xmatch(void){
 
514
 
 
515
void
 
516
Xmatch(void)
 
517
{
432
518
        word *p;
433
519
        char *subject;
434
 
        subject=list2str(runq->argv->words);
 
520
        subject = list2str(runq->argv->words);
435
521
        setstatus("no match");
436
 
        for(p=runq->argv->next->words;p;p=p->next)
 
522
        for(p = runq->argv->next->words;p;p = p->next)
437
523
                if(match(subject, p->word, '\0')){
438
524
                        setstatus("");
439
525
                        break;
442
528
        poplist();
443
529
        poplist();
444
530
}
445
 
void Xcase(void){
 
531
 
 
532
void
 
533
Xcase(void)
 
534
{
446
535
        word *p;
447
536
        char *s;
448
 
        int ok=0;
449
 
        s=list2str(runq->argv->next->words);
450
 
        for(p=runq->argv->words;p;p=p->next){
 
537
        int ok = 0;
 
538
        s = list2str(runq->argv->next->words);
 
539
        for(p = runq->argv->words;p;p = p->next){
451
540
                if(match(s, p->word, '\0')){
452
 
                        ok=1;
 
541
                        ok = 1;
453
542
                        break;
454
543
                }
455
544
        }
457
546
        if(ok)
458
547
                runq->pc++;
459
548
        else
460
 
                runq->pc=runq->code[runq->pc].i;
 
549
                runq->pc = runq->code[runq->pc].i;
461
550
        poplist();
462
551
}
463
 
word *conclist(word *lp, word *rp, word *tail)
 
552
 
 
553
word*
 
554
conclist(word *lp, word *rp, word *tail)
464
555
{
465
556
        char *buf;
466
557
        word *v;
467
558
        if(lp->next || rp->next)
468
 
                tail=conclist(lp->next==0?lp:lp->next, rp->next==0?rp:rp->next,
 
559
                tail = conclist(lp->next==0?lp:lp->next, rp->next==0?rp:rp->next,
469
560
                        tail);
470
 
        buf=emalloc(strlen(lp->word)+strlen(rp->word)+1);
 
561
        buf = emalloc(strlen(lp->word)+strlen(rp->word)+1);
471
562
        strcpy(buf, lp->word);
472
563
        strcat(buf, rp->word);
473
 
        v=newword(buf, tail);
 
564
        v = newword(buf, tail);
474
565
        efree(buf);
475
566
        return v;
476
567
}
477
 
void Xconc(void){
478
 
        word *lp=runq->argv->words;
479
 
        word *rp=runq->argv->next->words;
480
 
        word *vp=runq->argv->next->next->words;
481
 
        int lc=count(lp), rc=count(rp);
 
568
 
 
569
void
 
570
Xconc(void)
 
571
{
 
572
        word *lp = runq->argv->words;
 
573
        word *rp = runq->argv->next->words;
 
574
        word *vp = runq->argv->next->next->words;
 
575
        int lc = count(lp), rc = count(rp);
482
576
        if(lc!=0 || rc!=0){
483
577
                if(lc==0 || rc==0){
484
578
                        Xerror1("null list in concatenation");
488
582
                        Xerror1("mismatched list lengths in concatenation");
489
583
                        return;
490
584
                }
491
 
                vp=conclist(lp, rp, vp);
 
585
                vp = conclist(lp, rp, vp);
492
586
        }
493
587
        poplist();
494
588
        poplist();
495
 
        runq->argv->words=vp;
 
589
        runq->argv->words = vp;
496
590
}
497
 
void Xassign(void){
 
591
 
 
592
void
 
593
Xassign(void)
 
594
{
498
595
        var *v;
499
596
        if(count(runq->argv->words)!=1){
500
597
                Xerror1("variable name not singleton!");
501
598
                return;
502
599
        }
503
600
        deglob(runq->argv->words->word);
504
 
        v=vlook(runq->argv->words->word);
 
601
        v = vlook(runq->argv->words->word);
505
602
        poplist();
506
603
        globlist();
507
604
        freewords(v->val);
508
 
        v->val=runq->argv->words;
509
 
        v->changed=1;
 
605
        v->val = runq->argv->words;
 
606
        v->changed = 1;
510
607
        if(v->changefn)
511
608
                v->changefn(v);
512
 
        runq->argv->words=0;
 
609
        runq->argv->words = 0;
513
610
        poplist();
514
611
}
515
612
/*
516
613
 * copy arglist a, adding the copy to the front of tail
517
614
 */
518
 
word *copywords(word *a, word *tail)
 
615
 
 
616
word*
 
617
copywords(word *a, word *tail)
519
618
{
520
 
        word *v=0, **end;
521
 
        for(end=&v;a;a=a->next,end=&(*end)->next)
522
 
                *end=newword(a->word, 0);
523
 
        *end=tail;
 
619
        word *v = 0, **end;
 
620
        for(end=&v;a;a = a->next,end=&(*end)->next)
 
621
                *end = newword(a->word, 0);
 
622
        *end = tail;
524
623
        return v;
525
624
}
526
 
void Xdol(void){
 
625
 
 
626
void
 
627
Xdol(void)
 
628
{
527
629
        word *a, *star;
528
630
        char *s, *t;
529
631
        int n;
531
633
                Xerror1("variable name not singleton!");
532
634
                return;
533
635
        }
534
 
        s=runq->argv->words->word;
 
636
        s = runq->argv->words->word;
535
637
        deglob(s);
536
 
        n=0;
537
 
        for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0';
538
 
        a=runq->argv->next->words;
 
638
        n = 0;
 
639
        for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
 
640
        a = runq->argv->next->words;
539
641
        if(n==0 || *t)
540
 
                a=copywords(vlook(s)->val, a);
 
642
                a = copywords(vlook(s)->val, a);
541
643
        else{
542
 
                star=vlook("*")->val;
 
644
                star = vlook("*")->val;
543
645
                if(star && 1<=n && n<=count(star)){
544
 
                        while(--n) star=star->next;
545
 
                        a=newword(star->word, a);
 
646
                        while(--n) star = star->next;
 
647
                        a = newword(star->word, a);
546
648
                }
547
649
        }
548
650
        poplist();
549
 
        runq->argv->words=a;
 
651
        runq->argv->words = a;
550
652
}
551
 
void Xqdol(void){
 
653
 
 
654
void
 
655
Xqdol(void)
 
656
{
552
657
        word *a, *p;
553
658
        char *s;
554
659
        int n;
556
661
                Xerror1("variable name not singleton!");
557
662
                return;
558
663
        }
559
 
        s=runq->argv->words->word;
 
664
        s = runq->argv->words->word;
560
665
        deglob(s);
561
 
        a=vlook(s)->val;
 
666
        a = vlook(s)->val;
562
667
        poplist();
563
 
        n=count(a);
 
668
        n = count(a);
564
669
        if(n==0){
565
670
                pushword("");
566
671
                return;
567
672
        }
568
 
        for(p=a;p;p=p->next) n+=strlen(p->word);
569
 
        s=emalloc(n);
 
673
        for(p = a;p;p = p->next) n+=strlen(p->word);
 
674
        s = emalloc(n);
570
675
        if(a){
571
676
                strcpy(s, a->word);
572
 
                for(p=a->next;p;p=p->next){
 
677
                for(p = a->next;p;p = p->next){
573
678
                        strcat(s, " ");
574
679
                        strcat(s, p->word);
575
680
                }
579
684
        pushword(s);
580
685
        efree(s);
581
686
}
582
 
word *subwords(word *val, int len, word *sub, word *a)
583
 
{
584
 
        int n;
 
687
 
 
688
word*
 
689
copynwords(word *a, word *tail, int n)
 
690
{
 
691
        word *v, **end;
 
692
        
 
693
        v = 0;
 
694
        end = &v;
 
695
        while(n-- > 0){
 
696
                *end = newword(a->word, 0);
 
697
                end = &(*end)->next;
 
698
                a = a->next;
 
699
        }
 
700
        *end = tail;
 
701
        return v;
 
702
}
 
703
 
 
704
word*
 
705
subwords(word *val, int len, word *sub, word *a)
 
706
{
 
707
        int n, m;
585
708
        char *s;
586
 
        if(!sub) return a;
587
 
        a=subwords(val, len, sub->next, a);
588
 
        s=sub->word;
 
709
        if(!sub)
 
710
                return a;
 
711
        a = subwords(val, len, sub->next, a);
 
712
        s = sub->word;
589
713
        deglob(s);
590
 
        n=0;
591
 
        while('0'<=*s && *s<='9') n=n*10+ *s++ -'0';
592
 
        if(n<1 || len<n) return a;
593
 
        for(;n!=1;--n) val=val->next;
594
 
        return newword(val->word, a);
 
714
        m = 0;
 
715
        n = 0;
 
716
        while('0'<=*s && *s<='9')
 
717
                n = n*10+ *s++ -'0';
 
718
        if(*s == '-'){
 
719
                if(*++s == 0)
 
720
                        m = len - n;
 
721
                else{
 
722
                        while('0'<=*s && *s<='9')
 
723
                                m = m*10+ *s++ -'0';
 
724
                        m -= n;
 
725
                }
 
726
        }
 
727
        if(n<1 || n>len || m<0)
 
728
                return a;
 
729
        if(n+m>len)
 
730
                m = len-n;
 
731
        while(--n > 0)
 
732
                val = val->next;
 
733
        return copynwords(val, a, m+1);
595
734
}
596
 
void Xsub(void){
 
735
 
 
736
void
 
737
Xsub(void)
 
738
{
597
739
        word *a, *v;
598
740
        char *s;
599
741
        if(count(runq->argv->next->words)!=1){
600
742
                Xerror1("variable name not singleton!");
601
743
                return;
602
744
        }
603
 
        s=runq->argv->next->words->word;
 
745
        s = runq->argv->next->words->word;
604
746
        deglob(s);
605
 
        a=runq->argv->next->next->words;
606
 
        v=vlook(s)->val;
607
 
        a=subwords(v, count(v), runq->argv->words, a);
608
 
        poplist();
609
 
        poplist();
610
 
        runq->argv->words=a;
 
747
        a = runq->argv->next->next->words;
 
748
        v = vlook(s)->val;
 
749
        a = subwords(v, count(v), runq->argv->words, a);
 
750
        poplist();
 
751
        poplist();
 
752
        runq->argv->words = a;
611
753
}
612
 
void Xcount(void){
 
754
 
 
755
void
 
756
Xcount(void)
 
757
{
613
758
        word *a;
614
759
        char *s, *t;
615
760
        int n;
618
763
                Xerror1("variable name not singleton!");
619
764
                return;
620
765
        }
621
 
        s=runq->argv->words->word;
 
766
        s = runq->argv->words->word;
622
767
        deglob(s);
623
 
        n=0;
624
 
        for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0';
 
768
        n = 0;
 
769
        for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
625
770
        if(n==0 || *t){
626
 
                a=vlook(s)->val;
627
 
                itoa(num, count(a));
 
771
                a = vlook(s)->val;
 
772
                inttoascii(num, count(a));
628
773
        }
629
774
        else{
630
 
                a=vlook("*")->val;
631
 
                itoa(num, a && 1<=n && n<=count(a)?1:0);
 
775
                a = vlook("*")->val;
 
776
                inttoascii(num, a && 1<=n && n<=count(a)?1:0);
632
777
        }
633
778
        poplist();
634
779
        pushword(num);
635
780
}
636
 
void Xlocal(void){
 
781
 
 
782
void
 
783
Xlocal(void)
 
784
{
637
785
        if(count(runq->argv->words)!=1){
638
786
                Xerror1("variable name must be singleton\n");
639
787
                return;
640
788
        }
641
789
        deglob(runq->argv->words->word);
642
 
        runq->local=newvar(strdup(runq->argv->words->word), runq->local);
643
 
        runq->local->val=copywords(runq->argv->next->words, (word *)0);
644
 
        runq->local->changed=1;
 
790
        runq->local = newvar(strdup(runq->argv->words->word), runq->local);
 
791
        runq->local->val = copywords(runq->argv->next->words, (word *)0);
 
792
        runq->local->changed = 1;
645
793
        poplist();
646
794
        poplist();
647
795
}
648
 
void Xunlocal(void){
649
 
        var *v=runq->local, *hid;
650
 
        if(v==0) panic("Xunlocal: no locals!", 0);
651
 
        runq->local=v->next;
652
 
        hid=vlook(v->name);
653
 
        hid->changed=1;
 
796
 
 
797
void
 
798
Xunlocal(void)
 
799
{
 
800
        var *v = runq->local, *hid;
 
801
        if(v==0)
 
802
                panic("Xunlocal: no locals!", 0);
 
803
        runq->local = v->next;
 
804
        hid = vlook(v->name);
 
805
        hid->changed = 1;
654
806
        efree(v->name);
655
807
        freewords(v->val);
656
808
        efree((char *)v);
657
809
}
658
 
void freewords(word *w)
 
810
 
 
811
void
 
812
freewords(word *w)
659
813
{
660
814
        word *nw;
661
815
        while(w){
662
816
                efree(w->word);
663
 
                nw=w->next;
 
817
                nw = w->next;
664
818
                efree((char *)w);
665
 
                w=nw;
 
819
                w = nw;
666
820
        }
667
821
}
668
 
void Xfn(void){
 
822
 
 
823
void
 
824
Xfn(void)
 
825
{
669
826
        var *v;
670
827
        word *a;
671
828
        int end;
672
 
        end=runq->code[runq->pc].i;
673
 
        for(a=runq->argv->words;a;a=a->next){
674
 
                v=gvlook(a->word);
675
 
                if(v->fn) codefree(v->fn);
676
 
                v->fn=codecopy(runq->code);
677
 
                v->pc=runq->pc+2;
678
 
                v->fnchanged=1;
 
829
        end = runq->code[runq->pc].i;
 
830
        for(a = runq->argv->words;a;a = a->next){
 
831
                v = gvlook(a->word);
 
832
                if(v->fn)
 
833
                        codefree(v->fn);
 
834
                v->fn = codecopy(runq->code);
 
835
                v->pc = runq->pc+2;
 
836
                v->fnchanged = 1;
679
837
        }
680
 
        runq->pc=end;
 
838
        runq->pc = end;
681
839
        poplist();
682
840
}
683
 
void Xdelfn(void){
 
841
 
 
842
void
 
843
Xdelfn(void)
 
844
{
684
845
        var *v;
685
846
        word *a;
686
 
        for(a=runq->argv->words;a;a=a->next){
687
 
                v=gvlook(a->word);
688
 
                if(v->fn) codefree(v->fn);
689
 
                v->fn=0;
690
 
                v->fnchanged=1;
 
847
        for(a = runq->argv->words;a;a = a->next){
 
848
                v = gvlook(a->word);
 
849
                if(v->fn)
 
850
                        codefree(v->fn);
 
851
                v->fn = 0;
 
852
                v->fnchanged = 1;
691
853
        }
692
854
        poplist();
693
855
}
694
 
void Xpipe(void){
695
 
        struct thread *p=runq;
696
 
        int pc=p->pc, forkid;
697
 
        int lfd=p->code[pc++].i;
698
 
        int rfd=p->code[pc++].i;
699
 
        int pfd[2];
700
 
        if(pipe(pfd)<0){
701
 
                Xerror("can't get pipe");
702
 
                return;
703
 
        }
704
 
        switch(forkid=fork()){
705
 
        case -1:
706
 
                Xerror("try again");
707
 
                break;
708
 
        case 0:
709
 
                start(p->code, pc+2, runq->local);
710
 
                runq->ret=0;
711
 
                close(pfd[PRD]);
712
 
                pushredir(ROPEN, pfd[PWR], lfd);
713
 
                break;
714
 
        default:
715
 
                start(p->code, p->code[pc].i, runq->local);
716
 
                close(pfd[PWR]);
717
 
                pushredir(ROPEN, pfd[PRD], rfd);
718
 
                p->pc=p->code[pc+1].i;
719
 
                p->pid=forkid;
720
 
                break;
721
 
        }
722
 
}
723
 
char *concstatus(char *s, char *t)
 
856
 
 
857
char*
 
858
concstatus(char *s, char *t)
724
859
{
725
860
        static char v[NSTATUS+1];
726
 
        int n=strlen(s);
 
861
        int n = strlen(s);
727
862
        strncpy(v, s, NSTATUS);
728
863
        if(n<NSTATUS){
729
864
                v[n]='|';
732
867
        v[NSTATUS]='\0';
733
868
        return v;
734
869
}
735
 
void Xpipewait(void){
 
870
 
 
871
void
 
872
Xpipewait(void)
 
873
{
736
874
        char status[NSTATUS+1];
737
875
        if(runq->pid==-1)
738
876
                setstatus(concstatus(runq->status, getstatus()));
744
882
                setstatus(concstatus(getstatus(), status));
745
883
        }
746
884
}
747
 
void Xrdcmds(void){
748
 
        struct thread *p=runq;
 
885
 
 
886
void
 
887
Xrdcmds(void)
 
888
{
 
889
        struct thread *p = runq;
749
890
        word *prompt;
750
891
        flush(err);
751
 
        nerror=0;
 
892
        nerror = 0;
752
893
        if(flag['s'] && !truestatus())
753
894
                pfmt(err, "status=%v\n", vlook("status")->val);
754
895
        if(runq->iflag){
755
 
                prompt=vlook("prompt")->val;
 
896
                prompt = vlook("prompt")->val;
756
897
                if(prompt)
757
 
                        promptstr=prompt->word;
 
898
                        promptstr = prompt->word;
758
899
                else
759
900
                        promptstr="% ";
760
901
        }
761
902
        Noerror();
762
903
        if(yyparse()){
763
904
                if(!p->iflag || p->eof && !Eintr()){
764
 
                        if(p->cmdfile) efree(p->cmdfile);
 
905
                        if(p->cmdfile)
 
906
                                efree(p->cmdfile);
765
907
                        closeio(p->cmdfd);
766
908
                        Xreturn();      /* should this be omitted? */
767
909
                }
768
910
                else{
769
911
                        if(Eintr()){
770
912
                                pchr(err, '\n');
771
 
                                p->eof=0;
 
913
                                p->eof = 0;
772
914
                        }
773
915
                        --p->pc;        /* go back for next command */
774
916
                }
780
922
        }
781
923
        freenodes();
782
924
}
783
 
void Xerror(char *s)
 
925
 
 
926
void
 
927
Xerror(char *s)
784
928
{
785
929
        if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
786
930
                pfmt(err, "rc: %s: %r\n", s);
790
934
        setstatus("error");
791
935
        while(!runq->iflag) Xreturn();
792
936
}
793
 
void Xerror1(char *s)
 
937
 
 
938
void
 
939
Xerror1(char *s)
794
940
{
795
941
        if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
796
942
                pfmt(err, "rc: %s\n", s);
800
946
        setstatus("error");
801
947
        while(!runq->iflag) Xreturn();
802
948
}
803
 
void Xbackq(void){
804
 
        char wd[8193];
805
 
        int c;
806
 
        char *s, *ewd=&wd[8192], *stop;
807
 
        struct io *f;
808
 
        var *ifs=vlook("ifs");
809
 
        word *v, *nextv;
810
 
        int pfd[2];
811
 
        int pid;
812
 
        stop=ifs->val?ifs->val->word:"";
813
 
        if(pipe(pfd)<0){
814
 
                Xerror("can't make pipe");
815
 
                return;
816
 
        }
817
 
        switch(pid=fork()){
818
 
        case -1: Xerror("try again");
819
 
                close(pfd[PRD]);
820
 
                close(pfd[PWR]);
821
 
                return;
822
 
        case 0:
823
 
                close(pfd[PRD]);
824
 
                start(runq->code, runq->pc+1, runq->local);
825
 
                pushredir(ROPEN, pfd[PWR], 1);
826
 
                return;
827
 
        default:
828
 
                close(pfd[PWR]);
829
 
                f=openfd(pfd[PRD]);
830
 
                s=wd;
831
 
                v=0;
832
 
                while((c=rchr(f))!=EOF){
833
 
                        if(strchr(stop, c) || s==ewd){
834
 
                                if(s!=wd){
835
 
                                        *s='\0';
836
 
                                        v=newword(wd, v);
837
 
                                        s=wd;
838
 
                                }
839
 
                        }
840
 
                        else *s++=c;
841
 
                }
842
 
                if(s!=wd){
843
 
                        *s='\0';
844
 
                        v=newword(wd, v);
845
 
                }
846
 
                closeio(f);
847
 
                Waitfor(pid, 0);
848
 
                /* v points to reversed arglist -- reverse it onto argv */
849
 
                while(v){
850
 
                        nextv=v->next;
851
 
                        v->next=runq->argv->words;
852
 
                        runq->argv->words=v;
853
 
                        v=nextv;
854
 
                }
855
 
                runq->pc=runq->code[runq->pc].i;
856
 
                return;
857
 
        }
858
 
}
859
 
/*
860
 
 * Who should wait for the exit from the fork?
861
 
 */
862
 
void Xpipefd(void){
863
 
        struct thread *p=runq;
864
 
        int pc=p->pc;
865
 
        char name[40];
866
 
        int pfd[2];
867
 
        int sidefd, mainfd;
868
 
        if(pipe(pfd)<0){
869
 
                Xerror("can't get pipe");
870
 
                return;
871
 
        }
872
 
        if(p->code[pc].i==READ){
873
 
                sidefd=pfd[PWR];
874
 
                mainfd=pfd[PRD];
875
 
        }
876
 
        else{
877
 
                sidefd=pfd[PRD];
878
 
                mainfd=pfd[PWR];
879
 
        }
880
 
        switch(fork()){
881
 
        case -1:
882
 
                Xerror("try again");
883
 
                break;
884
 
        case 0:
885
 
                start(p->code, pc+2, runq->local);
886
 
                close(mainfd);
887
 
                pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
888
 
                runq->ret=0;
889
 
                break;
890
 
        default:
891
 
                close(sidefd);
892
 
                pushredir(ROPEN, mainfd, mainfd);       /* isn't this a noop? */
893
 
                strcpy(name, Fdprefix);
894
 
                itoa(name+strlen(name), mainfd);
895
 
                pushword(name);
896
 
                p->pc=p->code[pc+1].i;
897
 
                break;
898
 
        }
899
 
}
900
 
void Xsubshell(void){
901
 
        int pid;
902
 
        switch(pid=fork()){
903
 
        case -1:
904
 
                Xerror("try again");
905
 
                break;
906
 
        case 0:
907
 
                start(runq->code, runq->pc+1, runq->local);
908
 
                runq->ret=0;
909
 
                break;
910
 
        default:
911
 
                Waitfor(pid, 1);
912
 
                runq->pc=runq->code[runq->pc].i;
913
 
                break;
914
 
        }
915
 
}
916
 
void setstatus(char *s)
 
949
 
 
950
void
 
951
setstatus(char *s)
917
952
{
918
953
        setvar("status", newword(s, (word *)0));
919
954
}
920
 
char *getstatus(void){
921
 
        var *status=vlook("status");
 
955
 
 
956
char*
 
957
getstatus(void)
 
958
{
 
959
        var *status = vlook("status");
922
960
        return status->val?status->val->word:"";
923
961
}
924
 
int truestatus(void){
 
962
 
 
963
int
 
964
truestatus(void)
 
965
{
925
966
        char *s;
926
 
        for(s=getstatus();*s;s++)
927
 
                if(*s!='|' && *s!='0') return 0;
 
967
        for(s = getstatus();*s;s++)
 
968
                if(*s!='|' && *s!='0')
 
969
                        return 0;
928
970
        return 1;
929
971
}
930
 
void Xdelhere(void){
 
972
 
 
973
void
 
974
Xdelhere(void)
 
975
{
931
976
        Unlink(runq->code[runq->pc++].s);
932
977
}
933
 
void Xfor(void){
 
978
 
 
979
void
 
980
Xfor(void)
 
981
{
934
982
        if(runq->argv->words==0){
935
983
                poplist();
936
 
                runq->pc=runq->code[runq->pc].i;
 
984
                runq->pc = runq->code[runq->pc].i;
937
985
        }
938
986
        else{
939
987
                freelist(runq->local->val);
940
 
                runq->local->val=runq->argv->words;
941
 
                runq->local->changed=1;
942
 
                runq->argv->words=runq->argv->words->next;
943
 
                runq->local->val->next=0;
 
988
                runq->local->val = runq->argv->words;
 
989
                runq->local->changed = 1;
 
990
                runq->argv->words = runq->argv->words->next;
 
991
                runq->local->val->next = 0;
944
992
                runq->pc++;
945
993
        }
946
994
}
947
 
void Xglob(void){
 
995
 
 
996
void
 
997
Xglob(void)
 
998
{
948
999
        globlist();
949
1000
}