2 * built-in Korn commands: c_*
13 int physical
= Flag(FPHYSICAL
);
14 int cdnode
; /* was a node from cdpath added in? */
15 int printpath
= 0; /* print where we cd'd? */
17 struct tbl
*pwd_s
, *oldpwd_s
;
20 char *dir
, *try, *pwd
;
25 while ((optc
= ksh_getopt(wp
, &builtin_opt
, "LP")) != -1)
36 wp
+= builtin_opt
.optind
;
38 pwd_s
= global("PWD");
39 oldpwd_s
= global("OLDPWD");
42 /* No arguments - go home */
43 if ((dir
= str_val(global("HOME"))) == null
) {
44 bi_errorf("no home directory (HOME not set)");
48 /* One argument: - or dir */
50 if (strcmp(dir
, "-") == 0) {
51 dir
= str_val(oldpwd_s
);
52 // dir = convert_path_multi(str_val(oldpwd_s));
54 bi_errorf("no OLDPWD");
60 /* Two arguments - substitute arg1 in PWD for arg2 */
61 int ilen
, olen
, nlen
, elen
;
65 bi_errorf("don't know current directory");
68 /* substitue arg1 for arg2 in current path.
69 * if the first substitution fails because the cd fails
70 * we could try to find another substitution. For now
73 if ((cp
= strstr(current_wd
, wp
[0])) == (char *) 0) {
74 bi_errorf("bad substitution");
77 ilen
= cp
- current_wd
;
80 elen
= strlen(current_wd
+ ilen
+ olen
) + 1;
81 fdir
= dir
= alloc(ilen
+ nlen
+ elen
, ATEMP
);
82 memcpy(dir
, current_wd
, ilen
);
83 memcpy(dir
+ ilen
, wp
[1], nlen
);
84 memcpy(dir
+ ilen
+ nlen
, current_wd
+ ilen
+ olen
, elen
);
88 bi_errorf("too many arguments");
92 Xinit(xs
, xp
, PATH
, ATEMP
);
93 /* xp will have a bogus value after make_path() - set it to 0
94 * so that if it's used, it will cause a dump
98 (void)xp
; // Should be unused.
100 cdpath
= str_val(global("CDPATH"));
102 cdnode
= make_path(current_wd
, dir
, &cdpath
, &xs
, &phys_path
);
104 rval
= chdir(try = Xstring(xs
, xp
) + phys_path
);
106 simplify_path(Xstring(xs
, xp
));
107 rval
= chdir(try = Xstring(xs
, xp
));
109 } while (rval
< 0 && cdpath
!= (char *) 0);
113 bi_errorf("%s: bad directory", dir
);
115 bi_errorf("%s - %s", try, strerror(errno
));
121 /* Clear out tracked aliases with relative paths */
125 /* Set OLDPWD (note: unsetting OLDPWD does not disable this
126 * setting in at&t ksh)
129 /* Ignore failure (happens if readonly or integer) */
130 setstr(oldpwd_s
, current_wd
, KSH_RETURN_ERROR
);
132 if (!ISABSPATH(Xstring(xs
, xp
))) {
135 if (!physical
|| !(pwd
= get_phys_path(Xstring(xs
, xp
))))
136 // pwd = Xstring(xs, xp);
137 pwd
= convert_path_multi(Xstring(xs
, xp
));
142 set_current_wd(ptmp
);
143 /* Ignore failure (happens if readonly or integer) */
144 setstr(pwd_s
, ptmp
, KSH_RETURN_ERROR
);
146 set_current_wd(null
);
147 pwd
= Xstring(xs
, xp
);
148 // pwd = convert_path_multi(Xstring(xs, xp));
149 /* XXX unset $PWD? */
151 if (printpath
|| cdnode
)
152 shprintf("%s\n", pwd
);
162 int physical
= Flag(FPHYSICAL
);
163 char *p
, *freep
= NULL
;
165 while ((optc
= ksh_getopt(wp
, &builtin_opt
, "LP")) != -1)
176 wp
+= builtin_opt
.optind
;
179 bi_errorf("too many arguments");
182 p
= current_wd
[0] ? (physical
? get_phys_path(current_wd
) : current_wd
) :
184 if (p
&& access(p
, R_OK
) < 0)
187 freep
= p
= ksh_get_wd((char *) 0, 0);
189 bi_errorf("can't get current directory - %s",
203 #define PO_NL BIT(0) /* print newline */
204 #define PO_EXPAND BIT(1) /* expand backslash sequences */
205 #define PO_PMINUSMINUS BIT(2) /* print a -- argument */
206 #define PO_HIST BIT(3) /* print to history instead of stdout */
207 #define PO_COPROC BIT(4) /* printing to coprocess: block SIGPIPE */
210 int flags
= PO_EXPAND
|PO_NL
;
215 if (wp
[0][0] == 'e') { /* echo command */
218 /* A compromise between sysV and BSD echo commands:
219 * escape sequences are enabled by default, and
220 * -n, -e and -E are recognized if they appear
221 * in arguments with no illegal options (ie, echo -nq
223 * Different from sysV echo since options are recognized,
224 * different from BSD echo since escape sequences are enabled
228 while ((s
= *wp
) && *s
== '-' && s
[1]) {
235 nflags
&= ~PO_EXPAND
;
237 /* bad option: don't use nflags, print
248 const char *options
= "Rnprsu,";
249 while ((optc
= ksh_getopt(wp
, &builtin_opt
, options
)) != -1)
251 case 'R': /* fake BSD echo command */
252 flags
|= PO_PMINUSMINUS
;
263 if ((fd
= coproc_getfd(W_OK
, &emsg
)) < 0) {
264 bi_errorf("-p: %s", emsg
);
275 if (!*(s
= builtin_opt
.optarg
))
277 else if ((fd
= check_fd(s
, W_OK
, &emsg
)) < 0) {
278 bi_errorf("-u: %s: %s", s
, emsg
);
285 if (!(builtin_opt
.info
& GI_MINUSMINUS
)) {
286 /* treat a lone - like -- */
287 if (wp
[builtin_opt
.optind
] &&
288 strcmp(wp
[builtin_opt
.optind
], "-") == 0)
289 builtin_opt
.optind
++;
290 } else if (flags
& PO_PMINUSMINUS
)
291 builtin_opt
.optind
--;
292 wp
+= builtin_opt
.optind
;
295 Xinit(xs
, xp
, 128, ATEMP
);
297 while (*wp
!= NULL
) {
300 while ((c
= *s
++) != '\0') {
302 if ((flags
& PO_EXPAND
) && c
== '\\') {
305 switch ((c
= *s
++)) {
306 /* Oddly enough, \007 seems more portable than
307 * \a (due to HP-UX cc, Ultrix cc, old pcc's,
310 case 'a': c
= '\007'; break;
311 case 'b': c
= '\b'; break;
312 case 'c': flags
&= ~PO_NL
;
313 continue; /* AT&T brain damage */
314 case 'f': c
= '\f'; break;
315 case 'n': c
= '\n'; break;
316 case 'r': c
= '\r'; break;
317 case 't': c
= '\t'; break;
318 case 'v': c
= 0x0B; break;
320 /* Look for an octal number: can have
321 * three digits (not counting the
322 * leading 0). Truly burnt.
325 for (i
= 0; i
< 3; i
++) {
326 if (*s
>= '0' && *s
<= '7')
327 c
= c
*8 + *s
++ - '0';
332 case '\0': s
--; c
= '\\'; break;
346 if (flags
& PO_HIST
) {
349 histsave(source
->line
, Xstring(xs
, xp
), 1);
352 int n
, len
= Xlength(xs
, xp
);
355 /* Ensure we aren't killed by a SIGPIPE while writing to
356 * a coprocess. at&t ksh doesn't seem to do this (seems
357 * to just check that the co-process is alive, which is
360 if (coproc
.write
>= 0 && coproc
.write
== fd
) {
362 opipe
= block_pipe();
364 for (s
= Xstring(xs
, xp
); len
> 0; ) {
365 n
= write(fd
, s
, len
);
367 if (flags
& PO_COPROC
)
369 if (errno
== EINTR
) {
370 /* allow user to ^C out */
372 if (flags
& PO_COPROC
)
373 opipe
= block_pipe();
376 /* This doesn't really make sense - could
377 * break scripts (print -p generates
380 * coproc_write_close(fd);
387 if (flags
& PO_COPROC
)
399 int pflag
= 0, vflag
= 0, Vflag
= 0;
402 int iam_whence
= wp
[0][0] == 'w';
404 const char *options
= iam_whence
? "pv" : "pvV";
406 while ((optc
= ksh_getopt(wp
, &builtin_opt
, options
)) != -1)
420 wp
+= builtin_opt
.optind
;
423 fcflags
= FC_BI
| FC_PATH
| FC_FUNC
;
425 /* Note that -p on its own is deal with in comexec() */
427 fcflags
|= FC_DEFPATH
;
428 /* Convert command options to whence options - note that
429 * command -pV uses a different path search than whence -v
430 * or whence -pv. This should be considered a feature.
435 fcflags
&= ~(FC_BI
| FC_FUNC
);
437 while ((vflag
|| ret
== 0) && (id
= *wp
++) != NULL
) {
439 if ((iam_whence
|| vflag
) && !pflag
)
440 tp
= ktsearch(&keywords
, id
, hash(id
));
442 tp
= ktsearch(aliases
, id
, hash(id
));
443 if (tp
&& !(tp
->flag
& ISSET
))
447 tp
= findcom(id
, fcflags
);
448 if (vflag
|| (tp
->type
!= CALIAS
&& tp
->type
!= CEXEC
&&
449 tp
->type
!= CTALIAS
))
454 shprintf(" is a reserved word");
458 shprintf(" is an %salias for ",
459 (tp
->flag
& EXPORTV
) ? "exported " :
461 if (!iam_whence
&& !vflag
)
462 shprintf("alias %s=", id
);
463 print_value_quoted(tp
->val
.s
);
468 if (tp
->flag
& EXPORTV
)
469 shprintf("n exported");
470 if (tp
->flag
& TRACE
)
472 if (!(tp
->flag
& ISSET
)) {
473 shprintf(" undefined");
475 shprintf(" (autoload from %s)",
478 shprintf(" function");
483 shprintf(" is a%s shell builtin",
484 (tp
->flag
& SPEC_BI
) ? " special" : null
);
488 if (tp
->flag
& ISSET
) {
491 if (tp
->type
== CTALIAS
)
492 shprintf("a tracked %salias for ",
493 (tp
->flag
& EXPORTV
) ?
496 shprintf("%s", tp
->val
.s
);
499 shprintf(" not found");
504 shprintf("%s is *GOK*", id
);
513 /* Deal with command -vV - command -p dealt with in comexec() */
517 /* Let c_whence do the work. Note that c_command() must be
518 * a distinct function from c_whence() (tested in comexec()).
523 /* typeset, export, and readonly */
527 struct block
*l
= e
->loc
;
529 Tflag fset
= 0, fclr
= 0;
530 int thing
= 0, func
= 0, local
= 0;
531 const char *options
= "L#R#UZ#fi#lprtux"; /* see comment below */
532 char *fieldstr
, *basestr
;
539 case 'e': /* export */
543 case 'r': /* readonly */
548 /* called with 'typeset -' */
550 case 't': /* typeset */
555 fieldstr
= basestr
= (char *) 0;
556 builtin_opt
.flags
|= GF_PLUSOPT
;
557 /* at&t ksh seems to have 0-9 as options, which are multiplied
558 * to get a number that is used with -L, -R, -Z or -i (eg, -1R2
559 * sets right justify in a field of 12). This allows options
560 * to be grouped in an order (eg, -Lu12), but disallows -i8 -L3 and
561 * does not allow the number to be specified as a separate argument
562 * Here, the number must follow the RLZi option, but is optional
563 * (see the # kludge in ksh_getopt()).
565 while ((optc
= ksh_getopt(wp
, &builtin_opt
, options
)) != -1) {
570 fieldstr
= builtin_opt
.optarg
;
574 fieldstr
= builtin_opt
.optarg
;
577 /* at&t ksh uses u, but this conflicts with
578 * upper/lower case. If this option is changed,
579 * need to change the -U below as well
585 fieldstr
= builtin_opt
.optarg
;
592 basestr
= builtin_opt
.optarg
;
598 /* posix export/readonly -p flag.
599 * typset -p is the same as typeset (in pdksh);
600 * here for compatability with ksh93.
611 flag
= UCASEV_AL
; /* upper case / autoload */
619 if (builtin_opt
.info
& GI_PLUS
) {
631 if (fieldstr
&& !bi_getn(fieldstr
, &field
))
634 if (basestr
&& !bi_getn(basestr
, &base
))
637 if (!(builtin_opt
.info
& GI_MINUSMINUS
) && wp
[builtin_opt
.optind
] &&
638 (wp
[builtin_opt
.optind
][0] == '-' ||
639 wp
[builtin_opt
.optind
][0] == '+') &&
640 wp
[builtin_opt
.optind
][1] == '\0')
642 thing
= wp
[builtin_opt
.optind
][0];
643 builtin_opt
.optind
++;
646 if (func
&& ((fset
|fclr
) & ~(TRACE
|UCASEV_AL
|EXPORTV
))) {
647 bi_errorf("only -t, -u and -x options may be used with -f");
650 if (wp
[builtin_opt
.optind
]) {
651 /* Take care of exclusions.
652 * At this point, flags in fset are cleared in fclr and vise
653 * versa. This property should be preserved.
655 if (fset
& LCASEV
) /* LCASEV has priority over UCASEV_AL */
657 if (fset
& LJUST
) /* LJUST has priority over RJUST */
659 if ((fset
& (ZEROFIL
|LJUST
)) == ZEROFIL
) { /* -Z implies -ZR */
663 /* Setting these attributes clears the others, unless they
664 * are also set in this command
666 if (fset
& (LJUST
| RJUST
| ZEROFIL
| UCASEV_AL
| LCASEV
|
667 INTEGER
| INT_U
| INT_L
))
668 fclr
|= ~fset
& (LJUST
| RJUST
| ZEROFIL
| UCASEV_AL
| LCASEV
|
669 INTEGER
| INT_U
| INT_L
);
672 /* set variables and attributes */
673 if (wp
[builtin_opt
.optind
]) {
680 for (i
= builtin_opt
.optind
; wp
[i
]; i
++) {
682 f
= findfunc(wp
[i
], hash(wp
[i
]),
683 (fset
&UCASEV_AL
) ? true : false);
685 /* at&t ksh does ++rval: bogus */
693 fptreef(shl_stdout
, 0,
696 "%s() %T\n", wp
[i
], f
->val
.t
);
697 } else if (!typeset(wp
[i
], fset
, fclr
, field
, base
)) {
698 bi_errorf("%s: not identifier", wp
[i
]);
705 /* list variables and attributes */
706 flag
= fset
| fclr
; /* no difference at this point.. */
708 for (l
= e
->loc
; l
; l
= l
->next
) {
709 for (p
= ktsort(&l
->funs
); (vp
= *p
++); ) {
710 if (flag
&& (vp
->flag
& flag
) == 0)
713 fptreef(shl_stdout
, 0, vp
->flag
& FKSH
?
714 "function %s %T\n" : "%s() %T\n",
715 vp
->name
, vp
->val
.t
);
717 shprintf("%s\n", vp
->name
);
721 for (l
= e
->loc
; l
; l
= l
->next
) {
722 for (p
= ktsort(&l
->vars
); (vp
= *p
++); ) {
726 * See if the parameter is set (for arrays, if any
729 for (tvp
= vp
; tvp
; tvp
= tvp
->u
.array
)
730 if (tvp
->flag
& ISSET
) {
735 * Check attributes - note that all array elements
736 * have (should have?) the same attributes, so checking
737 * the first is sufficient.
739 * Report an unset param only if the user has
740 * explicitly given it some attribute (like export);
741 * otherwise, after "echo $FOO", we would report FOO...
743 if (!any_set
&& !(vp
->flag
& USERATTRIB
))
745 if (flag
&& (vp
->flag
& flag
) == 0)
747 for (; vp
; vp
= vp
->u
.array
) {
748 /* Ignore array elements that aren't set unless there
749 * are no set elements, in which case the first is
752 if ((vp
->flag
&ARRAY
) && any_set
&& !(vp
->flag
& ISSET
))
755 if (thing
== 0 && flag
== 0) {
756 /* at&t ksh prints things like export, integer,
757 * leftadj, zerofill, etc., but POSIX says must
758 * be suitable for re-entry...
760 shprintf("typeset ");
761 if ((vp
->flag
&INTEGER
))
763 if ((vp
->flag
&EXPORTV
))
765 if ((vp
->flag
&RDONLY
))
767 if ((vp
->flag
&TRACE
))
769 if ((vp
->flag
&LJUST
))
770 shprintf("-L%d ", vp
->u2
.field
);
771 if ((vp
->flag
&RJUST
))
772 shprintf("-R%d ", vp
->u2
.field
);
773 if ((vp
->flag
&ZEROFIL
))
775 if ((vp
->flag
&LCASEV
))
777 if ((vp
->flag
&UCASEV_AL
))
779 if ((vp
->flag
&INT_U
))
781 shprintf("%s\n", vp
->name
);
787 (flag
& EXPORTV
) ? "export" : "readonly");
788 if ((vp
->flag
&ARRAY
) && any_set
)
789 shprintf("%s[%d]", vp
->name
, vp
->index
);
791 shprintf("%s", vp
->name
);
792 if (thing
== '-' && (vp
->flag
&ISSET
)) {
793 char *s
= str_val(vp
);
795 /* at&t ksh can't have justified integers.. */
796 if ((vp
->flag
& (INTEGER
|LJUST
|RJUST
))
800 print_value_quoted(s
);
804 /* Only report first `element' of an array with
819 struct table
*t
= aliases
;
820 int rv
= 0, rflag
= 0, tflag
, Uflag
= 0, pflag
= 0;
825 builtin_opt
.flags
|= GF_PLUSOPT
;
826 while ((optc
= ksh_getopt(wp
, &builtin_opt
, "dprtUx")) != -1) {
827 prefix
= builtin_opt
.info
& GI_PLUS
? '+' : '-';
842 /* kludge for tracked alias initialization
843 * (don't do a path search, just make an entry)
854 wp
+= builtin_opt
.optind
;
856 if (!(builtin_opt
.info
& GI_MINUSMINUS
) && *wp
857 && (wp
[0][0] == '-' || wp
[0][0] == '+') && wp
[0][1] == '\0')
863 tflag
= t
== taliases
;
865 /* "hash -r" means reset all the tracked aliases.. */
867 static const char *const args
[] = {
868 "unalias", "-ta", (const char *) 0
872 shprintf("alias: -r flag can only be used with -t"
873 "and without arguments\n");
876 ksh_getopt_reset(&builtin_opt
, GF_ERROR
);
877 return c_unalias((char **) args
);
884 for (p
= ktsort(t
); (ap
= *p
++) != NULL
; )
885 if ((ap
->flag
& (ISSET
|xflag
)) == (ISSET
|xflag
)) {
887 shf_puts("alias ", shl_stdout
);
888 shf_puts(ap
->name
, shl_stdout
);
890 shf_putc('=', shl_stdout
);
891 print_value_quoted(ap
->val
.s
);
897 for (; *wp
!= NULL
; wp
++) {
899 char *val
= strchr(alias
, '=');
905 alias
= str_nsave(alias
, val
++ - alias
, ATEMP
);
907 if (val
== NULL
&& !tflag
&& !xflag
) {
908 ap
= ktsearch(t
, alias
, h
);
909 if (ap
!= NULL
&& (ap
->flag
&ISSET
)) {
911 shf_puts("alias ", shl_stdout
);
912 shf_puts(ap
->name
, shl_stdout
);
914 shf_putc('=', shl_stdout
);
915 print_value_quoted(ap
->val
.s
);
919 shprintf("%s alias not found\n", alias
);
924 ap
= ktenter(t
, alias
, h
);
925 ap
->type
= tflag
? CTALIAS
: CALIAS
;
926 /* Are we setting the value or just some flags? */
927 if ((val
&& !tflag
) || (!val
&& tflag
&& !Uflag
)) {
928 if (ap
->flag
&ALLOC
) {
929 ap
->flag
&= ~(ALLOC
|ISSET
);
930 afree((void*)ap
->val
.s
, APERM
);
932 /* ignore values for -t (at&t ksh does this) */
933 newval
= tflag
? search(alias
, path
, X_OK
, (int *) 0) :
936 ap
->val
.s
= str_save(newval
, APERM
);
937 ap
->flag
|= ALLOC
|ISSET
;
956 struct table
*t
= aliases
;
961 while ((optc
= ksh_getopt(wp
, &builtin_opt
, "adt")) != -1)
975 wp
+= builtin_opt
.optind
;
977 for (; *wp
!= NULL
; wp
++) {
978 ap
= ktsearch(t
, *wp
, hash(*wp
));
983 if (ap
->flag
&ALLOC
) {
984 ap
->flag
&= ~(ALLOC
|ISSET
);
985 afree((void*)ap
->val
.s
, APERM
);
987 ap
->flag
&= ~(DEFINED
|ISSET
|EXPORTV
);
993 for (ktwalk(&ts
, t
); (ap
= ktnext(&ts
)); ) {
994 if (ap
->flag
&ALLOC
) {
995 ap
->flag
&= ~(ALLOC
|ISSET
);
996 afree((void*)ap
->val
.s
, APERM
);
998 ap
->flag
&= ~(DEFINED
|ISSET
|EXPORTV
);
1011 if (wp
[1] == (char *) 0) /* at&t ksh does this */
1012 bi_errorf("no arguments");
1014 for (wp
++; *wp
; wp
++)
1015 if (!evaluate(*wp
, &val
, KSH_RETURN_ERROR
, true)) {
1016 rv
= 2; /* distinguish error from zero result */
1031 while ((optc
= ksh_getopt(wp
, &builtin_opt
, "lpnz")) != -1)
1042 case 'z': /* debugging: print zombies */
1048 wp
+= builtin_opt
.optind
;
1050 if (j_jobs((char *) 0, flag
, nflag
))
1054 if (j_jobs(*wp
, flag
, nflag
))
1064 static char *kill_fmt_entry(void *arg
, int i
, char *buf
, int buflen
);
1066 /* format a single kill item */
1068 kill_fmt_entry(void *arg
, int i
, char *buf
, int buflen
)
1070 struct kill_info
*ki
= (struct kill_info
*) arg
;
1073 if (sigtraps
[i
].name
)
1074 shf_snprintf(buf
, buflen
, "%*d %*s %s",
1076 ki
->name_width
, sigtraps
[i
].name
,
1079 shf_snprintf(buf
, buflen
, "%*d %*d %s",
1081 ki
->name_width
, sigtraps
[i
].signal
,
1090 Trap
*t
= (Trap
*) 0;
1095 /* assume old style options if -digits or -UPPERCASE */
1096 if ((p
= wp
[1]) && *p
== '-' && (digit(p
[1]) || isupper(p
[1]))) {
1097 if (!(t
= gettrap(p
+ 1, true))) {
1098 bi_errorf("bad signal `%s'", p
+ 1);
1101 i
= (wp
[2] && strcmp(wp
[2], "--") == 0) ? 3 : 2;
1105 while ((optc
= ksh_getopt(wp
, &builtin_opt
, "ls:")) != -1)
1111 if (!(t
= gettrap(builtin_opt
.optarg
, true))) {
1112 bi_errorf("bad signal `%s'",
1113 builtin_opt
.optarg
);
1120 i
= builtin_opt
.optind
;
1122 if ((lflag
&& t
) || (!wp
[i
] && !lflag
)) {
1123 shf_fprintf(shl_out
,
1124 "Usage: kill [ -s signame | -signum | -signame ] {pid|job}...\n"
1125 " kill -l [exit_status]\n");
1132 for (; wp
[i
]; i
++) {
1133 if (!bi_getn(wp
[i
], &n
))
1135 if (n
> 128 && n
< 128 + NSIG
)
1137 if (n
> 0 && n
< NSIG
&& sigtraps
[n
].name
)
1138 shprintf("%s\n", sigtraps
[n
].name
);
1140 shprintf("%d\n", n
);
1142 } else if (Flag(FPOSIX
)) {
1144 for (i
= 1; i
< NSIG
; i
++, p
= space
)
1145 if (sigtraps
[i
].name
)
1146 shprintf("%s%s", p
, sigtraps
[i
].name
);
1151 struct kill_info ki
;
1153 for (i
= NSIG
, ki
.num_width
= 1; i
>= 10; i
/= 10)
1155 ki
.name_width
= mess_width
= 0;
1156 for (i
= 0; i
< NSIG
; i
++) {
1157 w
= sigtraps
[i
].name
? strlen(sigtraps
[i
].name
) :
1159 if (w
> ki
.name_width
)
1161 w
= strlen(sigtraps
[i
].mess
);
1166 print_columns(shl_stdout
, NSIG
- 1,
1167 kill_fmt_entry
, (void *) &ki
,
1168 ki
.num_width
+ ki
.name_width
+ mess_width
+ 3, 1);
1173 sig
= t
? t
->signal
: SIGTERM
;
1174 for (; (p
= wp
[i
]); i
++) {
1178 } else if (!getn(p
, &n
)) {
1179 bi_errorf("%s: arguments must be jobs or process IDs",
1183 /* use killpg if < -1 since -1 does special things for
1184 * some non-killpg-endowed kills
1186 if ((n
< -1 ? killpg(-n
, sig
) : kill(n
, sig
)) < 0) {
1187 bi_errorf("%s: %s", p
, strerror(errno
));
1196 getopts_reset(int val
)
1199 ksh_getopt_reset(&user_opt
,
1200 GF_NONAME
| (Flag(FPOSIX
) ? 0 : GF_PLUSOPT
));
1201 user_opt
.optind
= user_opt
.uoptind
= val
;
1206 c_getopts(char **wp
)
1209 const char *options
;
1214 struct tbl
*vq
, *voptarg
;
1216 if (ksh_getopt(wp
, &builtin_opt
, null
) == '?')
1218 wp
+= builtin_opt
.optind
;
1222 bi_errorf("missing options argument");
1228 bi_errorf("missing name argument");
1231 if (!*var
|| *skip_varname(var
, true)) {
1232 bi_errorf("%s: is not an identifier", var
);
1236 if (e
->loc
->next
== (struct block
*) 0) {
1237 internal_errorf(0, "c_getopts: no argv");
1240 /* Which arguments are we parsing... */
1241 if (*wp
== (char *) 0)
1242 wp
= e
->loc
->next
->argv
;
1244 *--wp
= e
->loc
->next
->argv
[0];
1246 /* Check that our saved state won't cause a core dump... */
1247 for (argc
= 0; wp
[argc
]; argc
++)
1249 if (user_opt
.optind
> argc
||
1251 user_opt
.p
> strlen(wp
[user_opt
.optind
- 1])))
1253 bi_errorf("arguments changed since last call");
1257 user_opt
.optarg
= (char *) 0;
1258 optc
= ksh_getopt(wp
, &user_opt
, options
);
1260 if (optc
>= 0 && optc
!= '?' && (user_opt
.info
& GI_PLUS
)) {
1265 /* POSIX says var is set to ? at end-of-options, at&t ksh
1266 * sets it to null - we go with POSIX...
1268 buf
[0] = optc
< 0 ? '?' : optc
;
1272 /* at&t ksh does not change OPTIND if it was an unknown option.
1273 * Scripts counting on this are prone to break... (ie, don't count
1277 user_opt
.uoptind
= user_opt
.optind
;
1280 voptarg
= global("OPTARG");
1281 voptarg
->flag
&= ~RDONLY
; /* at&t ksh clears ro and int */
1282 /* Paranoia: ensure no bizarre results. */
1283 if (voptarg
->flag
& INTEGER
)
1284 typeset("OPTARG", 0, INTEGER
, 0, 0);
1285 if (user_opt
.optarg
== (char *) 0)
1288 /* This can't fail (have cleared readonly/integer) */
1289 setstr(voptarg
, user_opt
.optarg
, KSH_RETURN_ERROR
);
1294 /* Error message already printed (integer, readonly) */
1295 if (!setstr(vq
, buf
, KSH_RETURN_ERROR
))
1298 typeset(var
, EXPORTV
, 0, 0, 0);
1300 return optc
< 0 ? 1 : ret
;
1303 /* contact command - to ensure that people know that they are able to contact me - hnl_dk */
1306 c_contact(char **wp
)
1308 shprintf(" .............................................................................\n");
1310 shprintf(" : _____.___. _______ .____. :\n");
1311 shprintf("_____\\__ : |____________ \\ ___/___.____| |_______________ _____ :\n");
1312 shprintf("\\ __ __ ___/___ /__\\___ : |__ : __ / /___/_ /_____\n");
1313 shprintf(" \\ \\| |/ . |/ /// (_\\ ___/ |/ /_ /_\\ /_\\ \\\n");
1314 shprintf(" \\_______._______/|________///____________. |____._________/____________________\\\n");
1315 shprintf(" / |____|\n");
1316 shprintf(" : : spot\n");
1317 shprintf(" : This is abc-shell "ABC_VERSION
", the AmigaOS4 POSIX shell :\n");
1318 shprintf(" : the project page of abc-shell: http://sf.net/projects/abc-shell :\n");
1319 shprintf(" : you are welcome to contact me (Henning Nielsen Lund) at hnl_dk@amigaos.dk :\n");
1321 shprintf(" :...........................................................................:\n");
1325 /* A leading = means assignments before command are kept;
1326 * a leading * means a POSIX special builtin;
1327 * a leading + means a POSIX regular builtin
1328 * (* and + should not be combined).
1330 const struct builtin kshbuiltins
[] = {
1331 {"+alias", c_alias
}, /* no =: at&t manual wrong */
1333 {"+command", c_command
},
1335 {"*=export", c_typeset
},
1338 #endif /* HISTORY */
1339 {"+getopts", c_getopts
},
1345 {"*=readonly", c_typeset
},
1346 {"=typeset", c_typeset
},
1347 {"+unalias", c_unalias
},
1348 {"whence", c_whence
},
1349 {"contact", c_contact
}, /* special abc-shell builtin */