1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23 /*
24 * Copyright 1995 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31 #if defined(sun)
32 #pragma ident "@(#)args.c 1.11 05/09/14 SMI"
33 #endif
34
35 #include "defs.h"
36 #ifdef DO_SYSALIAS
37 #include "abbrev.h"
38 #endif
39 #include "version.h"
40
41 /*
42 * Copyright 2008-2021 J. Schilling
43 *
44 * @(#)args.c 1.96 21/02/27 2008-2021 J. Schilling
45 */
46 #ifndef lint
47 static UConst char sccsid[] =
48 "@(#)args.c 1.96 21/02/27 2008-2021 J. Schilling";
49 #endif
50
51 /*
52 * UNIX shell
53 */
54
55 #include "sh_policy.h"
56
57 #if !defined(DO_SET_O)
58 #undef DO_GLOBALALIASES
59 #undef DO_LOCALALIASES
60 #endif
61
62 void prversion __PR((void));
63 int options __PR((int argc, unsigned char **argv));
64 void setopts __PR((void));
65 void setargs __PR((unsigned char *argi[]));
66 static void freedolh __PR((void));
67 struct dolnod *freeargs __PR((struct dolnod *blk));
68 static struct dolnod *copyargs __PR((unsigned char *[], int));
69 static struct dolnod *clean_args __PR((struct dolnod *blk));
70 void clearup __PR((void));
71 struct dolnod *savargs __PR((int funcntp));
72 void restorargs __PR((struct dolnod *olddolh,
73 int funcntp));
74 struct dolnod *useargs __PR((void));
75 static unsigned char *lookcopt __PR((int wc));
76 #if defined(DO_SYSALIAS) && \
77 (defined(DO_GLOBALALIASES) || defined(DO_LOCALALIASES))
78 static void listaliasowner __PR((int parse, int flagidx));
79 #endif
80 #ifdef DO_SET_O
81 static void listopts __PR((int parse));
82 #ifdef DO_HOSTPROMPT
83 static void hostprompt __PR((int on));
84 #endif
85 #ifdef DO_PS34
86 static void ps_reset __PR((void));
87 #endif
88 #endif
89
90 static struct dolnod *dolh;
91
92 /* Used to save outermost positional parameters */
93 static struct dolnod *globdolh;
94 static unsigned char **globdolv;
95 static int globdolc;
96
97 unsigned char flagadr[20];
98
99 unsigned char flagchar[] =
100 {
101 #if defined(DO_SYSALIAS) && \
102 (defined(DO_GLOBALALIASES) || defined(DO_LOCALALIASES))
103 0, /* set -o aliasowner= */
104 #endif
105 'a', /* -a / -o allexport */
106 #ifdef DO_BGNICE
107 0, /* -o bgnice */
108 #endif
109 'e',
110 #ifdef DO_FDPIPE
111 0, /* set -o fdpipe */
112 #endif
113 #ifdef DO_FULLEXCODE
114 0, /* set -o fullexitcode */
115 #endif
116 #if defined(DO_SYSALIAS) && defined(DO_GLOBALALIASES)
117 0, /* set -o globalaliases */
118 #endif
119 #ifdef DO_GLOBSKIPDOT
120 0, /* set -o globskipdot */
121 #endif
122 'h',
123 #ifdef DO_HASHCMDS
124 0, /* -o hashcmds, enable # commands */
125 #endif
126 #ifdef DO_HOSTPROMPT
127 0, /* -o hostprompt, "<host> <user>> " prompt */
128 #endif
129 #ifdef INTERACTIVE
130 0, /* -o ignoreeof POSIX name */
131 #endif
132 'i',
133 'k', /* -k / -o keyword */
134 #if defined(DO_SYSALIAS) && defined(DO_LOCALALIASES)
135 0, /* set -o localaliases */
136 #endif
137 'm',
138 #ifdef DO_NOCLOBBER
139 'C', /* -C, set -o noclobber */
140 #endif
141 'n',
142 'f', /* -f / -o noglob */
143 #ifdef DO_NOTIFY
144 'b', /* -b / -o notify */
145 #endif
146 'u', /* -u / -o nounset */
147 't', /* -t / -o onecmd */
148 'P',
149 #ifdef DO_SET_O
150 0, /* -o posix */
151 #endif
152 'p',
153 #ifdef DO_PS34
154 0, /* -o promptcmdsubst */
155 #endif
156 'r',
157 STDFLG, /* -s / -o stdin */
158 'V',
159 #ifdef DO_TIME
160 0, /* set -o time */
161 #endif
162 #ifdef INTERACTIVE
163 0, /* set -o ved */
164 #endif
165 'v',
166 #ifdef INTERACTIVE
167 0, /* set -o vi */
168 #endif
169 'x',
170 0
171 };
172 #define NFLAGCHAR ((sizeof (flagchar) / sizeof (flagchar[0])) - 1)
173
174 #ifdef DO_SET_O
175 char *flagname[] =
176 {
177 #if defined(DO_SYSALIAS) && \
178 (defined(DO_GLOBALALIASES) || defined(DO_LOCALALIASES))
179 "aliasowner",
180 #endif
181 "allexport", /* -a POSIX */
182 #ifdef DO_BGNICE
183 "bgnice", /* -o bgnice */
184 #endif
185 "errexit", /* -e POSIX */
186 #ifdef DO_FDPIPE
187 "fdpipe", /* e.g. 2| for pipe from stderr */
188 #endif
189 #ifdef DO_FULLEXCODE
190 "fullexitcode", /* -o fullexitcode, do not mask $? */
191 #endif
192 #if defined(DO_SYSALIAS) && defined(DO_GLOBALALIASES)
193 "globalaliases",
194 #endif
195 #ifdef DO_GLOBSKIPDOT
196 "globskipdot",
197 #endif
198 "hashall", /* -h bash name (ksh93 uses "trackall") */
199 #ifdef DO_HASHCMDS
200 "hashcmds", /* -o hashcmds, enable # commands */
201 #endif
202 #ifdef DO_HOSTPROMPT
203 "hostprompt", /* -o hostprompt, "<host> <user>> " prompt */
204 #endif
205 #ifdef INTERACTIVE
206 "ignoreeof", /* -o ignoreeof POSIX name */
207 #endif
208 "interactive", /* -i ksh93 name */
209 "keyword", /* -k bash/ksh93 name */
210 #if defined(DO_SYSALIAS) && defined(DO_LOCALALIASES)
211 "localaliases",
212 #endif
213 "monitor", /* -m POSIX */
214 #ifdef DO_NOCLOBBER
215 "noclobber", /* -C, set -o noclobber */
216 #endif
217 "noexec", /* -n POSIX */
218 "noglob", /* -f POSIX */
219 #ifdef DO_NOTIFY
220 "notify", /* -b POSIX */
221 #endif
222 "nounset", /* -u POSIX */
223 "onecmd", /* -t bash name */
224 "pfsh", /* -P Schily Bourne Shell */
225 #ifdef DO_SET_O
226 "posix", /* -o posix */
227 #endif
228 "privileged", /* -p ksh93: only if really privileged */
229 #ifdef DO_PS34
230 "promptcmdsubst", /* -o promptcmdsubst */
231 #endif
232 "restricted", /* -r ksh93 name */
233 "stdin", /* -s Schily name */
234 "version", /* -V Schily Bourne Shell */
235 #ifdef DO_TIME
236 "time", /* -o time, enable timing */
237 #endif
238 #ifdef INTERACTIVE
239 "ved",
240 #endif
241 "verbose", /* -v POSIX */
242 #ifdef INTERACTIVE
243 "vi",
244 #endif
245 "xtrace", /* -x POSIX */
246 0
247 };
248 #endif
249
250 unsigned long flagval[] =
251 {
252 #if defined(DO_SYSALIAS) && \
253 (defined(DO_GLOBALALIASES) || defined(DO_LOCALALIASES))
254 fl2 | aliasownerflg, /* -o aliasowner= */
255 #endif
256 exportflg, /* -a / -o allexport */
257 #ifdef DO_BGNICE
258 fl2 | bgniceflg, /* -o bgnice */
259 #endif
260 errflg, /* -e */
261 #ifdef DO_FDPIPE
262 fl2 | fdpipeflg, /* -o fdpipe */
263 #endif
264 #ifdef DO_FULLEXCODE
265 fl2 | fullexitcodeflg, /* -o fullexitcode */
266 #endif
267 #if defined(DO_SYSALIAS) && defined(DO_GLOBALALIASES)
268 fl2 | globalaliasflg, /* -o globalaliases */
269 #endif
270 #ifdef DO_GLOBSKIPDOT
271 fl2 | globskipdot, /* -o globskipdot */
272 #endif
273 hashflg, /* -h / -o hashall */
274 #ifdef DO_HASHCMDS
275 fl2 | hashcmdsflg, /* -o hashcmds, enable # commands */
276 #endif
277 #ifdef DO_HOSTPROMPT
278 fl2 | hostpromptflg, /* -o hostprompt, "<host> <user>> " prompt */
279 #endif
280 #ifdef INTERACTIVE
281 fl2 | ignoreeofflg, /* -o ignoreeof POSIX name */
282 #endif
283 intflg, /* -i / -o interactive */
284 keyflg, /* -k / -o keyword */
285 #if defined(DO_SYSALIAS) && defined(DO_LOCALALIASES)
286 fl2 | localaliasflg, /* -o localaliases */
287 #endif
288 monitorflg, /* -m / -o monitor */
289 #ifdef DO_NOCLOBBER
290 fl2 | noclobberflg, /* -C, set -o noclobber */
291 #endif
292 noexec, /* -n / -o noexec */
293 nofngflg, /* -f / -o noglob */
294 #ifdef DO_NOTIFY
295 notifyflg, /* -b / -o notify */
296 #endif
297 setflg, /* -u / -o nounset */
298 oneflg, /* -t / -o onecmd */
299 pfshflg, /* -P */
300 #ifdef DO_SET_O
301 fl2 | posixflg, /* -o posix */
302 #endif
303 privflg, /* -p */
304 #ifdef DO_PS34
305 fl2 | promptcmdsubst, /* -o promptcmdsubst */
306 #endif
307 rshflg, /* -r / -o restrictive */
308 stdflg, /* -s / -o stdin */
309 fl2 | versflg, /* -V */
310 #ifdef DO_TIME
311 fl2 | timeflg, /* -o time */
312 #endif
313 #ifdef INTERACTIVE
314 fl2 | vedflg, /* -o ved */
315 #endif
316 readpr, /* -v / -o verbose */
317 #ifdef INTERACTIVE
318 fl2 | viflg, /* -o vi */
319 #endif
320 execpr, /* -x / -o xtrace */
321 0
322 };
323
324 unsigned char *shvers;
325
326 /* ======== option handling ======== */
327
328 #ifndef VSHNAME
329 #define VSHNAME "sh"
330 #endif
331
332 void
prversion()333 prversion()
334 {
335 char vbuf[BUFFERSIZE];
336
337 snprintf(vbuf, sizeof (vbuf),
338 "%s %s\n",
339 shname, shvers);
340 prs(UC vbuf);
341 if (dolv == NULL) {
342 /*
343 * We have been called as a result of a sh command line flag.
344 * Print the version information and exit.
345 */
346 prs(UC "\n");
347 prs(UC "Copyright (C) 1984-1989 AT&T\n");
348 prs(UC "Copyright (C) 1989-2009 Sun Microsystems\n");
349 #ifdef INTERACTIVE
350 prs(UC "Copyright (C) 1982-2021 Joerg Schilling\n");
351 #else
352 prs(UC "Copyright (C) 1985-2021 Joerg Schilling\n");
353 #endif
354 exitsh(0);
355 }
356 }
357
358 int
options(argc,argv)359 options(argc, argv)
360 int argc;
361 unsigned char **argv;
362 {
363 unsigned char *cp;
364 unsigned char **argp = argv;
365 unsigned char *flagc;
366 int len;
367 wchar_t wc;
368 unsigned long fv;
369
370 if (shvers == NULL) {
371 char vbuf[BUFFERSIZE];
372 size_t vlen;
373
374 vlen = snprintf(vbuf, sizeof (vbuf),
375 "version %s %s %s (%s-%s-%s)",
376 VSHNAME,
377 VERSION_DATE, VERSION_STR,
378 HOST_CPU, HOST_VENDOR, HOST_OS);
379 shvers = alloc(vlen + 1);
380 strcpy((char *)shvers, vbuf);
381 }
382
383 #ifdef DO_POSIX_SET
384 dashdash = 0;
385 #endif
386 #ifdef DO_MULTI_OPT
387 again:
388 #endif
389 if (argc > 1 && *argp[1] == '-') {
390 cp = argp[1];
391 /*
392 * Allow "--version" by mapping it to "-V".
393 */
394 if ((strcmp((char *)&cp[1], "version") == 0) ||
395 (cp[1] == '-' && strcmp((char *)&cp[2], "version") == 0)) {
396 cp = UC "-V";
397 } else if (cp[1] == '-' && cp[2] == '\0') {
398 /*
399 * if first argument is "--" then options are not
400 * to be changed. Fix for problems getting
401 * $1 starting with a "-"
402 */
403 argp[1] = argp[0];
404 argc--;
405 #ifdef DO_POSIX_SET
406 if (comdiv == cp) {
407 /*
408 * Support sh -c -- command
409 */
410 if ((comdiv = argp[2]) == NULL) {
411 failed(argv[1], mssgargn);
412 return (-1);
413 } else {
414 argp[2] = argp[3]?argp[3]:argp[0];
415 argc--;
416 }
417 }
418 dashdash++;
419 #endif
420 #ifdef DO_MULTI_OPT
421 setopts();
422 #endif
423 return (argc);
424 }
425 #ifdef DO_MULTI_OPT
426 /*
427 * Mark that we will later need to correct comdiv.
428 */
429 if (comdiv && dolv == NULL)
430 comdiv = UC -1;
431 #endif
432 if (cp[1] == '\0')
433 flags &= ~(execpr|readpr);
434
435 /*
436 * Step along 'flagchar[]' looking for matches.
437 * 'sicrp' are not legal with 'set' command.
438 */
439 (void) mbtowc(NULL, NULL, 0);
440 cp++;
441 while (*cp) {
442 if ((len = mbtowc(&wc, (char *)cp, MB_LEN_MAX)) <= 0) {
443 (void) mbtowc(NULL, NULL, 0);
444 len = 1;
445 wc = (unsigned char)*cp;
446 failed(argv[1], badopt);
447 return (-1);
448 }
449 cp += len;
450
451 #ifdef DO_SET_O
452 if (wc == 'o') { /* set set -o */
453 unsigned char *argarg;
454 int dolistopts = argc <= 2 ||
455 argp[2][0] == '-' ||
456 argp[2][0] == '+';
457
458 if (dolistopts) {
459 listopts(0);
460 continue;
461 }
462 argarg = UC strchr((char *)argp[2], '=');
463 if (argarg != NULL)
464 *argarg = '\0';
465 if ((flagc = lookopt(argp[2])) != NULL) {
466 argp[1] = argp[0];
467 argp++;
468 argc--;
469 wc = *flagc;
470 #if defined(DO_SYSALIAS) && \
471 (defined(DO_GLOBALALIASES) || defined(DO_LOCALALIASES))
472 /* LINTED */
473 if (flagval[flagc-flagchar] ==
474 (fl2 | aliasownerflg)) {
475 char *owner;
476
477 if (argarg != NULL)
478 owner = (char *)
479 &argarg[1];
480 else
481 owner = "";
482 ab_setaltowner(
483 GLOBAL_AB, owner);
484 ab_setaltowner(
485 LOCAL_AB, owner);
486 }
487 #endif
488 }
489 if (argarg != NULL)
490 *argarg = '=';
491 if (flagc == NULL || wc != *flagc) {
492 if (argc > 2) {
493 failed(argp[2], badopt);
494 return (-1);
495 }
496 continue;
497 }
498 } else { /* Not set -o, but: set -c */
499 #else /* !DO_SET_O */
500 {
501 #endif
502 flagc = lookcopt(wc);
503 }
504 if (wc == *flagc) {
505 if (eq(argv[0], "set") &&
506 wc && any(wc, UC "sicrp")) {
507 failed(argv[1], badopt);
508 return (-1);
509 } else {
510 unsigned long *fp = &flags;
511 #ifdef DO_PS34
512 unsigned long oflags;
513 #endif
514
515 /* LINTED */
516 fv = flagval[flagc-flagchar];
517 if (fv & fl2)
518 fp = &flags2;
519 #ifdef DO_PS34
520 oflags = *fp;
521 #endif
522 *fp |= fv & ~fl2;
523 /*
524 * Disallow to set -n on an interactive
525 * shell as this cannot be reset.
526 */
527 if (flags & intflg)
528 flags &= ~noexec;
529 #ifdef INTERACTIVE
530 flags2 &= ~viflg;
531 #endif
532 if (fv == errflg)
533 eflag = errflg;
534
535 #ifdef DO_MONITOR_SCRIPT
536 if (fv == monitorflg &&
537 (flags & jcflg) == 0) {
538 startjobs();
539 }
540 #endif
541
542 #ifdef EXECATTR_FILENAME /* from <exec_attr.h> */
543 if (fv == pfshflg)
544 secpolicy_init();
545 #endif
546 if (fv == (fl2 | versflg)) {
547 flags2 &= ~versflg;
548 prversion();
549 }
550 #if defined(DO_SYSALIAS) && defined(DO_GLOBALALIASES)
551 if (fv == (fl2 | globalaliasflg)) {
552 if (homenod.namval) {
553 catpath(homenod.namval,
554 UC globalname);
555 ab_use(GLOBAL_AB,
556 (char *)make(curstak()));
557 }
558 }
559 #endif
560 #if defined(DO_SYSALIAS) && defined(DO_LOCALALIASES)
561 if (fv == (fl2 | localaliasflg)) {
562 ab_use(LOCAL_AB,
563 (char *)localname);
564 }
565 #endif
566 #ifdef DO_HOSTPROMPT
567 if (fv == (fl2 | hostpromptflg))
568 hostprompt(TRUE);
569 #endif
570 #ifdef DO_PS34
571 if (fv == (fl2 | promptcmdsubst) &&
572 (oflags & promptcmdsubst) == 0)
573 ps_reset();
574 #endif
575 #ifdef DO_POSIX_EXPORT_ENV
576 if (fv == (fl2 | posixflg))
577 namscan(exportenv);
578 #endif
579 }
580 } else if (wc == 'c' && argc > 2 && comdiv == 0) {
581 comdiv = argp[2];
582 argp[1] = argp[0];
583 argp++;
584 argc--;
585 #ifdef DO_POSIX_SET
586 if (*argp[1] == '-' || /* Check for -- */
587 *argp[1] == '+') /* or more options */
588 goto again;
589 #endif
590 } else {
591 failed(argv[1], badopt);
592 return (-1);
593 }
594 }
595 argp[1] = argp[0];
596 argc--;
597 argp++;
598 } else if (argc > 1 &&
599 *argp[1] == '+') { /* unset flags x, k, t, n, v, e, u */
600 #ifdef DO_MULTI_OPT
601 /*
602 * Mark that we will later need to correct comdiv.
603 */
604 if (comdiv && dolv == NULL)
605 comdiv = UC -1;
606 #endif
607 (void) mbtowc(NULL, NULL, 0);
608 cp = argp[1];
609 cp++;
610 while (*cp) {
611 if ((len = mbtowc(&wc, (char *)cp, MB_LEN_MAX)) <= 0) {
612 (void) mbtowc(NULL, NULL, 0);
613 cp++;
614 continue;
615 }
616 cp += len;
617
618 #ifdef DO_SET_O
619 if (wc == 'o') { /* set +o */
620 int dolistopts = argc <= 2 ||
621 argp[2][0] == '-' ||
622 argp[2][0] == '+';
623
624 if (dolistopts) {
625 listopts(1);
626 continue;
627 }
628 if ((flagc = lookopt(argp[2])) != NULL) {
629 argp[1] = argp[0];
630 argp++;
631 argc--;
632 wc = *flagc;
633 }
634 if (flagc == NULL || wc != *flagc) {
635 if (argc > 2) {
636 failed(argp[2], badopt);
637 return (-1);
638 }
639 continue;
640 }
641 } else { /* Not set +o, but: set +c */
642 #else /* !DO_SET_O */
643 {
644 #endif
645 flagc = lookcopt(wc);
646 }
647 /*
648 * step through flags
649 */
650 if (wc == 0 ||
651 (!any(wc, UC "sicrp") && wc == *flagc)) {
652 unsigned long *fp = &flags;
653 /* LINTED */
654 fv = flagval[flagc-flagchar];
655 if (fv & fl2)
656 fp = &flags2;
657 *fp &= ~fv;
658 if (wc == 'e')
659 eflag = 0;
660 #ifdef EXECATTR_FILENAME
661 if (fv == pfshflg)
662 secpolicy_end();
663 #endif
664 #if defined(DO_SYSALIAS) && defined(DO_GLOBALALIASES)
665 if (fv == (fl2 | globalaliasflg)) {
666 ab_use(GLOBAL_AB, NULL);
667 }
668 #endif
669 #if defined(DO_SYSALIAS) && defined(DO_LOCALALIASES)
670 if (fv == (fl2 | localaliasflg)) {
671 ab_use(LOCAL_AB, NULL);
672 }
673 #endif
674 #if defined(DO_SYSALIAS) && \
675 (defined(DO_GLOBALALIASES) || defined(DO_LOCALALIASES))
676 if (fv == (fl2 | aliasownerflg)) {
677 ab_setaltowner(GLOBAL_AB, "");
678 ab_setaltowner(LOCAL_AB, "");
679 }
680 #endif
681 #ifdef DO_HOSTPROMPT
682 if (fv == (fl2 | hostpromptflg))
683 hostprompt(FALSE);
684 #endif
685 #ifdef DO_POSIX_EXPORT_ENV
686 if (fv == (fl2 | posixflg))
687 namscan(deexportenv);
688 #endif
689 } else {
690 failed(argv[1], badopt);
691 return (-1);
692 }
693 }
694 argp[1] = argp[0];
695 argc--;
696 argp++;
697 }
698 #ifdef DO_MULTI_OPT
699 if ((comdiv == NULL || dolv != NULL) &&
700 argc > 1 && (*argp[1] == '-' || *argp[1] == '+'))
701 goto again;
702
703 if (comdiv == UC -1 && dolv == NULL) {
704 /*
705 * Correct comdiv to point past last option.
706 */
707 if (argc > 1) {
708 comdiv = argp[1];
709 argp[1] = argp[0];
710 argv++;
711 argc--;
712 } else {
713 failed(argv[1], mssgargn);
714 return (-1);
715 }
716 }
717 #endif
718
719 setopts();
720 return (argc);
721 }
722
723 /*
724 * set up $-
725 * $- is only constructed from flag values in the basic "flags"
726 */
727 void
setopts()728 setopts()
729 {
730 unsigned char *flagc;
731 unsigned char *flagp;
732 unsigned long oflags = flags;
733
734 flagp = flagadr;
735 flags |= eflag;
736 if (flags) {
737 flagc = flagchar;
738 while (flagc < &flagchar[NFLAGCHAR]) {
739 if (*flagc && optval(flagc))
740 *flagp++ = *flagc;
741 flagc++;
742 }
743 }
744 *flagp = 0;
745 flags = oflags;
746 }
747
748 /*
749 * sets up positional parameters
750 */
751 void
setargs(argi)752 setargs(argi)
753 unsigned char *argi[];
754 {
755 unsigned char **argp = argi; /* count args */
756 int argn = 0;
757
758 while (*argp++ != UC ENDARGS)
759 argn++;
760 /*
761 * free old ones unless on for loop chain
762 */
763 freedolh();
764 dolh = copyargs(argi, argn);
765 dolc = argn - 1;
766 }
767
768
769 static void
freedolh()770 freedolh()
771 {
772 unsigned char **argp;
773 struct dolnod *argblk;
774
775 if ((argblk = dolh) != NULL) {
776 if ((--argblk->doluse) == 0) {
777 for (argp = argblk->dolarg; *argp != UC ENDARGS; argp++)
778 free(*argp);
779 free(argblk->dolarg);
780 free(argblk);
781 }
782 }
783 }
784
785 struct dolnod *
freeargs(blk)786 freeargs(blk)
787 struct dolnod *blk;
788 {
789 unsigned char **argp;
790 struct dolnod *argr = 0;
791 struct dolnod *argblk;
792 int cnt;
793
794 if ((argblk = blk) != NULL) {
795 argr = argblk->dolnxt;
796 cnt = --argblk->doluse;
797
798 if (argblk == dolh) {
799 if (cnt == 1)
800 return (argr);
801 else
802 return (argblk);
803 } else {
804 if (cnt == 0) {
805 for (argp = argblk->dolarg;
806 *argp != UC ENDARGS; argp++) {
807 free(*argp);
808 }
809 free(argblk->dolarg);
810 free(argblk);
811 }
812 }
813 }
814 return (argr);
815 }
816
817 static struct dolnod *
copyargs(from,n)818 copyargs(from, n)
819 unsigned char *from[];
820 int n;
821 {
822 struct dolnod *np = (struct dolnod *)alloc(sizeof (struct dolnod));
823 unsigned char **fp = from;
824 unsigned char **pp;
825
826 np -> dolnxt = 0;
827 np->doluse = 1; /* use count */
828 pp = np->dolarg = (unsigned char **)alloc((n+1)*sizeof (char *));
829 dolv = pp;
830
831 while (n--)
832 *pp++ = make(*fp++);
833 *pp++ = ENDARGS;
834 return (np);
835 }
836
837
838 static struct dolnod *
clean_args(blk)839 clean_args(blk)
840 struct dolnod *blk;
841 {
842 unsigned char **argp;
843 struct dolnod *argr = 0;
844 struct dolnod *argblk;
845
846 if ((argblk = blk) != NULL) {
847 argr = argblk->dolnxt;
848
849 if (argblk == dolh) {
850 argblk->doluse = 1;
851 } else {
852 for (argp = argblk->dolarg; *argp != UC ENDARGS; argp++)
853 free(*argp);
854 free(argblk->dolarg);
855 free(argblk);
856 }
857 }
858 return (argr);
859 }
860
861 void
clearup()862 clearup()
863 {
864 /*
865 * force `for' $* lists to go away
866 */
867 if (globdolv)
868 dolv = globdolv;
869 if (globdolc)
870 dolc = globdolc;
871 if (globdolh)
872 dolh = globdolh;
873 globdolv = 0;
874 globdolc = 0;
875 globdolh = 0;
876 while ((argfor = clean_args(argfor)) != NULL)
877 /* LINTED */
878 ;
879 /*
880 * clean up io files
881 */
882 while (pop())
883 /* LINTED */
884 ;
885
886 /*
887 * Clean up pipe file descriptor
888 * from command substitution
889 */
890
891 if (savpipe != -1) {
892 close(savpipe);
893 savpipe = -1;
894 }
895
896 /*
897 * clean up tmp files
898 */
899 while (poptemp())
900 /* LINTED */
901 ;
902 }
903
904 /*
905 * Save positiional parameters before outermost function invocation
906 * in case we are interrupted.
907 * Increment use count for current positional parameters so that they aren't
908 * thrown away.
909 */
910
911 struct dolnod *
savargs(funcntp)912 savargs(funcntp)
913 int funcntp;
914 {
915 if (!funcntp) {
916 globdolh = dolh;
917 globdolv = dolv;
918 globdolc = dolc;
919 }
920 useargs();
921 return (dolh);
922 }
923
924 /*
925 * After function invocation, free positional parameters,
926 * restore old positional parameters, and restore
927 * use count.
928 */
929
930 void
restorargs(olddolh,funcntp)931 restorargs(olddolh, funcntp)
932 struct dolnod *olddolh;
933 int funcntp;
934 {
935 if (argfor != olddolh)
936 while ((argfor = clean_args(argfor)) != olddolh && argfor)
937 /* LINTED */
938 ;
939 if (!argfor)
940 return;
941 freedolh();
942 dolh = olddolh;
943
944 /*
945 * increment use count so arguments aren't freed
946 */
947 if (dolh)
948 dolh -> doluse++;
949 argfor = freeargs(dolh);
950 if (funcntp == 1) {
951 globdolh = 0;
952 globdolv = 0;
953 globdolc = 0;
954 }
955 }
956
957 struct dolnod *
useargs()958 useargs()
959 {
960 if (dolh) {
961 if (dolh->doluse++ == 1) {
962 dolh->dolnxt = argfor;
963 argfor = dolh;
964 }
965 }
966 return (dolh);
967 }
968
969 static unsigned char *
lookcopt(wc)970 lookcopt(wc)
971 int wc;
972 {
973 unsigned char *flagc;
974
975 flagc = flagchar;
976 while (flagc < &flagchar[NFLAGCHAR]) {
977 if (*flagc && wc == *flagc)
978 break;
979 flagc++;
980 }
981 return (flagc);
982 }
983
984 int
optval(flagc)985 optval(flagc)
986 unsigned char *flagc;
987 {
988 unsigned long fv;
989 unsigned long *fp;
990
991 if (flagc == NULL)
992 return (0);
993
994 /* LINTED */
995 fv = flagval[flagc-flagchar];
996 fp = &flags;
997 if (fv & fl2) {
998 fp = &flags2;
999 fv &= ~fl2;
1000 }
1001 return (*fp & fv ? 1:0);
1002 }
1003
1004 #ifdef DO_SET_O
1005 unsigned char *
lookopt(name)1006 lookopt(name)
1007 unsigned char *name;
1008 {
1009 unsigned char *flagc;
1010
1011 for (flagc = flagchar;
1012 /* LINTED */
1013 flagname[flagc-flagchar]; flagc++) {
1014 /* LINTED */
1015 if (eq(name,
1016 flagname[flagc-flagchar])) {
1017 return (flagc);
1018 }
1019 }
1020 return (NULL);
1021 }
1022
1023 #if defined(DO_SYSALIAS) && \
1024 (defined(DO_GLOBALALIASES) || defined(DO_LOCALALIASES))
1025 static void
listaliasowner(parse,flagidx)1026 listaliasowner(parse, flagidx)
1027 int parse;
1028 int flagidx;
1029 {
1030 uid_t altuid = ab_getaltowner(GLOBAL_AB);
1031
1032 if (parse) {
1033 prs_buff(UC "set ");
1034 if (altuid == (uid_t)-1)
1035 prs_buff(UC "+o ");
1036 else
1037 prs_buff(UC "-o ");
1038 }
1039 prs_buff(UC flagname[flagidx]);
1040 if (altuid == (uid_t)-1 && parse) {
1041 prc_buff(NL);
1042 return;
1043 }
1044 prs_buff(UC "=");
1045 if (altuid != (uid_t)-1)
1046 prs_buff(UC ab_getaltoname(GLOBAL_AB));
1047 prc_buff(NL);
1048 }
1049 #endif
1050
1051 static void
listopts(parse)1052 listopts(parse)
1053 int parse;
1054 {
1055 unsigned char *flagc;
1056 int len;
1057 unsigned long fv;
1058
1059 /* LINTED */
1060 for (flagc = flagchar; flagname[flagc-flagchar]; flagc++) {
1061 if (*flagc == 'V')
1062 continue;
1063 /* LINTED */
1064 fv = flagval[flagc-flagchar];
1065 #if defined(DO_SYSALIAS) && \
1066 (defined(DO_GLOBALALIASES) || defined(DO_LOCALALIASES))
1067 if (fv == (fl2 | aliasownerflg)) {
1068 /* LINTED */
1069 listaliasowner(parse, flagc-flagchar);
1070 continue;
1071 }
1072 #endif
1073 fv = optval(flagc);
1074 if (parse) {
1075 if (any(*flagc, UC "sicrp")) /* Unsettable? */
1076 continue; /* so do not list */
1077 prs_buff(UC "set ");
1078 prs_buff(UC(fv ? "-":"+"));
1079 prs_buff(UC "o ");
1080 }
1081 /* LINTED */
1082 prs_buff(UC flagname[flagc-flagchar]);
1083 if (parse) {
1084 prc_buff(NL);
1085 continue;
1086 }
1087 /* LINTED */
1088 len = length(UC flagname[flagc-flagchar]);
1089 while (++len <= 16)
1090 prc_buff(SPACE);
1091 prc_buff(TAB);
1092 prs_buff(UC(fv ? "on":"off"));
1093 prc_buff(NL);
1094 }
1095 }
1096
1097 #ifdef DO_HOSTPROMPT
1098 #include <schily/utsname.h>
1099 #include <schily/pwd.h>
1100 static void
hostprompt(on)1101 hostprompt(on)
1102 int on;
1103 {
1104 #ifdef HAVE_UNAME
1105 struct utsname un;
1106 struct passwd *pw;
1107 unsigned char pr[1000];
1108 unsigned char *p;
1109 uid_t euid = geteuid();
1110
1111 if (on) {
1112 if (ps1nod.namval != NULL &&
1113 !eq(ps1nod.namval, (euid ? stdprompt : supprompt)))
1114 return;
1115 }
1116 uname(&un);
1117 pw = getpwuid(euid);
1118 if (pw == NULL)
1119 return;
1120 if ((length(UC un.nodename) + length(UC pw->pw_name) + 3) >
1121 sizeof (pr))
1122 return;
1123 p = movstr(UC un.nodename, pr);
1124 *p++ = ' ';
1125 p = movstr(UC pw->pw_name, p);
1126 *p++ = '>';
1127 *p++ = ' ';
1128 *p++ = '\0';
1129 if (!on) {
1130 if (ps1nod.namval != NULL &&
1131 !eq(ps1nod.namval, pr))
1132 return;
1133 }
1134 if (on)
1135 assign(&ps1nod, pr);
1136 else
1137 assign(&ps1nod, UC(euid ? stdprompt : supprompt));
1138 #endif
1139 }
1140 #endif /* DO_HOSTPROMPT */
1141
1142 #ifdef DO_PS34
1143 /*
1144 * Reset user specific prompts to their default values.
1145 */
1146 static void
ps_reset()1147 ps_reset()
1148 {
1149 assign(&ps1nod, UC(geteuid() ? stdprompt : supprompt));
1150 assign(&ps2nod, UC readmsg);
1151 #ifdef __needed_
1152 assign(&ps3nod, UC selectmsg);
1153 #endif
1154 assign(&ps4nod, UC execpmsg);
1155 #ifdef DO_HOSTPROMPT
1156 if (flags2 & hostpromptflg)
1157 hostprompt(TRUE);
1158 #endif
1159 }
1160 #endif /* DO_PS34 */
1161 #endif /* DO_SET_O */
1162