|
|
1.1 ! root 1: /* ! 2: * built-in Korn commands: c_* ! 3: */ ! 4: ! 5: static char *RCSid = "$Header: c_ksh.c,v 3.1 88/11/03 09:14:21 egisin Exp $"; ! 6: ! 7: #include <stddef.h> ! 8: #include <stdlib.h> ! 9: #include <stdio.h> ! 10: #include <string.h> ! 11: #include <errno.h> ! 12: #include <setjmp.h> ! 13: #include <signal.h> ! 14: #include "sh.h" ! 15: #include "table.h" ! 16: ! 17: int ! 18: c_hash(wp) ! 19: register char **wp; ! 20: { ! 21: register int i; ! 22: register struct tbl *tp, **p; ! 23: ! 24: wp++; ! 25: if (*wp == NULL) { ! 26: for (p = tsort(&commands); (tp = *p++) != NULL; ) ! 27: if ((tp->flag&ISSET)) ! 28: printf("%s\n", tp->val.s); ! 29: return 0; ! 30: } ! 31: ! 32: if (strcmp(*wp, "-r") == 0) ! 33: flushcom(1); ! 34: while (*wp != NULL) ! 35: findcom(*wp++, 1); ! 36: return 0; ! 37: } ! 38: ! 39: int ! 40: c_print(wp) ! 41: register char **wp; ! 42: { ! 43: int nl = 1; ! 44: int expand = 1; ! 45: FILE *f = stdout; ! 46: ! 47: for (wp++; *wp != NULL && **wp == '-'; wp++) { ! 48: register char *s = *wp + 1; ! 49: if (*s == '\0') { ! 50: wp++; ! 51: break; ! 52: } ! 53: while (*s) switch (*s++) { ! 54: case 'n': ! 55: nl = 0; ! 56: break; ! 57: case 'e': ! 58: expand = 1; ! 59: break; ! 60: case 'r': ! 61: expand = 0; ! 62: break; ! 63: case 'u': ! 64: if (!digit(*s) || (f = shf[*s++-'0']) == NULL) ! 65: errorf("bad -u argument\n"); ! 66: break; ! 67: } ! 68: } ! 69: ! 70: while (*wp != NULL) { ! 71: register char *s = *wp; ! 72: register int c; ! 73: while ((c = *s++) != '\0') ! 74: if (expand && c == '\\') { ! 75: switch ((c = *s++)) { ! 76: case 'b': c = '\b'; break; ! 77: case 'c': nl = 0; continue; /* AT&T brain damage */ ! 78: case 'f': c = '\f'; break; ! 79: case 'n': c = '\n'; break; ! 80: case 'r': c = '\r'; break; ! 81: case 't': c = '\t'; break; ! 82: case 'v': c = 0x0B; break; ! 83: case '0': case '1': case '2': case '3': ! 84: case '4': case '5': case '6': case '7': ! 85: c = c - '0'; ! 86: if (*s >= '0' && *s <= '7') ! 87: c = 8*c + *s++ - '0'; ! 88: if (*s >= '0' && *s <= '7') ! 89: c = 8*c + *s++ - '0'; ! 90: break; ! 91: case '\\': break; ! 92: default: ! 93: putc('\\', f); ! 94: } ! 95: putc(c, f); ! 96: } else ! 97: putc(c, f); ! 98: if (*++wp != NULL) ! 99: putc(' ', f); ! 100: } ! 101: if (nl) ! 102: putc('\n', f); ! 103: return 0; ! 104: } ! 105: ! 106: /* todo: handle case where id is both lexical and command */ ! 107: int ! 108: c_whence(wp) ! 109: register char **wp; ! 110: { ! 111: register struct tbl *tp; ! 112: char *id; ! 113: int vflag = 0; ! 114: ! 115: for (wp++; (id = *wp) != NULL && *id == '-'; wp++) ! 116: if (id[1] == 'v') ! 117: vflag = 1; ! 118: ! 119: while ((id = *wp++) != NULL) { ! 120: tp = tsearch(&lexicals, id, hash(id)); ! 121: if (tp == NULL) ! 122: tp = findcom(id, 1); ! 123: if (vflag) ! 124: switch ((tp == NULL) ? CNONE : tp->type) { ! 125: case CNONE: ! 126: printf("%s is unknown\n", id); ! 127: break; ! 128: case CSHELL: ! 129: printf("%s is a shell builtin\n", id); ! 130: break; ! 131: case CFUNC: ! 132: printf("%s is a function\n", id); ! 133: fptreef(stdout, "function %s %T\n", id, tp->val.t); ! 134: break; ! 135: case CEXEC: ! 136: printf("%s is %s\n", id, ! 137: (tp->flag&ISSET) ? tp->val.s : "unknown"); ! 138: break; ! 139: case CALIAS: ! 140: printf("%s is the alias '%s'\n", id, tp->val.s); ! 141: break; ! 142: case CKEYWD: ! 143: printf("%s is a shell keyword\n", id); ! 144: break; ! 145: default: ! 146: printf("%s is *GOK*\n", id); ! 147: break; ! 148: } ! 149: else ! 150: switch ((tp == NULL) ? CNONE : tp->type) { ! 151: case CNONE: ! 152: printf("\n"); ! 153: break; ! 154: case CSHELL: ! 155: printf("builtin %s\n", id); ! 156: break; ! 157: case CFUNC: ! 158: printf("%s\n", id); ! 159: break; ! 160: case CEXEC: ! 161: printf("%s\n", (tp->flag&ISSET) ? tp->val.s : id); ! 162: break; ! 163: case CALIAS: ! 164: printf("%s\n", tp->val.s); ! 165: break; ! 166: case CKEYWD: ! 167: printf("%s\n", id); ! 168: break; ! 169: default: ! 170: printf("*GOK*\n"); ! 171: break; ! 172: } ! 173: } ! 174: return 0; ! 175: } ! 176: ! 177: int ! 178: c_typeset(wp) ! 179: register char **wp; ! 180: { ! 181: register char *id; ! 182: struct block *l = e.loc; ! 183: register struct tbl *vp, **p; ! 184: int fset = 0, fclr = 0; ! 185: int thing = 0, func = 0; ! 186: ! 187: for (wp++; (id = *wp) != NULL && (*id == '-' || *id == '+'); wp++) { ! 188: int flag = 0; ! 189: thing = *id; ! 190: while (*++id != '\0') switch (*id) { ! 191: case 'f': ! 192: flag |= FUNCT; ! 193: func = 1; ! 194: break; ! 195: case 'i': ! 196: flag |= INTEGER; ! 197: break; ! 198: case 'r': ! 199: flag |= RDONLY; ! 200: break; ! 201: case 'x': ! 202: flag |= EXPORT; ! 203: break; ! 204: case 't': ! 205: flag |= TRACE; ! 206: break; ! 207: default: ! 208: errorf("unknown flag -%c\n", *id); ! 209: } ! 210: if (flag != 0) { /* + or - with options */ ! 211: if (thing == '-') ! 212: fset |= flag; ! 213: else ! 214: fclr |= flag; ! 215: thing = 0; ! 216: } ! 217: } ! 218: ! 219: /* list variables and attributes */ ! 220: if (*wp == NULL) { ! 221: for (l = e.loc; l != NULL; l = l->next) { ! 222: for (p = tsort((func==0) ? &l->vars : &l->funs); ! 223: (vp = *p++) != NULL; ) ! 224: if ((vp->flag&ISSET)) ! 225: if (thing == 0 && fclr == 0 && fset == 0) { ! 226: printf("typeset "); ! 227: if ((vp->flag&INTEGER)) ! 228: printf("-i "); ! 229: if ((vp->flag&EXPORT)) ! 230: printf("-x "); ! 231: if ((vp->flag&RDONLY)) ! 232: printf("-r "); ! 233: if ((vp->flag&TRACE)) ! 234: printf("-t "); ! 235: printf("%s\n", vp->name); ! 236: } else ! 237: if (thing == '+' || ! 238: fclr && (vp->flag&fclr) == fclr) { ! 239: printf("%s\n", vp->name); ! 240: } else ! 241: if (thing == '-' || ! 242: fset && (vp->flag&fset) == fset) { ! 243: if (fset&FUNCT) ! 244: printf("function %s\n", vp->name); ! 245: else ! 246: printf("%s=%s\n", vp->name, strval(vp)); ! 247: } ! 248: } ! 249: return (0); ! 250: } ! 251: ! 252: fset |= LOCAL; ! 253: for (; *wp != NULL; wp++) ! 254: #if 0 ! 255: if (func) { ! 256: } else ! 257: #endif ! 258: if (typeset(*wp, fset, fclr) == NULL) ! 259: errorf("%s: not identifier\n", *wp); ! 260: return 0; ! 261: } ! 262: ! 263: int ! 264: c_alias(wp) ! 265: register char **wp; ! 266: { ! 267: register struct table *t = &lexicals; ! 268: register struct tbl *ap, **p; ! 269: register int i; ! 270: int rv = 0; ! 271: ! 272: if (*++wp != NULL && strcmp(*wp, "-d") == 0) { ! 273: t = &homedirs; ! 274: wp++; ! 275: } ! 276: ! 277: if (*wp == NULL) ! 278: for (p = tsort(t); (ap = *p++) != NULL; ) ! 279: if (ap->type == CALIAS && (ap->flag&DEFINED)) ! 280: printf("%s='%s'\n", ap->name, ap->val.s); ! 281: ! 282: for (; *wp != NULL; wp++) { ! 283: register char *id = *wp; ! 284: register char *val = strchr(id, '='); ! 285: ! 286: if (val == NULL) { ! 287: ap = tsearch(t, id, hash(id)); ! 288: if (ap != NULL && ap->type == CALIAS && (ap->flag&DEFINED)) ! 289: printf("%s='%s'\n", ap->name, ap->val.s); ! 290: else ! 291: rv = 1; ! 292: } else { ! 293: *val++ = '\0'; ! 294: ap = tenter(t, id, hash(id)); ! 295: if (ap->type == CKEYWD) ! 296: errorf("cannot alias keyword\n"); ! 297: if ((ap->flag&ALLOC)) { ! 298: afree((Void*)ap->val.s, APERM); ! 299: ap->flag &=~ ALLOC|ISSET; ! 300: } ! 301: ap->type = CALIAS; ! 302: ap->val.s = strsave(val, APERM); ! 303: ap->flag |= DEFINED|ALLOC|ISSET; ! 304: } ! 305: } ! 306: return rv; ! 307: } ! 308: ! 309: int ! 310: c_unalias(wp) ! 311: register char **wp; ! 312: { ! 313: register struct table *t = &lexicals; ! 314: register struct tbl *ap; ! 315: ! 316: if (*++wp != NULL && strcmp(*wp, "-d") == 0) { ! 317: t = &homedirs; ! 318: wp++; ! 319: } ! 320: ! 321: for (; *wp != NULL; wp++) { ! 322: ap = tsearch(t, *wp, hash(*wp)); ! 323: if (ap == NULL || ap->type != CALIAS) ! 324: continue; ! 325: if ((ap->flag&ALLOC)) ! 326: afree((Void*)ap->val.s, APERM); ! 327: ap->flag &=~ DEFINED|ISSET|ALLOC; ! 328: } ! 329: return 0; ! 330: } ! 331: ! 332: int ! 333: c_let(wp) ! 334: char **wp; ! 335: { ! 336: int rv = 1; ! 337: ! 338: for (wp++; *wp; wp++) ! 339: rv = evaluate(*wp) == 0; ! 340: return rv; ! 341: } ! 342: ! 343: int ! 344: c_jobs(wp) ! 345: char **wp; ! 346: { ! 347: j_jobs(); ! 348: return 0; ! 349: } ! 350: ! 351: #if JOBS ! 352: int ! 353: c_fgbg(wp) ! 354: register char **wp; ! 355: { ! 356: int bg = strcmp(*wp, "bg") == 0; ! 357: ! 358: if (!flag[FMONITOR]) ! 359: errorf("Job control not enabled\n"); ! 360: wp++; ! 361: j_resume(j_lookup((*wp == NULL) ? "%" : *wp), bg); ! 362: return 0; ! 363: } ! 364: #endif ! 365: ! 366: int ! 367: c_kill(wp) ! 368: register char **wp; ! 369: { ! 370: register char *cp; ! 371: int sig = SIGTERM; ! 372: int rv = 0; ! 373: ! 374: if (*++wp == NULL) ! 375: errorf("Usage: kill [-l] [-signal] {pid|job} ...\n"); ! 376: if (strcmp(*wp, "-l") == 0) { ! 377: register struct trap *p = sigtraps; ! 378: for (sig = 0; sig < SIGNALS; sig++, p++) ! 379: if (p->signal) ! 380: printf("%2d %8s %s\n", p->signal, p->name, p->mess); ! 381: return 0; ! 382: } ! 383: ! 384: for (; (cp = *wp) != NULL; wp++) ! 385: if (*cp == '-' || isalpha(*cp)) { ! 386: struct trap *p; ! 387: p = gettrap((*cp == '-') ? cp+1 : cp); ! 388: if (p == NULL) ! 389: errorf("bad signal %s\n", ! 390: (*cp == '-') ? cp+1 : cp); ! 391: sig = p->signal; ! 392: } else if (digit(*cp)) { ! 393: if (kill(atoi(cp), sig) < 0) { ! 394: shellf("%s: %s\n", cp, strerror(errno)); ! 395: rv++; ! 396: } ! 397: } else if (*cp == '%') ! 398: j_kill(j_lookup(cp), sig); ! 399: else ! 400: errorf("invalid argument\n"); ! 401: return rv; ! 402: } ! 403: ! 404: int ! 405: c_bind(wp) ! 406: register char **wp; ! 407: { ! 408: int macro = 0; ! 409: register char *cp; ! 410: ! 411: for (wp++; (cp = *wp) != NULL && *cp == '-'; wp++) ! 412: if (cp[1] == 'm') ! 413: macro = 1; ! 414: ! 415: if (*wp == NULL) /* list all */ ! 416: x_bind((char*)NULL, (char*)NULL, 0); ! 417: ! 418: for (; *wp != NULL; wp++) { ! 419: cp = strchr(*wp, '='); ! 420: if (cp != NULL) ! 421: *cp++ = 0; ! 422: x_bind(*wp, cp, macro); ! 423: } ! 424: ! 425: return 0; ! 426: } ! 427: ! 428: extern c_fc(); ! 429: extern c_getopts(); ! 430: ! 431: Const struct builtin kshbuiltins [] = { ! 432: {"print", c_print}, ! 433: {"getopts", c_getopts}, ! 434: {"=typeset", c_typeset}, ! 435: {"whence", c_whence}, ! 436: {"alias", c_alias}, ! 437: {"unalias", c_unalias}, ! 438: {"hash", c_hash}, ! 439: {"let", c_let}, ! 440: {"fc", c_fc}, ! 441: {"jobs", c_jobs}, ! 442: {"kill", c_kill}, ! 443: #if JOBS ! 444: {"fg", c_fgbg}, ! 445: {"bg", c_fgbg}, ! 446: #endif ! 447: #if EDIT ! 448: {"bind", c_bind}, ! 449: #endif ! 450: {NULL, NULL} ! 451: }; ! 452:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.