1 /* $OpenBSD: c_ksh.c,v 1.33 2009/02/07 14:03:24 kili Exp $ */
4 * built-in Korn commands: c_*
16 int physical
= Flag(FPHYSICAL
);
17 int cdnode
; /* was a node from cdpath added in? */
18 int printpath
= 0; /* print where we cd'd? */
20 struct tbl
*pwd_s
, *oldpwd_s
;
23 char *dir
, *try, *pwd
;
28 while ((optc
= ksh_getopt(wp
, &builtin_opt
, "LP")) != -1)
39 wp
+= builtin_opt
.optind
;
41 if (Flag(FRESTRICTED
)) {
42 bi_errorf("restricted shell - can't cd");
46 pwd_s
= global("PWD");
47 oldpwd_s
= global("OLDPWD");
50 /* No arguments - go home */
51 if ((dir
= str_val(global("HOME"))) == null
) {
52 bi_errorf("no home directory (HOME not set)");
56 /* One argument: - or dir */
58 if (strcmp(dir
, "-") == 0) {
59 dir
= str_val(oldpwd_s
);
61 bi_errorf("no OLDPWD");
67 /* Two arguments - substitute arg1 in PWD for arg2 */
68 int ilen
, olen
, nlen
, elen
;
72 bi_errorf("don't know current directory");
75 /* substitute arg1 for arg2 in current path.
76 * if the first substitution fails because the cd fails
77 * we could try to find another substitution. For now
80 if ((cp
= strstr(current_wd
, wp
[0])) == (char *) 0) {
81 bi_errorf("bad substitution");
84 ilen
= cp
- current_wd
;
87 elen
= strlen(current_wd
+ ilen
+ olen
) + 1;
88 fdir
= dir
= alloc(ilen
+ nlen
+ elen
, ATEMP
);
89 memcpy(dir
, current_wd
, ilen
);
90 memcpy(dir
+ ilen
, wp
[1], nlen
);
91 memcpy(dir
+ ilen
+ nlen
, current_wd
+ ilen
+ olen
, elen
);
94 bi_errorf("too many arguments");
98 Xinit(xs
, xp
, PATH
, ATEMP
);
99 /* xp will have a bogus value after make_path() - set it to 0
100 * so that if it's used, it will cause a dump
104 cdpath
= str_val(global("CDPATH"));
106 cdnode
= make_path(current_wd
, dir
, &cdpath
, &xs
, &phys_path
);
108 rval
= chdir(try = Xstring(xs
, xp
) + phys_path
);
110 simplify_path(Xstring(xs
, xp
));
111 rval
= chdir(try = Xstring(xs
, xp
));
113 } while (rval
< 0 && cdpath
!= (char *) 0);
117 bi_errorf("%s: bad directory", dir
);
119 bi_errorf("%s - %s", try, strerror(errno
));
125 /* Clear out tracked aliases with relative paths */
128 /* Set OLDPWD (note: unsetting OLDPWD does not disable this
129 * setting in at&t ksh)
132 /* Ignore failure (happens if readonly or integer) */
133 setstr(oldpwd_s
, current_wd
, KSH_RETURN_ERROR
);
135 if (Xstring(xs
, xp
)[0] != '/') {
138 if (!physical
|| !(pwd
= get_phys_path(Xstring(xs
, xp
))))
139 pwd
= Xstring(xs
, xp
);
144 set_current_wd(ptmp
);
145 /* Ignore failure (happens if readonly or integer) */
146 setstr(pwd_s
, ptmp
, KSH_RETURN_ERROR
);
148 set_current_wd(null
);
149 pwd
= Xstring(xs
, xp
);
150 /* XXX unset $PWD? */
152 if (printpath
|| cdnode
)
153 shprintf("%s\n", pwd
);
165 int physical
= Flag(FPHYSICAL
);
166 char *p
, *freep
= NULL
;
168 while ((optc
= ksh_getopt(wp
, &builtin_opt
, "LP")) != -1)
179 wp
+= builtin_opt
.optind
;
182 bi_errorf("too many arguments");
185 p
= current_wd
[0] ? (physical
? get_phys_path(current_wd
) : current_wd
) :
187 if (p
&& access(p
, R_OK
) < 0)
190 freep
= p
= ksh_get_wd((char *) 0, 0);
192 bi_errorf("can't get current directory - %s",
206 #define PO_NL BIT(0) /* print newline */
207 #define PO_EXPAND BIT(1) /* expand backslash sequences */
208 #define PO_PMINUSMINUS BIT(2) /* print a -- argument */
209 #define PO_HIST BIT(3) /* print to history instead of stdout */
210 #define PO_COPROC BIT(4) /* printing to coprocess: block SIGPIPE */
212 int flags
= PO_EXPAND
|PO_NL
;
218 if (wp
[0][0] == 'e') { /* echo command */
221 /* A compromise between sysV and BSD echo commands:
222 * escape sequences are enabled by default, and
223 * -n, -e and -E are recognized if they appear
224 * in arguments with no illegal options (ie, echo -nq
226 * Different from sysV echo since options are recognized,
227 * different from BSD echo since escape sequences are enabled
232 if (*wp
&& strcmp(*wp
, "-n") == 0) {
237 while ((s
= *wp
) && *s
== '-' && s
[1]) {
244 nflags
&= ~PO_EXPAND
;
246 /* bad option: don't use
247 * nflags, print argument
258 const char *options
= "Rnprsu,";
259 while ((optc
= ksh_getopt(wp
, &builtin_opt
, options
)) != -1)
261 case 'R': /* fake BSD echo command */
262 flags
|= PO_PMINUSMINUS
;
273 if ((fd
= coproc_getfd(W_OK
, &emsg
)) < 0) {
274 bi_errorf("-p: %s", emsg
);
285 if (!*(s
= builtin_opt
.optarg
))
287 else if ((fd
= check_fd(s
, W_OK
, &emsg
)) < 0) {
288 bi_errorf("-u: %s: %s", s
, emsg
);
295 if (!(builtin_opt
.info
& GI_MINUSMINUS
)) {
296 /* treat a lone - like -- */
297 if (wp
[builtin_opt
.optind
] &&
298 strcmp(wp
[builtin_opt
.optind
], "-") == 0)
299 builtin_opt
.optind
++;
300 } else if (flags
& PO_PMINUSMINUS
)
301 builtin_opt
.optind
--;
302 wp
+= builtin_opt
.optind
;
305 Xinit(xs
, xp
, 128, ATEMP
);
307 while (*wp
!= NULL
) {
310 while ((c
= *s
++) != '\0') {
312 if ((flags
& PO_EXPAND
) && c
== '\\') {
315 switch ((c
= *s
++)) {
316 /* Oddly enough, \007 seems more portable than
317 * \a (due to HP-UX cc, Ultrix cc, old pcc's,
320 case 'a': c
= '\007'; break;
321 case 'b': c
= '\b'; break;
322 case 'c': flags
&= ~PO_NL
;
323 continue; /* AT&T brain damage */
324 case 'f': c
= '\f'; break;
325 case 'n': c
= '\n'; break;
326 case 'r': c
= '\r'; break;
327 case 't': c
= '\t'; break;
328 case 'v': c
= 0x0B; break;
330 /* Look for an octal number: can have
331 * three digits (not counting the
332 * leading 0). Truly burnt.
335 for (i
= 0; i
< 3; i
++) {
336 if (*s
>= '0' && *s
<= '7')
337 c
= c
*8 + *s
++ - '0';
342 case '\0': s
--; c
= '\\'; break;
356 if (flags
& PO_HIST
) {
359 histsave(source
->line
, Xstring(xs
, xp
), 1);
362 int n
, len
= Xlength(xs
, xp
);
365 /* Ensure we aren't killed by a SIGPIPE while writing to
366 * a coprocess. at&t ksh doesn't seem to do this (seems
367 * to just check that the co-process is alive, which is
370 if (coproc
.write
>= 0 && coproc
.write
== fd
) {
372 opipe
= block_pipe();
374 for (s
= Xstring(xs
, xp
); len
> 0; ) {
375 n
= write(fd
, s
, len
);
377 if (flags
& PO_COPROC
)
379 if (errno
== EINTR
) {
380 /* allow user to ^C out */
382 if (flags
& PO_COPROC
)
383 opipe
= block_pipe();
386 /* This doesn't really make sense - could
387 * break scripts (print -p generates
390 * coproc_write_close(fd);
397 if (flags
& PO_COPROC
)
409 int pflag
= 0, vflag
= 0, Vflag
= 0;
412 int iam_whence
= wp
[0][0] == 'w';
414 const char *options
= iam_whence
? "pv" : "pvV";
416 while ((optc
= ksh_getopt(wp
, &builtin_opt
, options
)) != -1)
430 wp
+= builtin_opt
.optind
;
433 fcflags
= FC_BI
| FC_PATH
| FC_FUNC
;
435 /* Note that -p on its own is deal with in comexec() */
437 fcflags
|= FC_DEFPATH
;
438 /* Convert command options to whence options - note that
439 * command -pV uses a different path search than whence -v
440 * or whence -pv. This should be considered a feature.
445 fcflags
&= ~(FC_BI
| FC_FUNC
);
447 while ((vflag
|| ret
== 0) && (id
= *wp
++) != NULL
) {
449 if ((iam_whence
|| vflag
) && !pflag
)
450 tp
= ktsearch(&keywords
, id
, hash(id
));
452 tp
= ktsearch(&aliases
, id
, hash(id
));
453 if (tp
&& !(tp
->flag
& ISSET
))
457 tp
= findcom(id
, fcflags
);
458 if (vflag
|| (tp
->type
!= CALIAS
&& tp
->type
!= CEXEC
&&
459 tp
->type
!= CTALIAS
))
464 shprintf(" is a reserved word");
468 shprintf(" is an %salias for ",
469 (tp
->flag
& EXPORT
) ? "exported " :
471 if (!iam_whence
&& !vflag
)
472 shprintf("alias %s=", id
);
473 print_value_quoted(tp
->val
.s
);
478 if (tp
->flag
& EXPORT
)
479 shprintf("n exported");
480 if (tp
->flag
& TRACE
)
482 if (!(tp
->flag
& ISSET
)) {
483 shprintf(" undefined");
485 shprintf(" (autoload from %s)",
488 shprintf(" function");
493 shprintf(" is a%s shell builtin",
494 (tp
->flag
& SPEC_BI
) ? " special" : null
);
498 if (tp
->flag
& ISSET
) {
501 if (tp
->type
== CTALIAS
)
502 shprintf("a tracked %salias for ",
503 (tp
->flag
& EXPORT
) ?
506 shprintf("%s", tp
->val
.s
);
509 shprintf(" not found");
514 shprintf("%s is *GOK*", id
);
523 /* Deal with command -vV - command -p dealt with in comexec() */
527 /* Let c_whence do the work. Note that c_command() must be
528 * a distinct function from c_whence() (tested in comexec()).
533 /* typeset, export, and readonly */
537 struct block
*l
= e
->loc
;
539 Tflag fset
= 0, fclr
= 0;
540 int thing
= 0, func
= 0, local
= 0;
541 const char *options
= "L#R#UZ#fi#lprtux"; /* see comment below */
542 char *fieldstr
, *basestr
;
549 case 'e': /* export */
553 case 'r': /* readonly */
558 /* called with 'typeset -' */
560 case 't': /* typeset */
565 fieldstr
= basestr
= (char *) 0;
566 builtin_opt
.flags
|= GF_PLUSOPT
;
567 /* at&t ksh seems to have 0-9 as options, which are multiplied
568 * to get a number that is used with -L, -R, -Z or -i (eg, -1R2
569 * sets right justify in a field of 12). This allows options
570 * to be grouped in an order (eg, -Lu12), but disallows -i8 -L3 and
571 * does not allow the number to be specified as a separate argument
572 * Here, the number must follow the RLZi option, but is optional
573 * (see the # kludge in ksh_getopt()).
575 while ((optc
= ksh_getopt(wp
, &builtin_opt
, options
)) != -1) {
580 fieldstr
= builtin_opt
.optarg
;
584 fieldstr
= builtin_opt
.optarg
;
587 /* at&t ksh uses u, but this conflicts with
588 * upper/lower case. If this option is changed,
589 * need to change the -U below as well
595 fieldstr
= builtin_opt
.optarg
;
602 basestr
= builtin_opt
.optarg
;
608 /* posix export/readonly -p flag.
609 * typeset -p is the same as typeset (in pdksh);
610 * here for compatibility with ksh93.
621 flag
= UCASEV_AL
; /* upper case / autoload */
629 if (builtin_opt
.info
& GI_PLUS
) {
641 if (fieldstr
&& !bi_getn(fieldstr
, &field
))
644 if (basestr
&& !bi_getn(basestr
, &base
))
647 if (!(builtin_opt
.info
& GI_MINUSMINUS
) && wp
[builtin_opt
.optind
] &&
648 (wp
[builtin_opt
.optind
][0] == '-' ||
649 wp
[builtin_opt
.optind
][0] == '+') &&
650 wp
[builtin_opt
.optind
][1] == '\0') {
651 thing
= wp
[builtin_opt
.optind
][0];
652 builtin_opt
.optind
++;
655 if (func
&& ((fset
|fclr
) & ~(TRACE
|UCASEV_AL
|EXPORT
))) {
656 bi_errorf("only -t, -u and -x options may be used with -f");
659 if (wp
[builtin_opt
.optind
]) {
660 /* Take care of exclusions.
661 * At this point, flags in fset are cleared in fclr and vise
662 * versa. This property should be preserved.
664 if (fset
& LCASEV
) /* LCASEV has priority over UCASEV_AL */
666 if (fset
& LJUST
) /* LJUST has priority over RJUST */
668 if ((fset
& (ZEROFIL
|LJUST
)) == ZEROFIL
) { /* -Z implies -ZR */
672 /* Setting these attributes clears the others, unless they
673 * are also set in this command
675 if (fset
& (LJUST
| RJUST
| ZEROFIL
| UCASEV_AL
| LCASEV
|
676 INTEGER
| INT_U
| INT_L
))
677 fclr
|= ~fset
& (LJUST
| RJUST
| ZEROFIL
| UCASEV_AL
|
678 LCASEV
| INTEGER
| INT_U
| INT_L
);
681 /* set variables and attributes */
682 if (wp
[builtin_opt
.optind
]) {
689 for (i
= builtin_opt
.optind
; wp
[i
]; i
++) {
691 f
= findfunc(wp
[i
], hash(wp
[i
]),
692 (fset
&UCASEV_AL
) ? true : false);
694 /* at&t ksh does ++rval: bogus */
702 fptreef(shl_stdout
, 0,
705 "%s() %T\n", wp
[i
], f
->val
.t
);
706 } else if (!typeset(wp
[i
], fset
, fclr
, field
, base
)) {
707 bi_errorf("%s: not identifier", wp
[i
]);
714 /* list variables and attributes */
715 flag
= fset
| fclr
; /* no difference at this point.. */
717 for (l
= e
->loc
; l
; l
= l
->next
) {
718 for (p
= ktsort(&l
->funs
); (vp
= *p
++); ) {
719 if (flag
&& (vp
->flag
& flag
) == 0)
722 fptreef(shl_stdout
, 0, vp
->flag
& FKSH
?
723 "function %s %T\n" : "%s() %T\n",
724 vp
->name
, vp
->val
.t
);
726 shprintf("%s\n", vp
->name
);
730 for (l
= e
->loc
; l
; l
= l
->next
) {
731 for (p
= ktsort(&l
->vars
); (vp
= *p
++); ) {
735 * See if the parameter is set (for arrays, if any
738 for (tvp
= vp
; tvp
; tvp
= tvp
->u
.array
)
739 if (tvp
->flag
& ISSET
) {
745 * Check attributes - note that all array elements
746 * have (should have?) the same attributes, so checking
747 * the first is sufficient.
749 * Report an unset param only if the user has
750 * explicitly given it some attribute (like export);
751 * otherwise, after "echo $FOO", we would report FOO...
753 if (!any_set
&& !(vp
->flag
& USERATTRIB
))
755 if (flag
&& (vp
->flag
& flag
) == 0)
757 for (; vp
; vp
= vp
->u
.array
) {
758 /* Ignore array elements that aren't
759 * set unless there are no set elements,
760 * in which case the first is reported on */
761 if ((vp
->flag
&ARRAY
) && any_set
&&
765 if (thing
== 0 && flag
== 0) {
766 /* at&t ksh prints things
767 * like export, integer,
768 * leftadj, zerofill, etc.,
769 * but POSIX says must
770 * be suitable for re-entry...
772 shprintf("typeset ");
773 if ((vp
->flag
&INTEGER
))
775 if ((vp
->flag
&EXPORT
))
777 if ((vp
->flag
&RDONLY
))
779 if ((vp
->flag
&TRACE
))
781 if ((vp
->flag
&LJUST
))
782 shprintf("-L%d ", vp
->u2
.field
);
783 if ((vp
->flag
&RJUST
))
784 shprintf("-R%d ", vp
->u2
.field
);
785 if ((vp
->flag
&ZEROFIL
))
787 if ((vp
->flag
&LCASEV
))
789 if ((vp
->flag
&UCASEV_AL
))
791 if ((vp
->flag
&INT_U
))
793 shprintf("%s\n", vp
->name
);
800 "export" : "readonly");
801 if ((vp
->flag
&ARRAY
) && any_set
)
803 vp
->name
, vp
->index
);
805 shprintf("%s", vp
->name
);
806 if (thing
== '-' && (vp
->flag
&ISSET
)) {
807 char *s
= str_val(vp
);
810 /* at&t ksh can't have
811 * justified integers.. */
813 (INTEGER
|LJUST
|RJUST
)) ==
817 print_value_quoted(s
);
821 /* Only report first `element' of an array with
836 struct table
*t
= &aliases
;
837 int rv
= 0, rflag
= 0, tflag
, Uflag
= 0, pflag
= 0;
842 builtin_opt
.flags
|= GF_PLUSOPT
;
843 while ((optc
= ksh_getopt(wp
, &builtin_opt
, "dprtUx")) != -1) {
844 prefix
= builtin_opt
.info
& GI_PLUS
? '+' : '-';
860 * kludge for tracked alias initialization
861 * (don't do a path search, just make an entry)
872 wp
+= builtin_opt
.optind
;
874 if (!(builtin_opt
.info
& GI_MINUSMINUS
) && *wp
&&
875 (wp
[0][0] == '-' || wp
[0][0] == '+') && wp
[0][1] == '\0') {
880 tflag
= t
== &taliases
;
882 /* "hash -r" means reset all the tracked aliases.. */
884 static const char *const args
[] = {
885 "unalias", "-ta", (const char *) 0
889 shprintf("alias: -r flag can only be used with -t"
890 " and without arguments\n");
893 ksh_getopt_reset(&builtin_opt
, GF_ERROR
);
894 return c_unalias((char **) args
);
900 for (p
= ktsort(t
); (ap
= *p
++) != NULL
; )
901 if ((ap
->flag
& (ISSET
|xflag
)) == (ISSET
|xflag
)) {
903 shf_puts("alias ", shl_stdout
);
904 shf_puts(ap
->name
, shl_stdout
);
906 shf_putc('=', shl_stdout
);
907 print_value_quoted(ap
->val
.s
);
913 for (; *wp
!= NULL
; wp
++) {
915 char *val
= strchr(alias
, '=');
921 alias
= str_nsave(alias
, val
++ - alias
, ATEMP
);
923 if (val
== NULL
&& !tflag
&& !xflag
) {
924 ap
= ktsearch(t
, alias
, h
);
925 if (ap
!= NULL
&& (ap
->flag
&ISSET
)) {
927 shf_puts("alias ", shl_stdout
);
928 shf_puts(ap
->name
, shl_stdout
);
930 shf_putc('=', shl_stdout
);
931 print_value_quoted(ap
->val
.s
);
935 shprintf("%s alias not found\n", alias
);
940 ap
= ktenter(t
, alias
, h
);
941 ap
->type
= tflag
? CTALIAS
: CALIAS
;
942 /* Are we setting the value or just some flags? */
943 if ((val
&& !tflag
) || (!val
&& tflag
&& !Uflag
)) {
944 if (ap
->flag
&ALLOC
) {
945 ap
->flag
&= ~(ALLOC
|ISSET
);
946 afree((void*)ap
->val
.s
, APERM
);
948 /* ignore values for -t (at&t ksh does this) */
949 newval
= tflag
? search(alias
, path
, X_OK
, (int *) 0) :
952 ap
->val
.s
= str_save(newval
, APERM
);
953 ap
->flag
|= ALLOC
|ISSET
;
972 struct table
*t
= &aliases
;
977 while ((optc
= ksh_getopt(wp
, &builtin_opt
, "adt")) != -1)
991 wp
+= builtin_opt
.optind
;
993 for (; *wp
!= NULL
; wp
++) {
994 ap
= ktsearch(t
, *wp
, hash(*wp
));
999 if (ap
->flag
&ALLOC
) {
1000 ap
->flag
&= ~(ALLOC
|ISSET
);
1001 afree((void*)ap
->val
.s
, APERM
);
1003 ap
->flag
&= ~(DEFINED
|ISSET
|EXPORT
);
1009 for (ktwalk(&ts
, t
); (ap
= ktnext(&ts
)); ) {
1010 if (ap
->flag
&ALLOC
) {
1011 ap
->flag
&= ~(ALLOC
|ISSET
);
1012 afree((void*)ap
->val
.s
, APERM
);
1014 ap
->flag
&= ~(DEFINED
|ISSET
|EXPORT
);
1027 if (wp
[1] == (char *) 0) /* at&t ksh does this */
1028 bi_errorf("no arguments");
1030 for (wp
++; *wp
; wp
++)
1031 if (!evaluate(*wp
, &val
, KSH_RETURN_ERROR
, true)) {
1032 rv
= 2; /* distinguish error from zero result */
1047 while ((optc
= ksh_getopt(wp
, &builtin_opt
, "lpnz")) != -1)
1058 case 'z': /* debugging: print zombies */
1064 wp
+= builtin_opt
.optind
;
1066 if (j_jobs((char *) 0, flag
, nflag
))
1070 if (j_jobs(*wp
, flag
, nflag
))
1080 int bg
= strcmp(*wp
, "bg") == 0;
1083 if (!Flag(FMONITOR
)) {
1084 bi_errorf("job control not enabled");
1087 if (ksh_getopt(wp
, &builtin_opt
, null
) == '?')
1089 wp
+= builtin_opt
.optind
;
1092 rv
= j_resume(*wp
, bg
);
1094 rv
= j_resume("%%", bg
);
1095 /* POSIX says fg shall return 0 (unless an error occurs).
1096 * at&t ksh returns the exit value of the job...
1098 return (bg
|| Flag(FPOSIX
)) ? 0 : rv
;
1106 static char *kill_fmt_entry(void *arg
, int i
, char *buf
, int buflen
);
1108 /* format a single kill item */
1110 kill_fmt_entry(void *arg
, int i
, char *buf
, int buflen
)
1112 struct kill_info
*ki
= (struct kill_info
*) arg
;
1115 if (sigtraps
[i
].name
)
1116 shf_snprintf(buf
, buflen
, "%*d %*s %s",
1118 ki
->name_width
, sigtraps
[i
].name
,
1121 shf_snprintf(buf
, buflen
, "%*d %*d %s",
1123 ki
->name_width
, sigtraps
[i
].signal
,
1132 Trap
*t
= (Trap
*) 0;
1137 /* assume old style options if -digits or -UPPERCASE */
1138 if ((p
= wp
[1]) && *p
== '-' && (digit(p
[1]) || isupper(p
[1]))) {
1139 if (!(t
= gettrap(p
+ 1, true))) {
1140 bi_errorf("bad signal `%s'", p
+ 1);
1143 i
= (wp
[2] && strcmp(wp
[2], "--") == 0) ? 3 : 2;
1147 while ((optc
= ksh_getopt(wp
, &builtin_opt
, "ls:")) != -1)
1153 if (!(t
= gettrap(builtin_opt
.optarg
, true))) {
1154 bi_errorf("bad signal `%s'",
1155 builtin_opt
.optarg
);
1162 i
= builtin_opt
.optind
;
1164 if ((lflag
&& t
) || (!wp
[i
] && !lflag
)) {
1165 shf_fprintf(shl_out
,
1166 "usage: kill [-s signame | -signum | -signame] { job | pid | pgrp } ...\n"
1167 " kill -l [exit_status ...]\n");
1174 for (; wp
[i
]; i
++) {
1175 if (!bi_getn(wp
[i
], &n
))
1177 if (n
> 128 && n
< 128 + NSIG
)
1179 if (n
> 0 && n
< NSIG
&& sigtraps
[n
].name
)
1180 shprintf("%s\n", sigtraps
[n
].name
);
1182 shprintf("%d\n", n
);
1184 } else if (Flag(FPOSIX
)) {
1186 for (i
= 1; i
< NSIG
; i
++, p
= space
)
1187 if (sigtraps
[i
].name
)
1188 shprintf("%s%s", p
, sigtraps
[i
].name
);
1193 struct kill_info ki
;
1195 for (i
= NSIG
, ki
.num_width
= 1; i
>= 10; i
/= 10)
1197 ki
.name_width
= mess_width
= 0;
1198 for (i
= 0; i
< NSIG
; i
++) {
1199 w
= sigtraps
[i
].name
? strlen(sigtraps
[i
].name
) :
1201 if (w
> ki
.name_width
)
1203 w
= strlen(sigtraps
[i
].mess
);
1208 print_columns(shl_stdout
, NSIG
- 1,
1209 kill_fmt_entry
, (void *) &ki
,
1210 ki
.num_width
+ ki
.name_width
+ mess_width
+ 3, 1);
1215 sig
= t
? t
->signal
: SIGTERM
;
1216 for (; (p
= wp
[i
]); i
++) {
1220 } else if (!getn(p
, &n
)) {
1221 bi_errorf("%s: arguments must be jobs or process IDs",
1225 /* use killpg if < -1 since -1 does special things for
1226 * some non-killpg-endowed kills
1228 if ((n
< -1 ? killpg(-n
, sig
) : kill(n
, sig
)) < 0) {
1229 bi_errorf("%s: %s", p
, strerror(errno
));
1238 getopts_reset(int val
)
1241 ksh_getopt_reset(&user_opt
,
1242 GF_NONAME
| (Flag(FPOSIX
) ? 0 : GF_PLUSOPT
));
1243 user_opt
.optind
= user_opt
.uoptind
= val
;
1248 c_getopts(char **wp
)
1251 const char *options
;
1256 struct tbl
*vq
, *voptarg
;
1258 if (ksh_getopt(wp
, &builtin_opt
, null
) == '?')
1260 wp
+= builtin_opt
.optind
;
1264 bi_errorf("missing options argument");
1270 bi_errorf("missing name argument");
1273 if (!*var
|| *skip_varname(var
, true)) {
1274 bi_errorf("%s: is not an identifier", var
);
1278 if (e
->loc
->next
== (struct block
*) 0) {
1279 internal_errorf(0, "c_getopts: no argv");
1282 /* Which arguments are we parsing... */
1283 if (*wp
== (char *) 0)
1284 wp
= e
->loc
->next
->argv
;
1286 *--wp
= e
->loc
->next
->argv
[0];
1288 /* Check that our saved state won't cause a core dump... */
1289 for (argc
= 0; wp
[argc
]; argc
++)
1291 if (user_opt
.optind
> argc
||
1293 user_opt
.p
> strlen(wp
[user_opt
.optind
- 1]))) {
1294 bi_errorf("arguments changed since last call");
1298 user_opt
.optarg
= (char *) 0;
1299 optc
= ksh_getopt(wp
, &user_opt
, options
);
1301 if (optc
>= 0 && optc
!= '?' && (user_opt
.info
& GI_PLUS
)) {
1306 /* POSIX says var is set to ? at end-of-options, at&t ksh
1307 * sets it to null - we go with POSIX...
1309 buf
[0] = optc
< 0 ? '?' : optc
;
1313 /* at&t ksh does not change OPTIND if it was an unknown option.
1314 * Scripts counting on this are prone to break... (ie, don't count
1318 user_opt
.uoptind
= user_opt
.optind
;
1321 voptarg
= global("OPTARG");
1322 voptarg
->flag
&= ~RDONLY
; /* at&t ksh clears ro and int */
1323 /* Paranoia: ensure no bizarre results. */
1324 if (voptarg
->flag
& INTEGER
)
1325 typeset("OPTARG", 0, INTEGER
, 0, 0);
1326 if (user_opt
.optarg
== (char *) 0)
1329 /* This can't fail (have cleared readonly/integer) */
1330 setstr(voptarg
, user_opt
.optarg
, KSH_RETURN_ERROR
);
1335 /* Error message already printed (integer, readonly) */
1336 if (!setstr(vq
, buf
, KSH_RETURN_ERROR
))
1339 typeset(var
, EXPORT
, 0, 0, 0);
1341 return optc
< 0 ? 1 : ret
;
1348 int optc
, rv
= 0, macro
= 0, list
= 0;
1351 while ((optc
= ksh_getopt(wp
, &builtin_opt
, "lm")) != -1)
1362 wp
+= builtin_opt
.optind
;
1364 if (*wp
== NULL
) /* list all */
1365 rv
= x_bind((char*)NULL
, (char*)NULL
, 0, list
);
1367 for (; *wp
!= NULL
; wp
++) {
1368 cp
= strchr(*wp
, '=');
1371 if (x_bind(*wp
, cp
, macro
, 0))
1379 /* A leading = means assignments before command are kept;
1380 * a leading * means a POSIX special builtin;
1381 * a leading + means a POSIX regular builtin
1382 * (* and + should not be combined).
1384 const struct builtin kshbuiltins
[] = {
1385 {"+alias", c_alias
}, /* no =: at&t manual wrong */
1387 {"+command", c_command
},
1389 {"*=export", c_typeset
},
1392 #endif /* HISTORY */
1393 {"+getopts", c_getopts
},
1399 {"*=readonly", c_typeset
},
1400 {"=typeset", c_typeset
},
1401 {"+unalias", c_unalias
},
1402 {"whence", c_whence
},