home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Professional
/
OS2PRO194.ISO
/
os2
/
sysutils
/
kornshel
/
c_ksh.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-08
|
13KB
|
626 lines
/*
* built-in Korn commands: c_*
*/
#ifndef lint
static char *RCSid = "$Id: c_ksh.c,v 1.2 1992/04/25 08:33:28 sjg Exp $";
#endif
#include "stdh.h"
#include <errno.h>
#include <setjmp.h>
#include "sh.h"
int
c_hash(wp)
register char **wp;
{
register struct tbl *tp, **p;
wp++;
if (*wp == NULL) {
for (p = tsort(&commands); (tp = *p++) != NULL; )
if ((tp->flag&ISSET))
printf("%s\n", tp->val.s);
return 0;
}
if (strcmp(*wp, "-r") == 0)
flushcom(1);
while (*wp != NULL)
findcom(*wp++, 1);
return 0;
}
int
c_cd(wp)
register char **wp;
{
char path [PATH];
char newd [PATH];
register char *cp;
register char *dir;
register char *cdpath;
register char *rep;
register char *pwd = NULL, *oldpwd = NULL;
register int done = 0;
register int prt = 0;
register struct tbl *v_pwd = NULL, *v_oldpwd = NULL;
if ((dir = wp[1]) == NULL && (dir = strval(global("HOME"))) == NULL)
errorf("no home directory");
v_pwd = global("PWD");
if ((pwd = strval(v_pwd)) == null) {
getcwd(path, (size_t)PATH);
setstr(v_pwd, path);
pwd = strval(v_pwd);
}
if (wp[1] != NULL && (rep = wp[2]) != NULL) {
/*
* Two arg version: cd pat rep
*/
if (strlen(pwd) - strlen(dir) + strlen(rep) >= PATH)
errorf("substitution too long\n");
cp = strstr(pwd, dir);
if (cp == NULL)
errorf("substitution failed\n");
strncpy(path, pwd, cp - pwd); /* first part */
strcpy(path + (cp - pwd), rep); /* replacement */
strcat(path, cp + strlen(dir)); /* last part */
dir = strsave(path, ATEMP);
prt = 1;
} else if (dir[0] == '-' && dir[1] == '\0') {
/*
* Change to previous dir: cd -
*/
dir = strval(v_oldpwd = global("OLDPWD"));
prt = 1;
}
#ifdef OS2
if (ISDIRSEP(dir[0]) ||
(dir[0] == '.' &&
(dir [1] == 0 || ISDIRSEP(dir[1]) ||
(dir[1] == '.' && (dir[2] == 0 || ISDIRSEP(dir[2]))))) ||
(isalpha(dir[0]) && dir[1] == ':') ) {
#else
if (ISDIRSEP(dir[0]) ||
(dir[0] == '.' &&
(dir[1] == 0 || ISDIRSEP(dir[1]) ||
(dir[1] == '.' && (dir [2] == 0 || ISDIRSEP(dir[2])))))) {
#endif
/*
* dir is an explicitly named path, so no CDPATH search
*/
cleanpath(pwd, dir, newd);
if (chdir(newd) < 0)
errorf("%s: bad directory\n", newd);
else if (prt)
shellf("%s\n", newd);
flushcom(0);
} else {
/*
* search CDPATH for dir
*/
cdpath = strval(global("CDPATH"));
while ( !done && cdpath != NULL ) {
cp = path;
#ifdef OS2
while (*cdpath && *cdpath != ';')
#else
while (*cdpath && *cdpath != ':')
#endif
*cp++ = *cdpath++;
if (*cdpath == '\0')
cdpath = NULL;
else
cdpath++;
if (prt = (cp > path)) {
*cp++ = DIRSEP;
(void) strcpy( cp, dir );
cp = path;
} else
cp = dir;
cleanpath(pwd, cp, newd);
if (chdir(newd) == 0)
done = 1;
} while (!done && cdpath != NULL);
if (!done)
errorf("%s: bad directory\n", dir);
if (prt)
shellf("%s\n", newd);
flushcom(0);
}
/*
* Keep track of OLDPWD and PWD
*/
oldpwd = pwd;
#ifdef OS2
getcwd(path, (size_t)PATH);
pwd = path;
#else
pwd = newd;
#endif
if (!v_oldpwd)
v_oldpwd = global("OLDPWD");
if (oldpwd && *oldpwd)
setstr(v_oldpwd, oldpwd);
else
unset(v_oldpwd);
if (*pwd)
setstr(v_pwd, pwd);
else
unset(v_pwd);
return 0;
}
int
c_print(wp)
register char **wp;
{
int nl = 1;
int expand = 1;
FILE *f = stdout;
for (wp++; *wp != NULL && **wp == '-'; wp++) {
register char *s = *wp + 1;
if (*s == '\0') {
wp++;
break;
}
while (*s) switch (*s++) {
case 'n':
nl = 0;
break;
case 'e':
expand = 1;
break;
case 'r':
expand = 0;
break;
case 'u':
if (!digit(*s) || (f = shf[*s++-'0']) == NULL)
errorf("bad -u argument\n");
break;
}
}
while (*wp != NULL) {
register char *s = *wp;
register int c;
while ((c = *s++) != '\0')
if (expand && c == '\\') {
switch ((c = *s++)) {
case 'b': c = '\b'; break;
case 'c': nl = 0; continue; /* AT&T brain damage */
case 'f': c = '\f'; break;
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case 'v': c = 0x0B; break;
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
c = c - '0';
if (*s >= '0' && *s <= '7')
c = 8*c + *s++ - '0';
if (*s >= '0' && *s <= '7')
c = 8*c + *s++ - '0';
break;
case '\\': break;
default:
putc('\\', f);
}
putc(c, f);
} else
putc(c, f);
if (*++wp != NULL)
putc(' ', f);
}
if (nl)
putc('\n', f);
return 0;
}
/* todo: handle case where id is both lexical and command */
int
c_whence(wp)
register char **wp;
{
register struct tbl *tp;
char *id;
int vflag = 0;
int ret = 0;
for (wp++; (id = *wp) != NULL && *id == '-'; wp++)
if (id[1] == 'v')
vflag = 1;
while ((id = *wp++) != NULL) {
tp = tsearch(&lexicals, id, hash(id));
if (tp == NULL)
tp = findcom(id, 0);
if (vflag)
switch ((tp == NULL) ? CNONE : tp->type) {
case CNONE:
printf("%s is unknown\n", id);
ret = 1;
break;
case CSHELL:
printf("%s is a shell builtin\n", id);
break;
case CFUNC:
printf("%s is a function\n", id);
fptreef(stdout, "function %s %T\n", id, tp->val.t);
break;
case CEXEC:
printf("%s is %s\n", id,
(tp->flag&ISSET) ? tp->val.s : "unknown");
if (!(tp->flag&ISSET))
ret = 1;
break;
case CALIAS:
printf("%s is the alias '%s'\n", id, tp->val.s);
break;
case CKEYWD:
printf("%s is a shell keyword\n", id);
break;
default:
printf("%s is *GOK*\n", id);
break;
}
else
switch ((tp == NULL) ? CNONE : tp->type) {
case CNONE:
printf("\n");
ret = 1;
break;
case CSHELL:
printf("builtin %s\n", id);
break;
case CFUNC:
printf("%s\n", id);
break;
case CEXEC:
printf("%s\n", (tp->flag&ISSET) ? tp->val.s : "");
if (!(tp->flag&ISSET))
ret = 1;
break;
case CALIAS:
printf("%s\n", tp->val.s);
break;
case CKEYWD:
printf("%s\n", id);
break;
default:
printf("*GOK*\n");
break;
}
}
return ret;
}
/* typeset, export, and readonly */
int
c_typeset(wp)
register char **wp;
{
register char *id;
struct block *l = e.loc;
register struct tbl *vp, **p;
int fset = 0, fclr = 0;
int thing = 0, func = 0, local = 0;
switch (**wp) {
case 'e': /* export */
fset |= EXPORT;
break;
case 'r': /* readonly */
fset |= RDONLY;
break;
case 't': /* typeset */
local = 1;
break;
}
for (wp++; (id = *wp) != NULL && (*id == '-' || *id == '+'); wp++) {
int flag = 0;
thing = *id;
while (*++id != '\0') switch (*id) {
case 'f':
flag |= FUNCT;
func = 1;
break;
case 'i':
flag |= INTEGER;
break;
case 'r':
flag |= RDONLY;
break;
case 'x':
flag |= EXPORT;
break;
case 't':
flag |= TRACE;
break;
default:
errorf("unknown flag -%c\n", *id);
}
if (flag != 0) { /* + or - with options */
if (thing == '-')
fset |= flag;
else
fclr |= flag;
thing = 0;
}
}
/* list variables and attributes */
if (*wp == NULL) {
for (l = e.loc; l != NULL; l = l->next) {
for (p = tsort((func==0) ? &l->vars : &l->funs);
(vp = *p++) != NULL; )
if ((vp->flag&ISSET))
if (thing == 0 && fclr == 0 && fset == 0) {
printf("typeset ");
if ((vp->flag&INTEGER))
printf("-i ");
if ((vp->flag&EXPORT))
printf("-x ");
if ((vp->flag&RDONLY))
printf("-r ");
if ((vp->flag&TRACE))
printf("-t ");
printf("%s\n", vp->name);
} else
if (thing == '+' ||
(fclr && (vp->flag&fclr) == fclr)) {
printf("%s\n", vp->name);
} else
if (thing == '-' ||
(fset && (vp->flag&fset) == fset)) {
if (fset&FUNCT)
printf("function %s\n", vp->name);
else
printf("%s=%s\n", vp->name, strval(vp));
}
}
return (0);
}
if (local)
fset |= LOCAL;
for (; *wp != NULL; wp++)
#if 0
if (func) {
} else
#endif
if (typeset(*wp, fset, fclr) == NULL)
errorf("%s: not identifier\n", *wp);
return 0;
}
int
c_alias(wp)
register char **wp;
{
register struct table *t = &lexicals;
register struct tbl *ap, **p;
int rv = 0;
if (*++wp != NULL && strcmp(*wp, "-d") == 0) {
t = &homedirs;
wp++;
}
if (*wp == NULL)
for (p = tsort(t); (ap = *p++) != NULL; )
if (ap->type == CALIAS && (ap->flag&DEFINED))
printf("%s='%s'\n", ap->name, ap->val.s);
for (; *wp != NULL; wp++) {
register char *id = *wp;
register char *val = strchr(id, '=');
if (val == NULL) {
ap = tsearch(t, id, hash(id));
if (ap != NULL && ap->type == CALIAS && (ap->flag&DEFINED))
printf("%s='%s'\n", ap->name, ap->val.s);
else
rv = 1;
} else {
*val++ = '\0';
ap = tenter(t, id, hash(id));
if (ap->type == CKEYWD)
errorf("cannot alias keyword\n");
if ((ap->flag&ALLOC)) {
afree((void*)ap->val.s, APERM);
ap->flag &= ~(ALLOC|ISSET);
}
ap->type = CALIAS;
ap->val.s = strsave(val, APERM);
ap->flag |= DEFINED|ALLOC|ISSET;
}
}
return rv;
}
int
c_unalias(wp)
register char **wp;
{
register struct table *t = &lexicals;
register struct tbl *ap;
if (*++wp != NULL && strcmp(*wp, "-d") == 0) {
t = &homedirs;
wp++;
}
for (; *wp != NULL; wp++) {
ap = tsearch(t, *wp, hash(*wp));
if (ap == NULL || ap->type != CALIAS)
continue;
if ((ap->flag&ALLOC))
afree((void*)ap->val.s, APERM);
ap->flag &= ~(DEFINED|ISSET|ALLOC);
}
return 0;
}
int
c_let(wp)
char **wp;
{
int rv = 1;
for (wp++; *wp; wp++)
rv = evaluate(*wp) == 0;
return rv;
}
int
c_jobs(wp)
char **wp;
{
j_jobs();
return 0;
}
#ifdef JOBS
int
c_fgbg(wp)
register char **wp;
{
int bg = strcmp(*wp, "bg") == 0;
if (!flag[FMONITOR])
errorf("Job control not enabled\n");
wp++;
j_resume(j_lookup((*wp == NULL) ? "%" : *wp), bg);
return 0;
}
#endif
int
c_kill(wp)
register char **wp;
{
register char *cp;
int sig = 15; /* SIGTERM */
int rv = 0;
int n;
int gotsig = FALSE;
if (*++wp == NULL)
errorf("Usage: kill [-l] [-signal] {pid|job} ...\n");
if (strcmp(*wp, "-l") == 0) {
register struct trap *p = sigtraps;
for (sig = 0; sig < SIGNALS; sig++, p++)
if (p->signal)
printf("%2d %8s %s\n", p->signal, p->name, p->mess);
return 0;
}
for (; (cp = *wp) != NULL; wp++)
if (*cp == '-' && gotsig == FALSE && *(wp+1) != NULL) {
struct trap *p;
gotsig = FALSE;
if (digit(*(cp+1))) {
if ((n = atoi(cp+1)) < SIGNALS) {
sig = n;
gotsig = TRUE;
} else if (kill(n, sig) < 0) {
shellf("%s: %s\n", cp, strerror(errno));
rv++;
}
} else {
p = gettrap(cp+1);
if (p == NULL)
errorf("bad signal %s\n", cp+1);
sig = p->signal;
gotsig = TRUE;
}
} else {
gotsig = FALSE;
if (digit(*cp) || (*cp == '-' && digit(*(cp+1)))) {
if (kill(atoi(cp), sig) < 0) {
shellf("%s: %s\n", cp, strerror(errno));
rv++;
}
} else
if (*cp == '%')
j_kill(j_lookup(cp), sig);
else
errorf("invalid argument\n");
}
return rv;
}
#ifdef EMACS
int
c_bind(wp)
register char **wp;
{
int macro = 0;
register char *cp;
for (wp++; (cp = *wp) != NULL && *cp == '-'; wp++)
if (cp[1] == 'm')
macro = 1;
if (*wp == NULL) /* list all */
x_bind((char*)NULL, (char*)NULL, 0);
for (; *wp != NULL; wp++) {
cp = strchr(*wp, '=');
if (cp != NULL)
*cp++ = 0;
x_bind(*wp, cp, macro);
}
return 0;
}
int
c_nothing(wp)
register char **wp;
{
return 0;
}
#endif
extern c_fc();
extern c_getopts();
const struct builtin kshbuiltins [] = {
{"cd", c_cd},
{"print", c_print},
{"getopts", c_getopts},
{"=typeset", c_typeset},
{"=export", c_typeset},
{"=readonly", c_typeset},
{"whence", c_whence},
{"=alias", c_alias},
{"unalias", c_unalias},
{"hash", c_hash},
{"let", c_let},
{"fc", c_fc},
{"jobs", c_jobs},
{"kill", c_kill},
{"extproc", c_nothing},
#ifdef JOBS
{"fg", c_fgbg},
{"bg", c_fgbg},
#endif
#ifdef EMACS
{"bind", c_bind},
#endif
{NULL, NULL}
};