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