GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/csh/func.c Lines: 0 634 0.0 %
Date: 2016-12-06 Branches: 0 523 0.0 %

Line Branch Exec Source
1
/*    $OpenBSD: func.c,v 1.32 2015/12/26 13:48:38 mestre 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
	if (intty && fseekp == feobp && aret == F_SEEK)
593
	    (void) fprintf(cshout, "? "), (void) fflush(cshout);
594
	aword[0] = 0;
595
	(void) getword(aword);
596
	switch (srchx(aword)) {
597
598
	case T_ELSE:
599
	    if (level == 0 && type == T_IF)
600
		return;
601
	    break;
602
603
	case T_IF:
604
	    while (getword(aword))
605
		continue;
606
	    if ((type == T_IF || type == T_ELSE) &&
607
		eq(aword, STRthen))
608
		level++;
609
	    break;
610
611
	case T_ENDIF:
612
	    if (type == T_IF || type == T_ELSE)
613
		level--;
614
	    break;
615
616
	case T_FOREACH:
617
	case T_WHILE:
618
	    if (type == T_BREAK)
619
		level++;
620
	    break;
621
622
	case T_END:
623
	    if (type == T_BREAK)
624
		level--;
625
	    break;
626
627
	case T_SWITCH:
628
	    if (type == T_SWITCH || type == T_BRKSW)
629
		level++;
630
	    break;
631
632
	case T_ENDSW:
633
	    if (type == T_SWITCH || type == T_BRKSW)
634
		level--;
635
	    break;
636
637
	case T_LABEL:
638
	    if (type == T_GOTO && getword(aword) && eq(aword, goal))
639
		level = -1;
640
	    break;
641
642
	default:
643
	    if (type != T_GOTO && (type != T_SWITCH || level != 0))
644
		break;
645
	    if (lastchr(aword) != ':')
646
		break;
647
	    aword[Strlen(aword) - 1] = 0;
648
	    if ((type == T_GOTO && eq(aword, goal)) ||
649
		(type == T_SWITCH && eq(aword, STRdefault)))
650
		level = -1;
651
	    break;
652
653
	case T_CASE:
654
	    if (type != T_SWITCH || level != 0)
655
		break;
656
	    (void) getword(aword);
657
	    if (lastchr(aword) == ':')
658
		aword[Strlen(aword) - 1] = 0;
659
	    cp = strip(Dfix1(aword));
660
	    if (Gmatch(goal, cp))
661
		level = -1;
662
	    free(cp);
663
	    break;
664
665
	case T_DEFAULT:
666
	    if (type == T_SWITCH && level == 0)
667
		level = -1;
668
	    break;
669
	}
670
	(void) getword(NULL);
671
    } while (level >= 0);
672
}
673
674
static int
675
getword(Char *wp)
676
{
677
    int found = 0;
678
    int c, d;
679
    int     kwd = 0;
680
    Char   *owp = wp;
681
682
    c = readc(1);
683
    d = 0;
684
    do {
685
	while (c == ' ' || c == '\t')
686
	    c = readc(1);
687
	if (c == '#')
688
	    do
689
		c = readc(1);
690
	    while (c >= 0 && c != '\n');
691
	if (c < 0)
692
	    goto past;
693
	if (c == '\n') {
694
	    if (wp)
695
		break;
696
	    return (0);
697
	}
698
	unreadc(c);
699
	found = 1;
700
	do {
701
	    c = readc(1);
702
	    if (c == '\\' && (c = readc(1)) == '\n')
703
		c = ' ';
704
	    if (c == '\'' || c == '"') {
705
		if (d == 0)
706
		    d = c;
707
		else if (d == c)
708
		    d = 0;
709
	    }
710
	    if (c < 0)
711
		goto past;
712
	    if (wp) {
713
		*wp++ = c;
714
		*wp = 0;	/* end the string b4 test */
715
	    }
716
	} while ((d || (!(kwd = keyword(owp)) && c != ' '
717
		  && c != '\t')) && c != '\n');
718
    } while (wp == 0);
719
720
    /*
721
     * if we have read a keyword ( "if", "switch" or "while" ) then we do not
722
     * need to unreadc the look-ahead char
723
     */
724
    if (!kwd) {
725
	unreadc(c);
726
	if (found)
727
	    *--wp = 0;
728
    }
729
730
    return (found);
731
732
past:
733
    switch (Stype) {
734
735
    case T_IF:
736
	stderror(ERR_NAME | ERR_NOTFOUND, "then/endif");
737
738
    case T_ELSE:
739
	stderror(ERR_NAME | ERR_NOTFOUND, "endif");
740
741
    case T_BRKSW:
742
    case T_SWITCH:
743
	stderror(ERR_NAME | ERR_NOTFOUND, "endsw");
744
745
    case T_BREAK:
746
	stderror(ERR_NAME | ERR_NOTFOUND, "end");
747
748
    case T_GOTO:
749
	setname(vis_str(Sgoal));
750
	stderror(ERR_NAME | ERR_NOTFOUND, "label");
751
    }
752
    /* NOTREACHED */
753
    return (0);
754
}
755
756
/*
757
 * keyword(wp) determines if wp is one of the built-n functions if,
758
 * switch or while. It seems that when an if statement looks like
759
 * "if(" then getword above sucks in the '(' and so the search routine
760
 * never finds what it is scanning for. Rather than rewrite doword, I hack
761
 * in a test to see if the string forms a keyword. Then doword stops
762
 * and returns the word "if" -strike
763
 */
764
765
static int
766
keyword(Char *wp)
767
{
768
    static Char STRif[] = {'i', 'f', '\0'};
769
    static Char STRwhile[] = {'w', 'h', 'i', 'l', 'e', '\0'};
770
    static Char STRswitch[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'};
771
772
    if (!wp)
773
	return (0);
774
775
    if ((Strcmp(wp, STRif) == 0) || (Strcmp(wp, STRwhile) == 0)
776
	|| (Strcmp(wp, STRswitch) == 0))
777
	return (1);
778
779
    return (0);
780
}
781
782
static void
783
toend(void)
784
{
785
    if (whyles->w_end.type == F_SEEK && whyles->w_end.f_seek == 0) {
786
	search(T_BREAK, 0, NULL);
787
	btell(&whyles->w_end);
788
	whyles->w_end.f_seek--;
789
    }
790
    else
791
	bseek(&whyles->w_end);
792
    wfree();
793
}
794
795
void
796
wfree(void)
797
{
798
    struct Ain    o;
799
    struct whyle *nwp;
800
801
    btell(&o);
802
803
    for (; whyles; whyles = nwp) {
804
	struct whyle *wp = whyles;
805
	nwp = wp->w_next;
806
807
	/*
808
	 * We free loops that have different seek types.
809
	 */
810
	if (wp->w_end.type != I_SEEK && wp->w_start.type == wp->w_end.type &&
811
	    wp->w_start.type == o.type) {
812
	    if (wp->w_end.type == F_SEEK) {
813
		if (o.f_seek >= wp->w_start.f_seek &&
814
		    (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek))
815
		    break;
816
	    }
817
	    else {
818
		if (o.a_seek >= wp->w_start.a_seek &&
819
		    (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek))
820
		    break;
821
	    }
822
	}
823
824
	if (wp->w_fe0)
825
	    blkfree(wp->w_fe0);
826
	if (wp->w_fename)
827
	    free(wp->w_fename);
828
	free(wp);
829
    }
830
}
831
832
void
833
/*ARGSUSED*/
834
doecho(Char **v, struct command *t)
835
{
836
    xecho(' ', v);
837
}
838
839
void
840
/*ARGSUSED*/
841
doglob(Char **v, struct command *t)
842
{
843
    xecho(0, v);
844
    (void) fflush(cshout);
845
}
846
847
static void
848
xecho(int sep, Char **v)
849
{
850
    Char *cp;
851
    int     nonl = 0;
852
    sigset_t sigset;
853
854
    if (setintr) {
855
	sigemptyset(&sigset);
856
	sigaddset(&sigset, SIGINT);
857
	sigprocmask(SIG_UNBLOCK, &sigset, NULL);
858
    }
859
    v++;
860
    if (*v == 0)
861
	return;
862
    gflag = 0, tglob(v);
863
    if (gflag) {
864
	v = globall(v);
865
	if (v == 0)
866
	    stderror(ERR_NAME | ERR_NOMATCH);
867
    }
868
    else {
869
	v = gargv = saveblk(v);
870
	trim(v);
871
    }
872
    if (sep == ' ' && *v && eq(*v, STRmn))
873
	nonl++, v++;
874
    while ((cp = *v++) != NULL) {
875
	int c;
876
877
	while ((c = *cp++) != '\0')
878
	    (void) vis_fputc(c | QUOTE, cshout);
879
880
	if (*v)
881
	    (void) vis_fputc(sep | QUOTE, cshout);
882
    }
883
    if (sep && nonl == 0)
884
	(void) fputc('\n', cshout);
885
    else
886
	(void) fflush(cshout);
887
    if (setintr)
888
	sigprocmask(SIG_BLOCK, &sigset, NULL);
889
    if (gargv)
890
	blkfree(gargv), gargv = 0;
891
}
892
893
void
894
/*ARGSUSED*/
895
dosetenv(Char **v, struct command *t)
896
{
897
    Char   *vp, *lp;
898
    sigset_t sigset;
899
900
    v++;
901
    if ((vp = *v++) == 0) {
902
	Char **ep;
903
904
	if (setintr) {
905
	    sigemptyset(&sigset);
906
	    sigaddset(&sigset, SIGINT);
907
	    sigprocmask(SIG_UNBLOCK, &sigset, NULL);
908
	}
909
	for (ep = STR_environ; *ep; ep++)
910
	    (void) fprintf(cshout, "%s\n", vis_str(*ep));
911
	return;
912
    }
913
    if ((lp = *v++) == 0)
914
	lp = STRNULL;
915
    Setenv(vp, lp = globone(lp, G_APPEND));
916
    if (eq(vp, STRPATH)) {
917
	importpath(lp);
918
	dohash(NULL, NULL);
919
    }
920
    free(lp);
921
}
922
923
void
924
/*ARGSUSED*/
925
dounsetenv(Char **v, struct command *t)
926
{
927
    Char  **ep, *p, *n;
928
    int     i, maxi;
929
    static Char *name = NULL;
930
931
    if (name)
932
	free(name);
933
    /*
934
     * Find the longest environment variable
935
     */
936
    for (maxi = 0, ep = STR_environ; *ep; ep++) {
937
	for (i = 0, p = *ep; *p && *p != '='; p++, i++)
938
	    continue;
939
	if (i > maxi)
940
	    maxi = i;
941
    }
942
943
    name = xreallocarray(NULL, maxi + 1, sizeof(Char));
944
945
    while (++v && *v)
946
	for (maxi = 1; maxi;)
947
	    for (maxi = 0, ep = STR_environ; *ep; ep++) {
948
		for (n = name, p = *ep; *p && *p != '='; *n++ = *p++)
949
		    continue;
950
		*n = '\0';
951
		if (!Gmatch(name, *v))
952
		    continue;
953
		maxi = 1;
954
		/*
955
		 * Delete name, and start again cause the environment changes
956
		 */
957
		Unsetenv(name);
958
		break;
959
	    }
960
    free(name);
961
    name = NULL;
962
}
963
964
void
965
Setenv(Char *name, Char *val)
966
{
967
    Char **ep = STR_environ;
968
    Char *cp, *dp;
969
    Char   *blk[2];
970
    Char  **oep = ep;
971
972
    for (; *ep; ep++) {
973
	for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
974
	    continue;
975
	if (*cp != 0 || *dp != '=')
976
	    continue;
977
	cp = Strspl(STRequal, val);
978
	free(* ep);
979
	*ep = strip(Strspl(name, cp));
980
	free(cp);
981
	blkfree((Char **) environ);
982
	environ = short2blk(STR_environ);
983
	return;
984
    }
985
    cp = Strspl(name, STRequal);
986
    blk[0] = strip(Strspl(cp, val));
987
    free(cp);
988
    blk[1] = 0;
989
    STR_environ = blkspl(STR_environ, blk);
990
    blkfree((Char **) environ);
991
    environ = short2blk(STR_environ);
992
    free(oep);
993
}
994
995
static void
996
Unsetenv(Char *name)
997
{
998
    Char **ep = STR_environ;
999
    Char *cp, *dp;
1000
    Char  **oep = ep;
1001
1002
    for (; *ep; ep++) {
1003
	for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
1004
	    continue;
1005
	if (*cp != 0 || *dp != '=')
1006
	    continue;
1007
	cp = *ep;
1008
	*ep = 0;
1009
	STR_environ = blkspl(STR_environ, ep + 1);
1010
	environ = short2blk(STR_environ);
1011
	*ep = cp;
1012
	free(cp);
1013
	free(oep);
1014
	return;
1015
    }
1016
}
1017
1018
void
1019
/*ARGSUSED*/
1020
doumask(Char **v, struct command *t)
1021
{
1022
    Char *cp = v[1];
1023
    int i;
1024
1025
    if (cp == 0) {
1026
	i = umask(0);
1027
	(void) umask(i);
1028
	(void) fprintf(cshout, "%o\n", i);
1029
	return;
1030
    }
1031
    i = 0;
1032
    while (Isdigit(*cp) && *cp != '8' && *cp != '9')
1033
	i = i * 8 + *cp++ - '0';
1034
    if (*cp || i < 0 || i > 0777)
1035
	stderror(ERR_NAME | ERR_MASK);
1036
    (void) umask(i);
1037
}
1038
1039
typedef quad_t RLIM_TYPE;
1040
1041
static struct limits {
1042
    int     limconst;
1043
    char   *limname;
1044
    int     limdiv;
1045
    char   *limscale;
1046
}       limits[] = {
1047
    { RLIMIT_CPU,	"cputime",	1,	"seconds" },
1048
    { RLIMIT_FSIZE,	"filesize",	1024,	"kbytes" },
1049
    { RLIMIT_DATA,	"datasize",	1024,	"kbytes" },
1050
    { RLIMIT_STACK,	"stacksize",	1024,	"kbytes" },
1051
    { RLIMIT_CORE,	"coredumpsize", 1024,	"kbytes" },
1052
    { RLIMIT_RSS,	"memoryuse",	1024,	"kbytes" },
1053
#ifdef RLIMIT_VMEM
1054
    { RLIMIT_VMEM,	"vmemoryuse",	1024,	"kbytes" },
1055
#endif
1056
    { RLIMIT_MEMLOCK,	"memorylocked",	1024,	"kbytes" },
1057
    { RLIMIT_NPROC,	"maxproc",	1,	"" },
1058
    { RLIMIT_NOFILE,	"openfiles",	1,	"" },
1059
    { -1,		NULL,		0,	NULL }
1060
};
1061
1062
static struct limits *findlim(Char *);
1063
static RLIM_TYPE getval(struct limits *, Char **);
1064
static void limtail(Char *, char *);
1065
static void plim(struct limits *, Char);
1066
static int setlim(struct limits *, Char, RLIM_TYPE);
1067
1068
static struct limits *
1069
findlim(Char *cp)
1070
{
1071
    struct limits *lp, *res;
1072
1073
    res = NULL;
1074
    for (lp = limits; lp->limconst >= 0; lp++)
1075
	if (prefix(cp, str2short(lp->limname))) {
1076
	    if (res)
1077
		stderror(ERR_NAME | ERR_AMBIG);
1078
	    res = lp;
1079
	}
1080
    if (res)
1081
	return (res);
1082
    stderror(ERR_NAME | ERR_LIMIT);
1083
    /* NOTREACHED */
1084
    return (0);
1085
}
1086
1087
void
1088
/*ARGSUSED*/
1089
dolimit(Char **v, struct command *t)
1090
{
1091
    struct limits *lp;
1092
    RLIM_TYPE limit;
1093
    char    hard = 0;
1094
1095
    v++;
1096
    if (*v && eq(*v, STRmh)) {
1097
	hard = 1;
1098
	v++;
1099
    }
1100
    if (*v == 0) {
1101
	for (lp = limits; lp->limconst >= 0; lp++)
1102
	    plim(lp, hard);
1103
	return;
1104
    }
1105
    lp = findlim(v[0]);
1106
    if (v[1] == 0) {
1107
	plim(lp, hard);
1108
	return;
1109
    }
1110
    limit = getval(lp, v + 1);
1111
    if (setlim(lp, hard, limit) < 0)
1112
	stderror(ERR_SILENT);
1113
}
1114
1115
static  RLIM_TYPE
1116
getval(struct limits *lp, Char **v)
1117
{
1118
    float f;
1119
    Char   *cp = *v++;
1120
1121
    f = atof(short2str(cp));
1122
1123
    while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E')
1124
	cp++;
1125
    if (*cp == 0) {
1126
	if (*v == 0)
1127
	    return ((RLIM_TYPE) ((f + 0.5) * lp->limdiv));
1128
	cp = *v;
1129
    }
1130
    switch (*cp) {
1131
    case ':':
1132
	if (lp->limconst != RLIMIT_CPU)
1133
	    goto badscal;
1134
	return ((RLIM_TYPE) (f * 60.0 + atof(short2str(cp + 1))));
1135
    case 'h':
1136
	if (lp->limconst != RLIMIT_CPU)
1137
	    goto badscal;
1138
	limtail(cp, "hours");
1139
	f *= 3600.0;
1140
	break;
1141
    case 'm':
1142
	if (lp->limconst == RLIMIT_CPU) {
1143
	    limtail(cp, "minutes");
1144
	    f *= 60.0;
1145
	    break;
1146
	}
1147
	*cp = 'm';
1148
	limtail(cp, "megabytes");
1149
	f *= 1024.0 * 1024.0;
1150
	break;
1151
    case 's':
1152
	if (lp->limconst != RLIMIT_CPU)
1153
	    goto badscal;
1154
	limtail(cp, "seconds");
1155
	break;
1156
    case 'M':
1157
	if (lp->limconst == RLIMIT_CPU)
1158
	    goto badscal;
1159
	*cp = 'm';
1160
	limtail(cp, "megabytes");
1161
	f *= 1024.0 * 1024.0;
1162
	break;
1163
    case 'k':
1164
	if (lp->limconst == RLIMIT_CPU)
1165
	    goto badscal;
1166
	limtail(cp, "kbytes");
1167
	f *= 1024.0;
1168
	break;
1169
    case 'u':
1170
	limtail(cp, "unlimited");
1171
	return (RLIM_INFINITY);
1172
    default:
1173
badscal:
1174
	stderror(ERR_NAME | ERR_SCALEF);
1175
    }
1176
    f += 0.5;
1177
    if (f > (float) RLIM_INFINITY)
1178
	return RLIM_INFINITY;
1179
    else
1180
	return ((RLIM_TYPE) f);
1181
}
1182
1183
static void
1184
limtail(Char *cp, char *str)
1185
{
1186
    char *origstr = str;
1187
1188
    while (*cp && *cp == *str)
1189
	cp++, str++;
1190
    if (*cp)
1191
	stderror(ERR_BADSCALE, origstr);
1192
}
1193
1194
/*ARGSUSED*/
1195
static void
1196
plim(struct limits *lp, Char hard)
1197
{
1198
    struct rlimit rlim;
1199
    RLIM_TYPE limit;
1200
1201
    (void) fprintf(cshout, "%s \t", lp->limname);
1202
1203
    (void) getrlimit(lp->limconst, &rlim);
1204
    limit = hard ? rlim.rlim_max : rlim.rlim_cur;
1205
1206
    if (limit == RLIM_INFINITY)
1207
	(void) fprintf(cshout, "unlimited");
1208
    else if (lp->limconst == RLIMIT_CPU)
1209
	psecs((long) limit);
1210
    else
1211
	(void) fprintf(cshout, "%ld %s", (long) (limit / lp->limdiv),
1212
		       lp->limscale);
1213
    (void) fputc('\n', cshout);
1214
}
1215
1216
void
1217
/*ARGSUSED*/
1218
dounlimit(Char **v, struct command *t)
1219
{
1220
    struct limits *lp;
1221
    int     lerr = 0;
1222
    Char    hard = 0;
1223
1224
    v++;
1225
    if (*v && eq(*v, STRmh)) {
1226
	hard = 1;
1227
	v++;
1228
    }
1229
    if (*v == 0) {
1230
	for (lp = limits; lp->limconst >= 0; lp++)
1231
	    if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0)
1232
		lerr++;
1233
	if (lerr)
1234
	    stderror(ERR_SILENT);
1235
	return;
1236
    }
1237
    while (*v) {
1238
	lp = findlim(*v++);
1239
	if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0)
1240
	    stderror(ERR_SILENT);
1241
    }
1242
}
1243
1244
static int
1245
setlim(struct limits *lp, Char hard, RLIM_TYPE limit)
1246
{
1247
    struct rlimit rlim;
1248
1249
    (void) getrlimit(lp->limconst, &rlim);
1250
1251
    if (hard)
1252
	rlim.rlim_max = limit;
1253
    else if (limit == RLIM_INFINITY && geteuid() != 0)
1254
	rlim.rlim_cur = rlim.rlim_max;
1255
    else
1256
	rlim.rlim_cur = limit;
1257
1258
    if (setrlimit(lp->limconst, &rlim) < 0) {
1259
	(void) fprintf(csherr, "%s: %s: Can't %s%s limit\n", bname, lp->limname,
1260
		       limit == RLIM_INFINITY ? "remove" : "set",
1261
		       hard ? " hard" : "");
1262
	return (-1);
1263
    }
1264
    return (0);
1265
}
1266
1267
void
1268
/*ARGSUSED*/
1269
dosuspend(Char **v, struct command *t)
1270
{
1271
    int     ctpgrp;
1272
1273
    void    (*old) (int);
1274
1275
    if (loginsh)
1276
	stderror(ERR_SUSPLOG);
1277
    untty();
1278
1279
    old = signal(SIGTSTP, SIG_DFL);
1280
    (void) kill(0, SIGTSTP);
1281
    /* the shell stops here */
1282
    (void) signal(SIGTSTP, old);
1283
1284
    if (tpgrp != -1) {
1285
retry:
1286
	ctpgrp = tcgetpgrp(FSHTTY);
1287
      if  (ctpgrp != opgrp) {
1288
	    old = signal(SIGTTIN, SIG_DFL);
1289
	    (void) kill(0, SIGTTIN);
1290
	    (void) signal(SIGTTIN, old);
1291
	  goto retry;
1292
	}
1293
	(void) setpgid(0, shpgrp);
1294
	(void) tcsetpgrp(FSHTTY, shpgrp);
1295
    }
1296
}
1297
1298
/* This is the dreaded EVAL built-in.
1299
 *   If you don't fiddle with file descriptors, and reset didfds,
1300
 *   this command will either ignore redirection inside or outside
1301
 *   its arguments, e.g. eval "date >x"  vs.  eval "date" >x
1302
 *   The stuff here seems to work, but I did it by trial and error rather
1303
 *   than really knowing what was going on.  If tpgrp is zero, we are
1304
 *   probably a background eval, e.g. "eval date &", and we want to
1305
 *   make sure that any processes we start stay in our pgrp.
1306
 *   This is also the case for "time eval date" -- stay in same pgrp.
1307
 *   Otherwise, under stty tostop, processes will stop in the wrong
1308
 *   pgrp, with no way for the shell to get them going again.  -IAN!
1309
 */
1310
1311
static Char **gv = NULL;
1312
1313
void
1314
/*ARGSUSED*/
1315
doeval(Char **v, struct command *t)
1316
{
1317
    Char  **oevalvec;
1318
    Char   *oevalp;
1319
    int     odidfds;
1320
    jmp_buf osetexit;
1321
    int     my_reenter;
1322
    Char  **savegv = gv;
1323
    int     saveIN;
1324
    int     saveOUT;
1325
    int     saveERR;
1326
    int     oSHIN;
1327
    int     oSHOUT;
1328
    int     oSHERR;
1329
1330
    UNREGISTER(v);
1331
1332
    oevalvec = evalvec;
1333
    oevalp = evalp;
1334
    odidfds = didfds;
1335
    oSHIN = SHIN;
1336
    oSHOUT = SHOUT;
1337
    oSHERR = SHERR;
1338
1339
    v++;
1340
    if (*v == 0)
1341
	return;
1342
    gflag = 0, tglob(v);
1343
    if (gflag) {
1344
	gv = v = globall(v);
1345
	gargv = 0;
1346
	if (v == 0)
1347
	    stderror(ERR_NOMATCH);
1348
	v = copyblk(v);
1349
    }
1350
    else {
1351
	gv = NULL;
1352
	v = copyblk(v);
1353
	trim(v);
1354
    }
1355
1356
    saveIN = dcopy(SHIN, -1);
1357
    saveOUT = dcopy(SHOUT, -1);
1358
    saveERR = dcopy(SHERR, -1);
1359
1360
    getexit(osetexit);
1361
1362
    if ((my_reenter = setexit()) == 0) {
1363
	evalvec = v;
1364
	evalp = 0;
1365
	SHIN = dcopy(0, -1);
1366
	SHOUT = dcopy(1, -1);
1367
	SHERR = dcopy(2, -1);
1368
	didfds = 0;
1369
	process(0);
1370
    }
1371
1372
    evalvec = oevalvec;
1373
    evalp = oevalp;
1374
    doneinp = 0;
1375
    didfds = odidfds;
1376
    (void) close(SHIN);
1377
    (void) close(SHOUT);
1378
    (void) close(SHERR);
1379
    SHIN = dmove(saveIN, oSHIN);
1380
    SHOUT = dmove(saveOUT, oSHOUT);
1381
    SHERR = dmove(saveERR, oSHERR);
1382
    if (gv)
1383
	blkfree(gv), gv = NULL;
1384
    resexit(osetexit);
1385
    gv = savegv;
1386
    if (my_reenter)
1387
	stderror(ERR_SILENT);
1388
}