GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/csh/func.c Lines: 0 636 0.0 %
Date: 2017-11-13 Branches: 0 509 0.0 %

Line Branch Exec Source
1
/*    $OpenBSD: func.c,v 1.35 2017/08/30 06:42:21 anton Exp $       */
2
/*    $NetBSD: func.c,v 1.11 1996/02/09 02:28:29 christos Exp $       */
3
4
/*-
5
 * Copyright (c) 1980, 1991, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
#include <sys/types.h>
34
#include <sys/stat.h>
35
#include <signal.h>
36
#include <locale.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <unistd.h>
40
#include <stdarg.h>
41
42
#include "csh.h"
43
#include "extern.h"
44
#include "pathnames.h"
45
46
extern char **environ;
47
48
static int zlast = -1;
49
static void	islogin(void);
50
static void	reexecute(struct command *);
51
static void	preread(void);
52
static void	doagain(void);
53
static void	search(int, int, Char *);
54
static int	getword(Char *);
55
static int	keyword(Char *);
56
static void	toend(void);
57
static void	xecho(int, Char **);
58
static void	Unsetenv(Char *);
59
60
struct biltins *
61
isbfunc(struct command *t)
62
{
63
    Char *cp = t->t_dcom[0];
64
    struct biltins *bp, *bp1, *bp2;
65
    static struct biltins label = {"", dozip, 0, 0};
66
    static struct biltins foregnd = {"%job", dofg1, 0, 0};
67
    static struct biltins backgnd = {"%job &", dobg1, 0, 0};
68
69
    if (lastchr(cp) == ':') {
70
	label.bname = short2str(cp);
71
	return (&label);
72
    }
73
    if (*cp == '%') {
74
	if (t->t_dflg & F_AMPERSAND) {
75
	    t->t_dflg &= ~F_AMPERSAND;
76
	    backgnd.bname = short2str(cp);
77
	    return (&backgnd);
78
	}
79
	foregnd.bname = short2str(cp);
80
	return (&foregnd);
81
    }
82
    /*
83
     * Binary search Bp1 is the beginning of the current search range. Bp2 is
84
     * one past the end.
85
     */
86
    for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) {
87
	int i;
88
89
	bp = bp1 + ((bp2 - bp1) >> 1);
90
	if ((i = *cp - *bp->bname) == 0 &&
91
	    (i = Strcmp(cp, str2short(bp->bname))) == 0)
92
	    return bp;
93
	if (i < 0)
94
	    bp2 = bp;
95
	else
96
	    bp1 = bp + 1;
97
    }
98
    return (0);
99
}
100
101
void
102
func(struct command *t, struct biltins *bp)
103
{
104
    int     i;
105
106
    xechoit(t->t_dcom);
107
    setname(bp->bname);
108
    i = blklen(t->t_dcom) - 1;
109
    if (i < bp->minargs)
110
	stderror(ERR_NAME | ERR_TOOFEW);
111
    if (i > bp->maxargs)
112
	stderror(ERR_NAME | ERR_TOOMANY);
113
    (*bp->bfunct) (t->t_dcom, t);
114
}
115
116
void
117
/*ARGSUSED*/
118
doonintr(Char **v, struct command *t)
119
{
120
    Char *cp;
121
    Char *vv = v[1];
122
    sigset_t sigset;
123
124
    if (parintr == SIG_IGN)
125
	return;
126
    if (setintr && intty)
127
	stderror(ERR_NAME | ERR_TERMINAL);
128
    cp = gointr;
129
    gointr = 0;
130
    free(cp);
131
    if (vv == 0) {
132
	if (setintr) {
133
	    sigemptyset(&sigset);
134
	    sigaddset(&sigset, SIGINT);
135
	    sigprocmask(SIG_BLOCK, &sigset, NULL);
136
	} else
137
	    (void) signal(SIGINT, SIG_DFL);
138
	gointr = 0;
139
    }
140
    else if (eq((vv = strip(vv)), STRminus)) {
141
	(void) signal(SIGINT, SIG_IGN);
142
	gointr = Strsave(STRminus);
143
    }
144
    else {
145
	gointr = Strsave(vv);
146
	(void) signal(SIGINT, pintr);
147
    }
148
}
149
150
void
151
/*ARGSUSED*/
152
donohup(Char **v, struct command *t)
153
{
154
    if (intty)
155
	stderror(ERR_NAME | ERR_TERMINAL);
156
    if (setintr == 0) {
157
	(void) signal(SIGHUP, SIG_IGN);
158
    }
159
}
160
161
void
162
/*ARGSUSED*/
163
dozip(Char **v, struct command *t)
164
{
165
    ;
166
}
167
168
void
169
prvars(void)
170
{
171
    plist(&shvhed);
172
}
173
174
void
175
/*ARGSUSED*/
176
doalias(Char **v, struct command *t)
177
{
178
    struct varent *vp;
179
    Char *p;
180
181
    v++;
182
    p = *v++;
183
    if (p == 0)
184
	plist(&aliases);
185
    else if (*v == 0) {
186
	vp = adrof1(strip(p), &aliases);
187
	if (vp) {
188
	    blkpr(cshout, vp->vec);
189
	    fputc('\n', cshout);
190
	}
191
    }
192
    else {
193
	if (eq(p, STRalias) || eq(p, STRunalias)) {
194
	    setname(vis_str(p));
195
	    stderror(ERR_NAME | ERR_DANGER);
196
	}
197
	set1(strip(p), saveblk(v), &aliases);
198
    }
199
}
200
201
void
202
/*ARGSUSED*/
203
unalias(Char **v, struct command *t)
204
{
205
    unset1(v, &aliases);
206
}
207
208
void
209
/*ARGSUSED*/
210
dologout(Char **v, struct command *t)
211
{
212
    islogin();
213
    goodbye();
214
}
215
216
void
217
/*ARGSUSED*/
218
dologin(Char **v, struct command *t)
219
{
220
    islogin();
221
    rechist();
222
    (void) signal(SIGTERM, parterm);
223
    (void) execl(_PATH_LOGIN, "login", short2str(v[1]), (char *)NULL);
224
    untty();
225
    xexit(1);
226
}
227
228
static void
229
islogin(void)
230
{
231
    if (chkstop == 0 && setintr)
232
	panystop(0);
233
    if (loginsh)
234
	return;
235
    stderror(ERR_NOTLOGIN);
236
}
237
238
void
239
doif(Char **v, struct command *kp)
240
{
241
    int i;
242
    Char **vv;
243
244
    v++;
245
    i = expr(&v);
246
    vv = v;
247
    if (*vv == NULL)
248
	stderror(ERR_NAME | ERR_EMPTYIF);
249
    if (eq(*vv, STRthen)) {
250
	if (*++vv)
251
	    stderror(ERR_NAME | ERR_IMPRTHEN);
252
	setname(vis_str(STRthen));
253
	/*
254
	 * If expression was zero, then scan to else, otherwise just fall into
255
	 * following code.
256
	 */
257
	if (!i)
258
	    search(T_IF, 0, NULL);
259
	return;
260
    }
261
    /*
262
     * Simple command attached to this if. Left shift the node in this tree,
263
     * munging it so we can reexecute it.
264
     */
265
    if (i) {
266
	lshift(kp->t_dcom, vv - kp->t_dcom);
267
	reexecute(kp);
268
	donefds();
269
    }
270
}
271
272
/*
273
 * Reexecute a command, being careful not
274
 * to redo i/o redirection, which is already set up.
275
 */
276
static void
277
reexecute(struct command *kp)
278
{
279
    kp->t_dflg &= F_SAVE;
280
    kp->t_dflg |= F_REPEAT;
281
    /*
282
     * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set
283
     * pgrp's as the jobs would then have no way to get the tty (we can't give
284
     * it to them, and our parent wouldn't know their pgrp, etc.
285
     */
286
    execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL);
287
}
288
289
void
290
/*ARGSUSED*/
291
doelse(Char **v, struct command *t)
292
{
293
    search(T_ELSE, 0, NULL);
294
}
295
296
void
297
/*ARGSUSED*/
298
dogoto(Char **v, struct command *t)
299
{
300
    Char   *lp;
301
302
    gotolab(lp = globone(v[1], G_ERROR));
303
    free(lp);
304
}
305
306
void
307
gotolab(Char *lab)
308
{
309
    struct whyle *wp;
310
    /*
311
     * While we still can, locate any unknown ends of existing loops. This
312
     * obscure code is the WORST result of the fact that we don't really parse.
313
     */
314
    zlast = T_GOTO;
315
    for (wp = whyles; wp; wp = wp->w_next)
316
	if (wp->w_end.type == F_SEEK && wp->w_end.f_seek == 0) {
317
	    search(T_BREAK, 0, NULL);
318
	    btell(&wp->w_end);
319
	}
320
	else
321
	    bseek(&wp->w_end);
322
    search(T_GOTO, 0, lab);
323
    /*
324
     * Eliminate loops which were exited.
325
     */
326
    wfree();
327
}
328
329
void
330
/*ARGSUSED*/
331
doswitch(Char **v, struct command *t)
332
{
333
    Char *cp, *lp;
334
335
    v++;
336
    if (!*v || *(*v++) != '(')
337
	stderror(ERR_SYNTAX);
338
    cp = **v == ')' ? STRNULL : *v++;
339
    if (*(*v++) != ')')
340
	v--;
341
    if (*v)
342
	stderror(ERR_SYNTAX);
343
    search(T_SWITCH, 0, lp = globone(cp, G_ERROR));
344
    free(lp);
345
}
346
347
void
348
/*ARGSUSED*/
349
dobreak(Char **v, struct command *t)
350
{
351
    if (whyles)
352
	toend();
353
    else
354
	stderror(ERR_NAME | ERR_NOTWHILE);
355
}
356
357
void
358
/*ARGSUSED*/
359
doexit(Char **v, struct command *t)
360
{
361
    if (chkstop == 0 && (intty || intact) && evalvec == 0)
362
	panystop(0);
363
    /*
364
     * Don't DEMAND parentheses here either.
365
     */
366
    v++;
367
    if (*v) {
368
	set(STRstatus, putn(expr(&v)));
369
	if (*v)
370
	    stderror(ERR_NAME | ERR_EXPRESSION);
371
    }
372
    btoeof();
373
    if (intty)
374
	(void) close(SHIN);
375
}
376
377
void
378
/*ARGSUSED*/
379
doforeach(Char **v, struct command *t)
380
{
381
    Char *cp, *sp;
382
    struct whyle *nwp;
383
384
    v++;
385
    sp = cp = strip(*v);
386
    if (!letter(*sp))
387
	stderror(ERR_NAME | ERR_VARBEGIN);
388
    while (*cp && alnum(*cp))
389
	cp++;
390
    if (*cp)
391
	stderror(ERR_NAME | ERR_VARALNUM);
392
    if ((cp - sp) > MAXVARLEN)
393
	stderror(ERR_NAME | ERR_VARTOOLONG);
394
    cp = *v++;
395
    if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')')
396
	stderror(ERR_NAME | ERR_NOPAREN);
397
    v++;
398
    gflag = 0, tglob(v);
399
    v = globall(v);
400
    if (v == 0)
401
	stderror(ERR_NAME | ERR_NOMATCH);
402
    nwp = xcalloc(1, sizeof *nwp);
403
    nwp->w_fe = nwp->w_fe0 = v;
404
    gargv = 0;
405
    btell(&nwp->w_start);
406
    nwp->w_fename = Strsave(cp);
407
    nwp->w_next = whyles;
408
    nwp->w_end.type = F_SEEK;
409
    whyles = nwp;
410
    /*
411
     * Pre-read the loop so as to be more comprehensible to a terminal user.
412
     */
413
    zlast = T_FOREACH;
414
    if (intty)
415
	preread();
416
    doagain();
417
}
418
419
void
420
/*ARGSUSED*/
421
dowhile(Char **v, struct command *t)
422
{
423
    int status;
424
    bool again = whyles != 0 && SEEKEQ(&whyles->w_start, &lineloc) &&
425
    whyles->w_fename == 0;
426
427
    v++;
428
    /*
429
     * Implement prereading here also, taking care not to evaluate the
430
     * expression before the loop has been read up from a terminal.
431
     */
432
    if (intty && !again)
433
	status = !exp0(&v, 1);
434
    else
435
	status = !expr(&v);
436
    if (*v)
437
	stderror(ERR_NAME | ERR_EXPRESSION);
438
    if (!again) {
439
	struct whyle *nwp = xcalloc(1, sizeof(*nwp));
440
441
	nwp->w_start = lineloc;
442
	nwp->w_end.type = F_SEEK;
443
	nwp->w_end.f_seek = 0;
444
	nwp->w_next = whyles;
445
	whyles = nwp;
446
	zlast = T_WHILE;
447
	if (intty) {
448
	    /*
449
	     * The tty preread
450
	     */
451
	    preread();
452
	    doagain();
453
	    return;
454
	}
455
    }
456
    if (status)
457
	/* We ain't gonna loop no more, no more! */
458
	toend();
459
}
460
461
static void
462
preread(void)
463
{
464
    sigset_t sigset;
465
466
    whyles->w_end.type = I_SEEK;
467
    if (setintr) {
468
	sigemptyset(&sigset);
469
	sigaddset(&sigset, SIGINT);
470
	sigprocmask(SIG_UNBLOCK, &sigset, NULL);
471
    }
472
473
    search(T_BREAK, 0, NULL);		/* read the expression in */
474
    if (setintr)
475
	sigprocmask(SIG_BLOCK, &sigset, NULL);
476
    btell(&whyles->w_end);
477
}
478
479
void
480
/*ARGSUSED*/
481
doend(Char **v, struct command *t)
482
{
483
    if (!whyles)
484
	stderror(ERR_NAME | ERR_NOTWHILE);
485
    btell(&whyles->w_end);
486
    doagain();
487
}
488
489
void
490
/*ARGSUSED*/
491
docontin(Char **v, struct command *t)
492
{
493
    if (!whyles)
494
	stderror(ERR_NAME | ERR_NOTWHILE);
495
    doagain();
496
}
497
498
static void
499
doagain(void)
500
{
501
    /* Repeating a while is simple */
502
    if (whyles->w_fename == 0) {
503
	bseek(&whyles->w_start);
504
	return;
505
    }
506
    /*
507
     * The foreach variable list actually has a spurious word ")" at the end of
508
     * the w_fe list.  Thus we are at the of the list if one word beyond this
509
     * is 0.
510
     */
511
    if (!whyles->w_fe[1]) {
512
	dobreak(NULL, NULL);
513
	return;
514
    }
515
    set(whyles->w_fename, Strsave(*whyles->w_fe++));
516
    bseek(&whyles->w_start);
517
}
518
519
void
520
dorepeat(Char **v, struct command *kp)
521
{
522
    int i;
523
    sigset_t sigset;
524
525
    i = getn(v[1]);
526
    if (setintr) {
527
	sigemptyset(&sigset);
528
	sigaddset(&sigset, SIGINT);
529
	sigprocmask(SIG_BLOCK, &sigset, NULL);
530
    }
531
    lshift(v, 2);
532
    while (i > 0) {
533
	if (setintr)
534
	    sigprocmask(SIG_UNBLOCK, &sigset, NULL);
535
	reexecute(kp);
536
	--i;
537
    }
538
    donefds();
539
    if (setintr)
540
	sigprocmask(SIG_UNBLOCK, &sigset, NULL);
541
}
542
543
void
544
/*ARGSUSED*/
545
doswbrk(Char **v, struct command *t)
546
{
547
    search(T_BRKSW, 0, NULL);
548
}
549
550
int
551
srchx(Char *cp)
552
{
553
    struct srch *sp, *sp1, *sp2;
554
    int i;
555
556
    /*
557
     * Binary search Sp1 is the beginning of the current search range. Sp2 is
558
     * one past the end.
559
     */
560
    for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) {
561
	sp = sp1 + ((sp2 - sp1) >> 1);
562
	if ((i = *cp - *sp->s_name) == 0 &&
563
	    (i = Strcmp(cp, str2short(sp->s_name))) == 0)
564
	    return sp->s_value;
565
	if (i < 0)
566
	    sp2 = sp;
567
	else
568
	    sp1 = sp + 1;
569
    }
570
    return (-1);
571
}
572
573
static Char Stype;
574
static Char *Sgoal;
575
576
static void
577
search(int type, int level, Char *goal)
578
{
579
    Char    wordbuf[BUFSIZ];
580
    Char *aword = wordbuf;
581
    Char *cp;
582
583
    Stype = type;
584
    Sgoal = goal;
585
    if (type == T_GOTO) {
586
	struct Ain a;
587
	a.type = F_SEEK;
588
	a.f_seek = 0;
589
	bseek(&a);
590
    }
591
    do {
592
	needprompt = intty && fseekp == feobp && aret == F_SEEK;
593
	if (!filec && needprompt)
594
	    (void) fprintf(cshout, "? "), (void) fflush(cshout);
595
	aword[0] = 0;
596
	(void) getword(aword);
597
	switch (srchx(aword)) {
598
599
	case T_ELSE:
600
	    if (level == 0 && type == T_IF)
601
		return;
602
	    break;
603
604
	case T_IF:
605
	    while (getword(aword))
606
		continue;
607
	    if ((type == T_IF || type == T_ELSE) &&
608
		eq(aword, STRthen))
609
		level++;
610
	    break;
611
612
	case T_ENDIF:
613
	    if (type == T_IF || type == T_ELSE)
614
		level--;
615
	    break;
616
617
	case T_FOREACH:
618
	case T_WHILE:
619
	    if (type == T_BREAK)
620
		level++;
621
	    break;
622
623
	case T_END:
624
	    if (type == T_BREAK)
625
		level--;
626
	    break;
627
628
	case T_SWITCH:
629
	    if (type == T_SWITCH || type == T_BRKSW)
630
		level++;
631
	    break;
632
633
	case T_ENDSW:
634
	    if (type == T_SWITCH || type == T_BRKSW)
635
		level--;
636
	    break;
637
638
	case T_LABEL:
639
	    if (type == T_GOTO && getword(aword) && eq(aword, goal))
640
		level = -1;
641
	    break;
642
643
	default:
644
	    if (type != T_GOTO && (type != T_SWITCH || level != 0))
645
		break;
646
	    if (lastchr(aword) != ':')
647
		break;
648
	    aword[Strlen(aword) - 1] = 0;
649
	    if ((type == T_GOTO && eq(aword, goal)) ||
650
		(type == T_SWITCH && eq(aword, STRdefault)))
651
		level = -1;
652
	    break;
653
654
	case T_CASE:
655
	    if (type != T_SWITCH || level != 0)
656
		break;
657
	    (void) getword(aword);
658
	    if (lastchr(aword) == ':')
659
		aword[Strlen(aword) - 1] = 0;
660
	    cp = strip(Dfix1(aword));
661
	    if (Gmatch(goal, cp))
662
		level = -1;
663
	    free(cp);
664
	    break;
665
666
	case T_DEFAULT:
667
	    if (type == T_SWITCH && level == 0)
668
		level = -1;
669
	    break;
670
	}
671
	(void) getword(NULL);
672
    } while (level >= 0);
673
}
674
675
static int
676
getword(Char *wp)
677
{
678
    int found = 0;
679
    int c, d;
680
    int     kwd = 0;
681
    Char   *owp = wp;
682
683
    c = readc(1);
684
    d = 0;
685
    do {
686
	while (c == ' ' || c == '\t')
687
	    c = readc(1);
688
	if (c == '#')
689
	    do
690
		c = readc(1);
691
	    while (c >= 0 && c != '\n');
692
	if (c < 0)
693
	    goto past;
694
	if (c == '\n') {
695
	    if (wp)
696
		break;
697
	    return (0);
698
	}
699
	unreadc(c);
700
	found = 1;
701
	do {
702
	    c = readc(1);
703
	    if (c == '\\' && (c = readc(1)) == '\n')
704
		c = ' ';
705
	    if (c == '\'' || c == '"') {
706
		if (d == 0)
707
		    d = c;
708
		else if (d == c)
709
		    d = 0;
710
	    }
711
	    if (c < 0)
712
		goto past;
713
	    if (wp) {
714
		*wp++ = c;
715
		*wp = 0;	/* end the string b4 test */
716
	    }
717
	} while ((d || (!(kwd = keyword(owp)) && c != ' '
718
		  && c != '\t')) && c != '\n');
719
    } while (wp == 0);
720
721
    /*
722
     * if we have read a keyword ( "if", "switch" or "while" ) then we do not
723
     * need to unreadc the look-ahead char
724
     */
725
    if (!kwd) {
726
	unreadc(c);
727
	if (found)
728
	    *--wp = 0;
729
    }
730
731
    return (found);
732
733
past:
734
    switch (Stype) {
735
736
    case T_IF:
737
	stderror(ERR_NAME | ERR_NOTFOUND, "then/endif");
738
739
    case T_ELSE:
740
	stderror(ERR_NAME | ERR_NOTFOUND, "endif");
741
742
    case T_BRKSW:
743
    case T_SWITCH:
744
	stderror(ERR_NAME | ERR_NOTFOUND, "endsw");
745
746
    case T_BREAK:
747
	stderror(ERR_NAME | ERR_NOTFOUND, "end");
748
749
    case T_GOTO:
750
	setname(vis_str(Sgoal));
751
	stderror(ERR_NAME | ERR_NOTFOUND, "label");
752
    }
753
    /* NOTREACHED */
754
    return (0);
755
}
756
757
/*
758
 * keyword(wp) determines if wp is one of the built-n functions if,
759
 * switch or while. It seems that when an if statement looks like
760
 * "if(" then getword above sucks in the '(' and so the search routine
761
 * never finds what it is scanning for. Rather than rewrite doword, I hack
762
 * in a test to see if the string forms a keyword. Then doword stops
763
 * and returns the word "if" -strike
764
 */
765
766
static int
767
keyword(Char *wp)
768
{
769
    static Char STRif[] = {'i', 'f', '\0'};
770
    static Char STRwhile[] = {'w', 'h', 'i', 'l', 'e', '\0'};
771
    static Char STRswitch[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'};
772
773
    if (!wp)
774
	return (0);
775
776
    if ((Strcmp(wp, STRif) == 0) || (Strcmp(wp, STRwhile) == 0)
777
	|| (Strcmp(wp, STRswitch) == 0))
778
	return (1);
779
780
    return (0);
781
}
782
783
static void
784
toend(void)
785
{
786
    if (whyles->w_end.type == F_SEEK && whyles->w_end.f_seek == 0) {
787
	search(T_BREAK, 0, NULL);
788
	btell(&whyles->w_end);
789
	whyles->w_end.f_seek--;
790
    }
791
    else
792
	bseek(&whyles->w_end);
793
    wfree();
794
}
795
796
void
797
wfree(void)
798
{
799
    struct Ain    o;
800
    struct whyle *nwp;
801
802
    btell(&o);
803
804
    for (; whyles; whyles = nwp) {
805
	struct whyle *wp = whyles;
806
	nwp = wp->w_next;
807
808
	/*
809
	 * We free loops that have different seek types.
810
	 */
811
	if (wp->w_end.type != I_SEEK && wp->w_start.type == wp->w_end.type &&
812
	    wp->w_start.type == o.type) {
813
	    if (wp->w_end.type == F_SEEK) {
814
		if (o.f_seek >= wp->w_start.f_seek &&
815
		    (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek))
816
		    break;
817
	    }
818
	    else {
819
		if (o.a_seek >= wp->w_start.a_seek &&
820
		    (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek))
821
		    break;
822
	    }
823
	}
824
825
	if (wp->w_fe0)
826
	    blkfree(wp->w_fe0);
827
	if (wp->w_fename)
828
	    free(wp->w_fename);
829
	free(wp);
830
    }
831
}
832
833
void
834
/*ARGSUSED*/
835
doecho(Char **v, struct command *t)
836
{
837
    xecho(' ', v);
838
}
839
840
void
841
/*ARGSUSED*/
842
doglob(Char **v, struct command *t)
843
{
844
    xecho(0, v);
845
    (void) fflush(cshout);
846
}
847
848
static void
849
xecho(int sep, Char **v)
850
{
851
    Char *cp;
852
    int     nonl = 0;
853
    sigset_t sigset;
854
855
    if (setintr) {
856
	sigemptyset(&sigset);
857
	sigaddset(&sigset, SIGINT);
858
	sigprocmask(SIG_UNBLOCK, &sigset, NULL);
859
    }
860
    v++;
861
    if (*v == 0)
862
	return;
863
    gflag = 0, tglob(v);
864
    if (gflag) {
865
	v = globall(v);
866
	if (v == 0)
867
	    stderror(ERR_NAME | ERR_NOMATCH);
868
    }
869
    else {
870
	v = gargv = saveblk(v);
871
	trim(v);
872
    }
873
    if (sep == ' ' && *v && eq(*v, STRmn))
874
	nonl++, v++;
875
    while ((cp = *v++) != NULL) {
876
	int c;
877
878
	while ((c = *cp++) != '\0')
879
	    (void) vis_fputc(c | QUOTE, cshout);
880
881
	if (*v)
882
	    (void) vis_fputc(sep | QUOTE, cshout);
883
    }
884
    if (sep && nonl == 0)
885
	(void) fputc('\n', cshout);
886
    else
887
	(void) fflush(cshout);
888
    if (setintr)
889
	sigprocmask(SIG_BLOCK, &sigset, NULL);
890
    if (gargv)
891
	blkfree(gargv), gargv = 0;
892
}
893
894
void
895
/*ARGSUSED*/
896
dosetenv(Char **v, struct command *t)
897
{
898
    Char   *vp, *lp;
899
    sigset_t sigset;
900
901
    v++;
902
    if ((vp = *v++) == 0) {
903
	Char **ep;
904
905
	if (setintr) {
906
	    sigemptyset(&sigset);
907
	    sigaddset(&sigset, SIGINT);
908
	    sigprocmask(SIG_UNBLOCK, &sigset, NULL);
909
	}
910
	for (ep = STR_environ; *ep; ep++)
911
	    (void) fprintf(cshout, "%s\n", vis_str(*ep));
912
	return;
913
    }
914
    if ((lp = *v++) == 0)
915
	lp = STRNULL;
916
    Setenv(vp, lp = globone(lp, G_APPEND));
917
    if (eq(vp, STRPATH)) {
918
	importpath(lp);
919
	dohash(NULL, NULL);
920
    }
921
    free(lp);
922
}
923
924
void
925
/*ARGSUSED*/
926
dounsetenv(Char **v, struct command *t)
927
{
928
    Char  **ep, *p, *n;
929
    int     i, maxi;
930
    static Char *name = NULL;
931
932
    if (name)
933
	free(name);
934
    /*
935
     * Find the longest environment variable
936
     */
937
    for (maxi = 0, ep = STR_environ; *ep; ep++) {
938
	for (i = 0, p = *ep; *p && *p != '='; p++, i++)
939
	    continue;
940
	if (i > maxi)
941
	    maxi = i;
942
    }
943
944
    name = xreallocarray(NULL, maxi + 1, sizeof(Char));
945
946
    while (++v && *v)
947
	for (maxi = 1; maxi;)
948
	    for (maxi = 0, ep = STR_environ; *ep; ep++) {
949
		for (n = name, p = *ep; *p && *p != '='; *n++ = *p++)
950
		    continue;
951
		*n = '\0';
952
		if (!Gmatch(name, *v))
953
		    continue;
954
		maxi = 1;
955
		/*
956
		 * Delete name, and start again cause the environment changes
957
		 */
958
		Unsetenv(name);
959
		break;
960
	    }
961
    free(name);
962
    name = NULL;
963
}
964
965
void
966
Setenv(Char *name, Char *val)
967
{
968
    Char **ep = STR_environ;
969
    Char *cp, *dp;
970
    Char   *blk[2];
971
    Char  **oep = ep;
972
973
    for (; *ep; ep++) {
974
	for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
975
	    continue;
976
	if (*cp != 0 || *dp != '=')
977
	    continue;
978
	cp = Strspl(STRequal, val);
979
	free(* ep);
980
	*ep = strip(Strspl(name, cp));
981
	free(cp);
982
	blkfree((Char **) environ);
983
	environ = short2blk(STR_environ);
984
	return;
985
    }
986
    cp = Strspl(name, STRequal);
987
    blk[0] = strip(Strspl(cp, val));
988
    free(cp);
989
    blk[1] = 0;
990
    STR_environ = blkspl(STR_environ, blk);
991
    blkfree((Char **) environ);
992
    environ = short2blk(STR_environ);
993
    free(oep);
994
}
995
996
static void
997
Unsetenv(Char *name)
998
{
999
    Char **ep = STR_environ;
1000
    Char *cp, *dp;
1001
    Char  **oep = ep;
1002
1003
    for (; *ep; ep++) {
1004
	for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
1005
	    continue;
1006
	if (*cp != 0 || *dp != '=')
1007
	    continue;
1008
	cp = *ep;
1009
	*ep = 0;
1010
	STR_environ = blkspl(STR_environ, ep + 1);
1011
	environ = short2blk(STR_environ);
1012
	*ep = cp;
1013
	free(cp);
1014
	free(oep);
1015
	return;
1016
    }
1017
}
1018
1019
void
1020
/*ARGSUSED*/
1021
doumask(Char **v, struct command *t)
1022
{
1023
    Char *cp = v[1];
1024
    int i;
1025
1026
    if (cp == 0) {
1027
	i = umask(0);
1028
	(void) umask(i);
1029
	(void) fprintf(cshout, "%o\n", i);
1030
	return;
1031
    }
1032
    i = 0;
1033
    while (Isdigit(*cp) && *cp != '8' && *cp != '9')
1034
	i = i * 8 + *cp++ - '0';
1035
    if (*cp || i < 0 || i > 0777)
1036
	stderror(ERR_NAME | ERR_MASK);
1037
    (void) umask(i);
1038
}
1039
1040
static struct limits {
1041
    int     limconst;
1042
    char   *limname;
1043
    int     limdiv;
1044
    char   *limscale;
1045
}       limits[] = {
1046
    { RLIMIT_CPU,	"cputime",	1,	"seconds" },
1047
    { RLIMIT_FSIZE,	"filesize",	1024,	"kbytes" },
1048
    { RLIMIT_DATA,	"datasize",	1024,	"kbytes" },
1049
    { RLIMIT_STACK,	"stacksize",	1024,	"kbytes" },
1050
    { RLIMIT_CORE,	"coredumpsize", 1024,	"kbytes" },
1051
    { RLIMIT_RSS,	"memoryuse",	1024,	"kbytes" },
1052
#ifdef RLIMIT_VMEM
1053
    { RLIMIT_VMEM,	"vmemoryuse",	1024,	"kbytes" },
1054
#endif
1055
    { RLIMIT_MEMLOCK,	"memorylocked",	1024,	"kbytes" },
1056
    { RLIMIT_NPROC,	"maxproc",	1,	"" },
1057
    { RLIMIT_NOFILE,	"openfiles",	1,	"" },
1058
    { -1,		NULL,		0,	NULL }
1059
};
1060
1061
static struct limits *findlim(Char *);
1062
static rlim_t getval(struct limits *, Char **);
1063
static void limtail(Char *, char *);
1064
static void plim(struct limits *, Char);
1065
static int setlim(struct limits *, Char, rlim_t);
1066
1067
static struct limits *
1068
findlim(Char *cp)
1069
{
1070
    struct limits *lp, *res;
1071
1072
    res = NULL;
1073
    for (lp = limits; lp->limconst >= 0; lp++)
1074
	if (prefix(cp, str2short(lp->limname))) {
1075
	    if (res)
1076
		stderror(ERR_NAME | ERR_AMBIG);
1077
	    res = lp;
1078
	}
1079
    if (res)
1080
	return (res);
1081
    stderror(ERR_NAME | ERR_LIMIT);
1082
    /* NOTREACHED */
1083
    return (0);
1084
}
1085
1086
void
1087
/*ARGSUSED*/
1088
dolimit(Char **v, struct command *t)
1089
{
1090
    struct limits *lp;
1091
    rlim_t limit;
1092
    char    hard = 0;
1093
1094
    v++;
1095
    if (*v && eq(*v, STRmh)) {
1096
	hard = 1;
1097
	v++;
1098
    }
1099
    if (*v == 0) {
1100
	for (lp = limits; lp->limconst >= 0; lp++)
1101
	    plim(lp, hard);
1102
	return;
1103
    }
1104
    lp = findlim(v[0]);
1105
    if (v[1] == 0) {
1106
	plim(lp, hard);
1107
	return;
1108
    }
1109
    limit = getval(lp, v + 1);
1110
    if (setlim(lp, hard, limit) < 0)
1111
	stderror(ERR_SILENT);
1112
}
1113
1114
static  rlim_t
1115
getval(struct limits *lp, Char **v)
1116
{
1117
    float f;
1118
    Char   *cp = *v++;
1119
1120
    f = atof(short2str(cp));
1121
1122
    while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E')
1123
	cp++;
1124
    if (*cp == 0) {
1125
	if (*v == 0)
1126
	    return ((rlim_t) ((f + 0.5) * lp->limdiv));
1127
	cp = *v;
1128
    }
1129
    switch (*cp) {
1130
    case ':':
1131
	if (lp->limconst != RLIMIT_CPU)
1132
	    goto badscal;
1133
	return ((rlim_t) (f * 60.0 + atof(short2str(cp + 1))));
1134
    case 'h':
1135
	if (lp->limconst != RLIMIT_CPU)
1136
	    goto badscal;
1137
	limtail(cp, "hours");
1138
	f *= 3600.0;
1139
	break;
1140
    case 'm':
1141
	if (lp->limconst == RLIMIT_CPU) {
1142
	    limtail(cp, "minutes");
1143
	    f *= 60.0;
1144
	    break;
1145
	}
1146
	*cp = 'm';
1147
	limtail(cp, "megabytes");
1148
	f *= 1024.0 * 1024.0;
1149
	break;
1150
    case 's':
1151
	if (lp->limconst != RLIMIT_CPU)
1152
	    goto badscal;
1153
	limtail(cp, "seconds");
1154
	break;
1155
    case 'M':
1156
	if (lp->limconst == RLIMIT_CPU)
1157
	    goto badscal;
1158
	*cp = 'm';
1159
	limtail(cp, "megabytes");
1160
	f *= 1024.0 * 1024.0;
1161
	break;
1162
    case 'k':
1163
	if (lp->limconst == RLIMIT_CPU)
1164
	    goto badscal;
1165
	limtail(cp, "kbytes");
1166
	f *= 1024.0;
1167
	break;
1168
    case 'u':
1169
	limtail(cp, "unlimited");
1170
	return (RLIM_INFINITY);
1171
    default:
1172
badscal:
1173
	stderror(ERR_NAME | ERR_SCALEF);
1174
    }
1175
    f += 0.5;
1176
    if (f > (float) RLIM_INFINITY)
1177
	return RLIM_INFINITY;
1178
    else
1179
	return ((rlim_t) f);
1180
}
1181
1182
static void
1183
limtail(Char *cp, char *str)
1184
{
1185
    char *origstr = str;
1186
1187
    while (*cp && *cp == *str)
1188
	cp++, str++;
1189
    if (*cp)
1190
	stderror(ERR_BADSCALE, origstr);
1191
}
1192
1193
/*ARGSUSED*/
1194
static void
1195
plim(struct limits *lp, Char hard)
1196
{
1197
    struct rlimit rlim;
1198
    rlim_t limit;
1199
1200
    (void) fprintf(cshout, "%s \t", lp->limname);
1201
1202
    (void) getrlimit(lp->limconst, &rlim);
1203
    limit = hard ? rlim.rlim_max : rlim.rlim_cur;
1204
1205
    if (limit == RLIM_INFINITY)
1206
	(void) fprintf(cshout, "unlimited");
1207
    else if (lp->limconst == RLIMIT_CPU)
1208
	psecs((long) limit);
1209
    else
1210
	(void) fprintf(cshout, "%llu %s",
1211
	    (unsigned long long) (limit / lp->limdiv), lp->limscale);
1212
    (void) fputc('\n', cshout);
1213
}
1214
1215
void
1216
/*ARGSUSED*/
1217
dounlimit(Char **v, struct command *t)
1218
{
1219
    struct limits *lp;
1220
    int     lerr = 0;
1221
    Char    hard = 0;
1222
1223
    v++;
1224
    if (*v && eq(*v, STRmh)) {
1225
	hard = 1;
1226
	v++;
1227
    }
1228
    if (*v == 0) {
1229
	for (lp = limits; lp->limconst >= 0; lp++)
1230
	    if (setlim(lp, hard, RLIM_INFINITY) < 0)
1231
		lerr++;
1232
	if (lerr)
1233
	    stderror(ERR_SILENT);
1234
	return;
1235
    }
1236
    while (*v) {
1237
	lp = findlim(*v++);
1238
	if (setlim(lp, hard, RLIM_INFINITY) < 0)
1239
	    stderror(ERR_SILENT);
1240
    }
1241
}
1242
1243
static int
1244
setlim(struct limits *lp, Char hard, rlim_t limit)
1245
{
1246
    struct rlimit rlim;
1247
1248
    (void) getrlimit(lp->limconst, &rlim);
1249
1250
    if (hard)
1251
	rlim.rlim_max = limit;
1252
    else if (limit == RLIM_INFINITY && geteuid() != 0)
1253
	rlim.rlim_cur = rlim.rlim_max;
1254
    else
1255
	rlim.rlim_cur = limit;
1256
1257
    if (setrlimit(lp->limconst, &rlim) < 0) {
1258
	(void) fprintf(csherr, "%s: %s: Can't %s%s limit\n", bname, lp->limname,
1259
		       limit == RLIM_INFINITY ? "remove" : "set",
1260
		       hard ? " hard" : "");
1261
	return (-1);
1262
    }
1263
    return (0);
1264
}
1265
1266
void
1267
/*ARGSUSED*/
1268
dosuspend(Char **v, struct command *t)
1269
{
1270
    int     ctpgrp;
1271
1272
    void    (*old) (int);
1273
1274
    if (loginsh)
1275
	stderror(ERR_SUSPLOG);
1276
    untty();
1277
1278
    old = signal(SIGTSTP, SIG_DFL);
1279
    (void) kill(0, SIGTSTP);
1280
    /* the shell stops here */
1281
    (void) signal(SIGTSTP, old);
1282
1283
    if (tpgrp != -1) {
1284
retry:
1285
	ctpgrp = tcgetpgrp(FSHTTY);
1286
      if  (ctpgrp != opgrp) {
1287
	    old = signal(SIGTTIN, SIG_DFL);
1288
	    (void) kill(0, SIGTTIN);
1289
	    (void) signal(SIGTTIN, old);
1290
	  goto retry;
1291
	}
1292
	(void) setpgid(0, shpgrp);
1293
	(void) tcsetpgrp(FSHTTY, shpgrp);
1294
    }
1295
}
1296
1297
/* This is the dreaded EVAL built-in.
1298
 *   If you don't fiddle with file descriptors, and reset didfds,
1299
 *   this command will either ignore redirection inside or outside
1300
 *   its arguments, e.g. eval "date >x"  vs.  eval "date" >x
1301
 *   The stuff here seems to work, but I did it by trial and error rather
1302
 *   than really knowing what was going on.  If tpgrp is zero, we are
1303
 *   probably a background eval, e.g. "eval date &", and we want to
1304
 *   make sure that any processes we start stay in our pgrp.
1305
 *   This is also the case for "time eval date" -- stay in same pgrp.
1306
 *   Otherwise, under stty tostop, processes will stop in the wrong
1307
 *   pgrp, with no way for the shell to get them going again.  -IAN!
1308
 */
1309
1310
static Char **gv = NULL;
1311
1312
void
1313
/*ARGSUSED*/
1314
doeval(Char **v, struct command *t)
1315
{
1316
    Char  **oevalvec;
1317
    Char   *oevalp;
1318
    int     odidfds;
1319
    jmp_buf osetexit;
1320
    int     my_reenter;
1321
    Char  **savegv = gv;
1322
    int     saveIN;
1323
    int     saveOUT;
1324
    int     saveERR;
1325
    int     oSHIN;
1326
    int     oSHOUT;
1327
    int     oSHERR;
1328
1329
    UNREGISTER(v);
1330
1331
    oevalvec = evalvec;
1332
    oevalp = evalp;
1333
    odidfds = didfds;
1334
    oSHIN = SHIN;
1335
    oSHOUT = SHOUT;
1336
    oSHERR = SHERR;
1337
1338
    v++;
1339
    if (*v == 0)
1340
	return;
1341
    gflag = 0, tglob(v);
1342
    if (gflag) {
1343
	gv = v = globall(v);
1344
	gargv = 0;
1345
	if (v == 0)
1346
	    stderror(ERR_NOMATCH);
1347
	v = copyblk(v);
1348
    }
1349
    else {
1350
	gv = NULL;
1351
	v = copyblk(v);
1352
	trim(v);
1353
    }
1354
1355
    saveIN = dcopy(SHIN, -1);
1356
    saveOUT = dcopy(SHOUT, -1);
1357
    saveERR = dcopy(SHERR, -1);
1358
1359
    getexit(osetexit);
1360
1361
    if ((my_reenter = setexit()) == 0) {
1362
	evalvec = v;
1363
	evalp = 0;
1364
	SHIN = dcopy(0, -1);
1365
	SHOUT = dcopy(1, -1);
1366
	SHERR = dcopy(2, -1);
1367
	didfds = 0;
1368
	process(0);
1369
    }
1370
1371
    evalvec = oevalvec;
1372
    evalp = oevalp;
1373
    doneinp = 0;
1374
    didfds = odidfds;
1375
    (void) close(SHIN);
1376
    (void) close(SHOUT);
1377
    (void) close(SHERR);
1378
    SHIN = dmove(saveIN, oSHIN);
1379
    SHOUT = dmove(saveOUT, oSHOUT);
1380
    SHERR = dmove(saveERR, oSHERR);
1381
    if (gv)
1382
	blkfree(gv), gv = NULL;
1383
    resexit(osetexit);
1384
    gv = savegv;
1385
    if (my_reenter)
1386
	stderror(ERR_SILENT);
1387
}