/* * Handle the multitudinous $ expansion forms. * Ugh. */ static void Dgetdol(void) { Char *np; struct varent *vp = NULL; Char name[4 * MAXVARLEN + 1]; int c, sc; int subscr = 0, lwb = 1, upb = 0; bool dimen = 0, bitset = 0; char tnp; Char wbuf[BUFSIZ]; static Char *dolbang = NULL; dolnmod = dolmcnt = dolwcnt = 0; c = sc = DgetC(0); if (c == '{') c = DgetC(0); /* sc is { to take } later */ if ((c & TRIM) == '#') dimen++, c = DgetC(0); /* $# takes dimension */ else if (c == '?') bitset++, c = DgetC(0); /* $? tests existence */ switch (c) { case '!': if (dimen || bitset) stderror(ERR_SYNTAX); if (backpid != 0) { if (dolbang) xfree(dolbang); setDolp(dolbang = putn(backpid)); } goto eatbrac; case '$': if (dimen || bitset) stderror(ERR_SYNTAX); setDolp(doldol); goto eatbrac; case '<' | QUOTE: if (bitset) stderror(ERR_NOTALLOWED, "$?<"); if (dimen) stderror(ERR_NOTALLOWED, "$?#"); for (np = wbuf; read(OLDSTD, &tnp, 1) == 1; np++) { *np = (unsigned char) tnp; if (np >= &wbuf[BUFSIZ - 1]) stderror(ERR_LTOOLONG); if (tnp == '\n') break; } *np = 0; /* * KLUDGE: dolmod is set here because it will cause setDolp to call * domod and thus to copy wbuf. Otherwise setDolp would use it * directly. If we saved it ourselves, no one would know when to free * it. The actual function of the 'q' causes filename expansion not to * be done on the interpolated value. */ dolmod[dolnmod++] = 'q'; dolmcnt = 10000; setDolp(wbuf); goto eatbrac; case DEOF: case '\n': stderror(ERR_SYNTAX); /* NOTREACHED */ break; case '*': (void) Strlcpy(name, STRargv, sizeof name/sizeof(Char)); vp = adrof(STRargv); subscr = -1; /* Prevent eating [...] */ break; default: np = name; if (Isdigit(c)) { if (dimen) stderror(ERR_NOTALLOWED, "$#<num>"); subscr = 0; do { subscr = subscr * 10 + c - '0'; c = DgetC(0); } while (Isdigit(c)); unDredc(c); if (subscr < 0) stderror(ERR_RANGE); if (subscr == 0) { if (bitset) { dolp = ffile ? STR1 : STR0; goto eatbrac; } if (ffile == 0) stderror(ERR_DOLZERO); fixDolMod(); setDolp(ffile); goto eatbrac; } if (bitset) stderror(ERR_DOLQUEST); vp = adrof(STRargv); if (vp == 0) { vp = &nulargv; goto eatmod; } break; } if (!alnum(c)) stderror(ERR_VARALNUM); for (;;) { *np++ = c; c = DgetC(0); if (!alnum(c)) break; if (np >= &name[MAXVARLEN]) stderror(ERR_VARTOOLONG); } *np++ = 0; unDredc(c); vp = adrof(name); } if (bitset) { dolp = (vp || getenv(short2str(name))) ? STR1 : STR0; goto eatbrac; } if (vp == 0) { np = str2short(getenv(short2str(name))); if (np) { fixDolMod(); setDolp(np); goto eatbrac; } udvar(name); /* NOTREACHED */ } c = DgetC(0); upb = blklen(vp->vec); if (dimen == 0 && subscr == 0 && c == '[') { np = name; for (;;) { c = DgetC(DODOL); /* Allow $ expand within [ ] */ if (c == ']') break; if (c == '\n' || c == DEOF) stderror(ERR_INCBR); if (np >= &name[sizeof(name) / sizeof(Char) - 2]) stderror(ERR_VARTOOLONG); *np++ = c; } *np = 0, np = name; if (dolp || dolcnt) /* $ exp must end before ] */ stderror(ERR_EXPORD); if (!*np) stderror(ERR_SYNTAX); if (Isdigit(*np)) { int i; for (i = 0; Isdigit(*np); i = i * 10 + *np++ - '0') continue; if ((i < 0 || i > upb) && !any("-*", *np)) { dolerror(vp->v_name); return; } lwb = i; if (!*np) upb = lwb, np = STRstar; } if (*np == '*') np++; else if (*np != '-') stderror(ERR_MISSING, '-'); else { int i = upb; np++; if (Isdigit(*np)) { i = 0; while (Isdigit(*np)) i = i * 10 + *np++ - '0'; if (i < 0 || i > upb) { dolerror(vp->v_name); return; } } if (i < lwb) upb = lwb - 1; else upb = i; } if (lwb == 0) { if (upb != 0) { dolerror(vp->v_name); return; } upb = -1; } if (*np) stderror(ERR_SYNTAX); } else { if (subscr > 0) { if (subscr > upb) lwb = 1, upb = 0; else lwb = upb = subscr; } unDredc(c); } if (dimen) { Char *cp = putn(upb - lwb + 1); addla(cp); xfree(cp); } else { eatmod: fixDolMod(); dolnxt = &vp->vec[lwb - 1]; dolcnt = upb - lwb + 1; } eatbrac: if (sc == '{') { c = Dredc(); if (c != '}') stderror(ERR_MISSING, '}'); } }
/* * dcanon - canonicalize the pathname, removing excess ./ and ../ etc. * we are of course assuming that the file system is standardly * constructed (always have ..'s, directories have links) */ Char * dcanon(Char *cp, Char *p) { Char *sp; Char *p1, *p2; /* general purpose */ bool slash; Char link[PATH_MAX]; char tlink[PATH_MAX]; int cc; Char *newcp; /* * christos: if the path given does not start with a slash prepend cwd. If * cwd does not start with a path or the result would be too long abort(). */ if (*cp != '/') { Char tmpdir[PATH_MAX]; p1 = value(STRcwd); if (p1 == NULL || *p1 != '/') abort(); if (Strlen(p1) + Strlen(cp) + 1 >= PATH_MAX) abort(); (void) Strlcpy(tmpdir, p1, sizeof tmpdir/sizeof(Char)); (void) Strlcat(tmpdir, STRslash, sizeof tmpdir/sizeof(Char)); (void) Strlcat(tmpdir, cp, sizeof tmpdir/sizeof(Char)); free(cp); cp = p = Strsave(tmpdir); } while (*p) { /* for each component */ sp = p; /* save slash address */ while (*++p == '/') /* flush extra slashes */ continue; if (p != ++sp) for (p1 = sp, p2 = p; (*p1++ = *p2++) != '\0';) continue; p = sp; /* save start of component */ slash = 0; while (*p) /* find next slash or end of path */ if (*++p == '/') { slash = 1; *p = 0; break; } if (*sp == '\0') /* if component is null */ if (--sp == cp) /* if path is one char (i.e. /) */ break; else *sp = '\0'; else if (sp[0] == '.' && sp[1] == 0) { if (slash) { for (p1 = sp, p2 = p + 1; (*p1++ = *p2++) != '\0';) continue; p = --sp; } else if (--sp != cp) *sp = '\0'; } else if (sp[0] == '.' && sp[1] == '.' && sp[2] == 0) { /* * We have something like "yyy/xxx/..", where "yyy" can be null or * a path starting at /, and "xxx" is a single component. Before * compressing "xxx/..", we want to expand "yyy/xxx", if it is a * symbolic link. */ *--sp = 0; /* form the pathname for readlink */ if (sp != cp && !adrof(STRignore_symlinks) && (cc = readlink(short2str(cp), tlink, sizeof tlink-1)) >= 0) { tlink[cc] = '\0'; (void) Strlcpy(link, str2short(tlink), sizeof link/sizeof(Char)); if (slash) *p = '/'; /* * Point p to the '/' in "/..", and restore the '/'. */ *(p = sp) = '/'; /* * find length of p */ for (p1 = p; *p1++;) continue; if (*link != '/') { /* * Relative path, expand it between the "yyy/" and the * "/..". First, back sp up to the character past "yyy/". */ while (*--sp != '/') continue; sp++; *sp = 0; /* * New length is "yyy/" + link + "/.." and rest */ p1 = newcp = xreallocarray(NULL, (sp - cp) + cc + (p1 - p), sizeof(Char)); /* * Copy new path into newcp */ for (p2 = cp; (*p1++ = *p2++) != '\0';) continue; for (p1--, p2 = link; (*p1++ = *p2++) != '\0';) continue; for (p1--, p2 = p; (*p1++ = *p2++) != '\0';) continue; /* * Restart canonicalization at expanded "/xxx". */ p = sp - cp - 1 + newcp; } else { /* * New length is link + "/.." and rest */ p1 = newcp = xreallocarray(NULL, cc + (p1 - p), sizeof(Char)); /* * Copy new path into newcp */ for (p2 = link; (*p1++ = *p2++) != '\0';) continue; for (p1--, p2 = p; (*p1++ = *p2++) != '\0';) continue; /* * Restart canonicalization at beginning */ p = newcp; } free(cp); cp = newcp; continue; /* canonicalize the link */ } *sp = '/'; if (sp != cp) while (*--sp != '/') continue; if (slash) { for (p1 = sp + 1, p2 = p + 1; (*p1++ = *p2++) != '\0';) continue; p = sp; } else if (cp == sp) *++sp = '\0'; else *sp = '\0'; } else { /* normal dir name (not . or .. or nothing) */ if (sp != cp && adrof(STRchase_symlinks) && !adrof(STRignore_symlinks) && (cc = readlink(short2str(cp), tlink, sizeof tlink-1)) >= 0) { tlink[cc] = '\0'; (void) Strlcpy(link, str2short(tlink), sizeof link/sizeof(Char)); /* * restore the '/'. */ if (slash) *p = '/'; /* * point sp to p (rather than backing up). */ sp = p; /* * find length of p */ for (p1 = p; *p1++;) continue; if (*link != '/') { /* * Relative path, expand it between the "yyy/" and the * remainder. First, back sp up to the character past * "yyy/". */ while (*--sp != '/') continue; sp++; *sp = 0; /* * New length is "yyy/" + link + "/.." and rest */ p1 = newcp = xreallocarray(NULL, (sp - cp) + cc + (p1 - p), sizeof(Char)); /* * Copy new path into newcp */ for (p2 = cp; (*p1++ = *p2++) != '\0';) continue; for (p1--, p2 = link; (*p1++ = *p2++) != '\0';) continue; for (p1--, p2 = p; (*p1++ = *p2++) != '\0';) continue; /* * Restart canonicalization at expanded "/xxx". */ p = sp - cp - 1 + newcp; } else { /* * New length is link + the rest */ p1 = newcp = xreallocarray(NULL, cc + (p1 - p), sizeof(Char)); /* * Copy new path into newcp */ for (p2 = link; (*p1++ = *p2++) != '\0';) continue; for (p1--, p2 = p; (*p1++ = *p2++) != '\0';) continue; /* * Restart canonicalization at beginning */ p = newcp; } free(cp); cp = newcp; continue; /* canonicalize the link */ } if (slash) *p = '/'; } } /* * fix home... */ p1 = value(STRhome); cc = Strlen(p1); /* * See if we're not in a subdir of STRhome */ if (p1 && *p1 == '/' && (Strncmp(p1, cp, cc) != 0 || (cp[cc] != '/' && cp[cc] != '\0'))) { static ino_t home_ino = -1; static dev_t home_dev = -1; static Char *home_ptr = NULL; struct stat statbuf; /* * Get dev and ino of STRhome */ if (home_ptr != p1 && stat(short2str(p1), &statbuf) != -1) { home_dev = statbuf.st_dev; home_ino = statbuf.st_ino; home_ptr = p1; } /* * Start comparing dev & ino backwards */ Strlcpy(link, cp, sizeof link/sizeof(Char)); p2 = link; for (sp = NULL; *p2 && stat(short2str(p2), &statbuf) != -1;) { if (statbuf.st_dev == home_dev && statbuf.st_ino == home_ino) { sp = (Char *) - 1; break; } if ((sp = Strrchr(p2, '/')) != NULL) *sp = '\0'; } /* * See if we found it */ if (*p2 && sp == (Char *) -1) { /* * Use STRhome to make '~' work */ newcp = Strspl(p1, cp + Strlen(p2)); free(cp); cp = newcp; } } return cp; }
/* * Handle the multitudinous $ expansion forms. * Ugh. */ static void Dgetdol(void) { Char *np; struct varent *vp = NULL; struct Strbuf *name = Strbuf_alloc(); eChar c, sc; int subscr = 0, lwb = 1, upb = 0; int dimen = 0, bitset = 0, length = 0; static Char *dolbang = NULL; cleanup_push(name, Strbuf_free); dolmod.len = dolmcnt = dol_flag_a = 0; c = sc = DgetC(0); if (c == DEOF) { stderror(ERR_SYNTAX); return; } if (c == '{') c = DgetC(0); /* sc is { to take } later */ if ((c & TRIM) == '#') dimen++, c = DgetC(0); /* $# takes dimension */ else if (c == '?') bitset++, c = DgetC(0); /* $? tests existence */ else if (c == '%') length++, c = DgetC(0); /* $% returns length in chars */ switch (c) { case '!': if (dimen || bitset || length) stderror(ERR_SYNTAX); if (backpid != 0) { xfree(dolbang); setDolp(dolbang = putn((tcsh_number_t)backpid)); } cleanup_until(name); goto eatbrac; case '$': if (dimen || bitset || length) stderror(ERR_SYNTAX); setDolp(doldol); cleanup_until(name); goto eatbrac; case '<'|QUOTE: { static struct Strbuf wbuf; /* = Strbuf_INIT; */ if (bitset) stderror(ERR_NOTALLOWED, "$?<"); if (dimen) stderror(ERR_NOTALLOWED, "$#<"); if (length) stderror(ERR_NOTALLOWED, "$%<"); wbuf.len = 0; { char cbuf[MB_LEN_MAX]; size_t cbp = 0; int old_pintr_disabled; for (;;) { int len; ssize_t res; Char wc; pintr_push_enable(&old_pintr_disabled); res = force_read(OLDSTD, cbuf + cbp, 1); cleanup_until(&old_pintr_disabled); if (res != 1) break; cbp++; len = normal_mbtowc(&wc, cbuf, cbp); if (len == -1) { reset_mbtowc(); if (cbp < MB_LEN_MAX) continue; /* Maybe a partial character */ wc = (unsigned char)*cbuf | INVALID_BYTE; } if (len <= 0) len = 1; if (cbp != (size_t)len) memmove(cbuf, cbuf + len, cbp - len); cbp -= len; if (wc == '\n') break; Strbuf_append1(&wbuf, wc); } while (cbp != 0) { int len; Char wc; len = normal_mbtowc(&wc, cbuf, cbp); if (len == -1) { reset_mbtowc(); wc = (unsigned char)*cbuf | INVALID_BYTE; } if (len <= 0) len = 1; if (cbp != (size_t)len) memmove(cbuf, cbuf + len, cbp - len); cbp -= len; if (wc == '\n') break; Strbuf_append1(&wbuf, wc); } Strbuf_terminate(&wbuf); } fixDolMod(); setDolp(wbuf.s); /* Kept allocated until next $< expansion */ cleanup_until(name); goto eatbrac; } case '*': Strbuf_append(name, STRargv); Strbuf_terminate(name); vp = adrof(STRargv); subscr = -1; /* Prevent eating [...] */ break; case DEOF: case '\n': np = dimen ? STRargv : (bitset ? STRstatus : NULL); if (np) { bitset = 0; Strbuf_append(name, np); Strbuf_terminate(name); vp = adrof(np); subscr = -1; /* Prevent eating [...] */ unDredc(c); break; } else stderror(ERR_SYNTAX); /*NOTREACHED*/ default: if (Isdigit(c)) { if (dimen) stderror(ERR_NOTALLOWED, "$#<num>"); subscr = 0; do { subscr = subscr * 10 + c - '0'; c = DgetC(0); } while (c != DEOF && Isdigit(c)); unDredc(c); if (subscr < 0) stderror(ERR_RANGE); if (subscr == 0) { if (bitset) { dolp = dolzero ? STR1 : STR0; cleanup_until(name); goto eatbrac; } if (ffile == 0) stderror(ERR_DOLZERO); if (length) { length = Strlen(ffile); addla(putn((tcsh_number_t)length)); } else { fixDolMod(); setDolp(ffile); } cleanup_until(name); goto eatbrac; } #if 0 if (bitset) stderror(ERR_NOTALLOWED, "$?<num>"); if (length) stderror(ERR_NOTALLOWED, "$%<num>"); #endif vp = adrof(STRargv); if (vp == 0) { vp = &nulargv; cleanup_until(name); goto eatmod; } break; } if (c == DEOF || !alnum(c)) { np = dimen ? STRargv : (bitset ? STRstatus : NULL); if (np) { bitset = 0; Strbuf_append(name, np); Strbuf_terminate(name); vp = adrof(np); subscr = -1; /* Prevent eating [...] */ unDredc(c); break; } else stderror(ERR_VARALNUM); } for (;;) { Strbuf_append1(name, (Char) c); c = DgetC(0); if (c == DEOF || !alnum(c)) break; } Strbuf_terminate(name); unDredc(c); vp = adrof(name->s); } if (bitset) { dolp = (vp || getenv(short2str(name->s))) ? STR1 : STR0; cleanup_until(name); goto eatbrac; } if (vp == NULL || vp->vec == NULL) { np = str2short(getenv(short2str(name->s))); if (np) { static Char *env_val; /* = NULL; */ cleanup_until(name); fixDolMod(); if (length) { addla(putn((tcsh_number_t)Strlen(np))); } else { xfree(env_val); env_val = Strsave(np); setDolp(env_val); } goto eatbrac; } udvar(name->s); /* NOTREACHED */ } cleanup_until(name); c = DgetC(0); upb = blklen(vp->vec); if (dimen == 0 && subscr == 0 && c == '[') { name = Strbuf_alloc(); cleanup_push(name, Strbuf_free); np = name->s; for (;;) { c = DgetC(DODOL); /* Allow $ expand within [ ] */ if (c == ']') break; if (c == '\n' || c == DEOF) stderror(ERR_INCBR); Strbuf_append1(name, (Char) c); } Strbuf_terminate(name); np = name->s; if (dolp || dolcnt) /* $ exp must end before ] */ stderror(ERR_EXPORD); if (!*np) stderror(ERR_SYNTAX); if (Isdigit(*np)) { int i; for (i = 0; Isdigit(*np); i = i * 10 + *np++ - '0') continue; if (i < 0 || (i > upb && !any("-*", *np))) { cleanup_until(name); dolerror(vp->v_name); return; } lwb = i; if (!*np) upb = lwb, np = STRstar; } if (*np == '*') np++; else if (*np != '-') stderror(ERR_MISSING, '-'); else { int i = upb; np++; if (Isdigit(*np)) { i = 0; while (Isdigit(*np)) i = i * 10 + *np++ - '0'; if (i < 0 || i > upb) { cleanup_until(name); dolerror(vp->v_name); return; } } if (i < lwb) upb = lwb - 1; else upb = i; } if (lwb == 0) { if (upb != 0) { cleanup_until(name); dolerror(vp->v_name); return; } upb = -1; } if (*np) stderror(ERR_SYNTAX); cleanup_until(name); } else { if (subscr > 0) { if (subscr > upb) lwb = 1, upb = 0; else lwb = upb = subscr; } unDredc(c); } if (dimen) { /* this is a kludge. It prevents Dgetdol() from */ /* pushing erroneous ${#<error> values into the labuf. */ if (sc == '{') { c = Dredc(); if (c != '}') stderror(ERR_MISSING, '}'); unDredc(c); } addla(putn((tcsh_number_t)(upb - lwb + 1))); } else if (length) { int i; for (i = lwb - 1, length = 0; i < upb; i++) length += Strlen(vp->vec[i]); #ifdef notdef /* We don't want that, since we can always compute it by adding $#xxx */ length += i - 1; /* Add the number of spaces in */ #endif addla(putn((tcsh_number_t)length)); } else { eatmod: fixDolMod(); dolnxt = &vp->vec[lwb - 1]; dolcnt = upb - lwb + 1; } eatbrac: if (sc == '{') { c = Dredc(); if (c != '}') stderror(ERR_MISSING, '}'); } }
int main(int argc, char *argv[]) { struct sigaction oact; Char *cp; char *tcp, **tempv; const char *ecp; sigset_t nsigset; int f; cshin = stdin; cshout = stdout; csherr = stderr; setprogname(argv[0]); settimes(); /* Immed. estab. timing base */ /* * Initialize non constant strings */ #ifdef _PATH_BSHELL STR_BSHELL = SAVE(_PATH_BSHELL); #endif #ifdef _PATH_CSHELL STR_SHELLPATH = SAVE(_PATH_CSHELL); #endif STR_environ = blk2short(environ); environ = short2blk(STR_environ); /* So that we can free it */ STR_WORD_CHARS = SAVE(WORD_CHARS); HIST = '!'; HISTSUB = '^'; word_chars = STR_WORD_CHARS; tempv = argv; if (eq(str2short(tempv[0]), STRaout)) /* A.out's are quittable */ quitit = 1; uid = getuid(); gid = getgid(); euid = geteuid(); egid = getegid(); /* * We are a login shell if: 1. we were invoked as -<something> and we had * no arguments 2. or we were invoked only with the -l flag */ loginsh = (**tempv == '-' && argc == 1) || (argc == 2 && tempv[1][0] == '-' && tempv[1][1] == 'l' && tempv[1][2] == '\0'); if (loginsh && **tempv != '-') { /* * Mangle the argv space */ tempv[1][0] = '\0'; tempv[1][1] = '\0'; tempv[1] = NULL; for (tcp = *tempv; *tcp++;) continue; for (tcp--; tcp >= *tempv; tcp--) tcp[1] = tcp[0]; *++tcp = '-'; argc--; } if (loginsh) (void)time(&chktim); AsciiOnly = 1; #ifdef NLS (void)setlocale(LC_ALL, ""); { int k; for (k = 0200; k <= 0377 && !Isprint(k); k++) continue; AsciiOnly = k > 0377; } #else AsciiOnly = getenv("LANG") == NULL && getenv("LC_CTYPE") == NULL; #endif /* NLS */ /* * Move the descriptors to safe places. The variable didfds is 0 while we * have only FSH* to work with. When didfds is true, we have 0,1,2 and * prefer to use these. */ initdesc(); /* * XXX: This is to keep programs that use stdio happy. * what we really want is freunopen() .... * Closing cshin cshout and csherr (which are really stdin stdout * and stderr at this point and then reopening them in the same order * gives us again stdin == cshin stdout == cshout and stderr == csherr. * If that was not the case builtins like printf that use stdio * would break. But in any case we could fix that with memcpy and * a bit of pointer manipulation... * Fortunately this is not needed under the current implementation * of stdio. */ (void)fclose(cshin); (void)fclose(cshout); (void)fclose(csherr); if (!(cshin = funopen((void *) &SHIN, readf, writef, seekf, closef))) exit(1); if (!(cshout = funopen((void *) &SHOUT, readf, writef, seekf, closef))) exit(1); if (!(csherr = funopen((void *) &SHERR, readf, writef, seekf, closef))) exit(1); (void)setvbuf(cshin, NULL, _IOLBF, 0); (void)setvbuf(cshout, NULL, _IOLBF, 0); (void)setvbuf(csherr, NULL, _IOLBF, 0); /* * Initialize the shell variables. ARGV and PROMPT are initialized later. * STATUS is also munged in several places. CHILD is munged when * forking/waiting */ set(STRstatus, Strsave(STR0)); if ((ecp = getenv("HOME")) != NULL) cp = quote(SAVE(ecp)); else cp = NULL; if (cp == NULL) fast = 1; /* No home -> can't read scripts */ else set(STRhome, cp); dinit(cp); /* dinit thinks that HOME == cwd in a login * shell */ /* * Grab other useful things from the environment. Should we grab * everything?? */ if ((ecp = getenv("LOGNAME")) != NULL || (ecp = getenv("USER")) != NULL) set(STRuser, quote(SAVE(ecp))); if ((ecp = getenv("TERM")) != NULL) set(STRterm, quote(SAVE(ecp))); /* * Re-initialize path if set in environment */ if ((ecp = getenv("PATH")) == NULL) { #ifdef _PATH_DEFPATH importpath(str2short(_PATH_DEFPATH)); #else setq(STRpath, defaultpath(), &shvhed); #endif } else { importpath(str2short(ecp)); } set(STRshell, Strsave(STR_SHELLPATH)); doldol = putn((int) getpid()); /* For $$ */ shtemp = Strspl(STRtmpsh, doldol); /* For << */ /* * Record the interrupt states from the parent process. If the parent is * non-interruptible our hand must be forced or we (and our children) won't * be either. Our children inherit termination from our parent. We catch it * only if we are the login shell. */ /* parents interruptibility */ (void)sigaction(SIGINT, NULL, &oact); parintr = oact.sa_handler; (void)sigaction(SIGTERM, NULL, &oact); parterm = oact.sa_handler; /* catch these all, login shell or not */ (void)signal(SIGHUP, phup); /* exit processing on HUP */ (void)signal(SIGXCPU, phup); /* ...and on XCPU */ (void)signal(SIGXFSZ, phup); /* ...and on XFSZ */ /* * Process the arguments. * * Note that processing of -v/-x is actually delayed till after script * processing. * * We set the first character of our name to be '-' if we are a shell * running interruptible commands. Many programs which examine ps'es * use this to filter such shells out. */ argc--, tempv++; while (argc > 0 && (tcp = tempv[0])[0] == '-' && *++tcp != '\0' && !batch) { do switch (*tcp++) { case 0: /* - Interruptible, no prompt */ prompt = 0; setintr = 1; nofile = 1; break; case 'b': /* -b Next arg is input file */ batch = 1; break; case 'c': /* -c Command input from arg */ if (argc == 1) xexit(0); argc--, tempv++; arginp = SAVE(tempv[0]); prompt = 0; nofile = 1; break; case 'e': /* -e Exit on any error */ exiterr = 1; break; case 'f': /* -f Fast start */ fast = 1; break; case 'i': /* -i Interactive, even if !intty */ intact = 1; nofile = 1; break; case 'm': /* -m read .cshrc (from su) */ mflag = 1; break; case 'n': /* -n Don't execute */ noexec = 1; break; case 'q': /* -q (Undoc'd) ... die on quit */ quitit = 1; break; case 's': /* -s Read from std input */ nofile = 1; break; case 't': /* -t Read one line from input */ onelflg = 2; prompt = 0; nofile = 1; break; case 'v': /* -v Echo hist expanded input */ nverbose = 1; /* ... later */ break; case 'x': /* -x Echo just before execution */ nexececho = 1; /* ... later */ break; case 'V': /* -V Echo hist expanded input */ setNS(STRverbose); /* NOW! */ break; case 'X': /* -X Echo just before execution */ setNS(STRecho); /* NOW! */ break; } while (*tcp); tempv++, argc--; } if (quitit) /* With all due haste, for debugging */ (void)signal(SIGQUIT, SIG_DFL); /* * Unless prevented by -, -c, -i, -s, or -t, if there are remaining * arguments the first of them is the name of a shell file from which to * read commands. */ if (nofile == 0 && argc > 0) { nofile = open(tempv[0], O_RDONLY); if (nofile < 0) { child = 1; /* So this doesn't return */ stderror(ERR_SYSTEM, tempv[0], strerror(errno)); } ffile = SAVE(tempv[0]); /* * Replace FSHIN. Handle /dev/std{in,out,err} specially * since once they are closed we cannot open them again. * In that case we use our own saved descriptors */ if ((SHIN = dmove(nofile, FSHIN)) < 0) switch(nofile) { case 0: SHIN = FSHIN; break; case 1: SHIN = FSHOUT; break; case 2: SHIN = FSHERR; break; default: stderror(ERR_SYSTEM, tempv[0], strerror(errno)); /* NOTREACHED */ } (void)ioctl(SHIN, FIOCLEX, NULL); prompt = 0; /* argc not used any more */ tempv++; } intty = isatty(SHIN); intty |= intact; if (intty || (intact && isatty(SHOUT))) { if (!batch && (uid != euid || gid != egid)) { errno = EACCES; child = 1; /* So this doesn't return */ stderror(ERR_SYSTEM, "csh", strerror(errno)); } } /* * Decide whether we should play with signals or not. If we are explicitly * told (via -i, or -) or we are a login shell (arg0 starts with -) or the * input and output are both the ttys("csh", or "csh</dev/ttyx>/dev/ttyx") * Note that in only the login shell is it likely that parent may have set * signals to be ignored */ if (loginsh || intact || (intty && isatty(SHOUT))) setintr = 1; settell(); /* * Save the remaining arguments in argv. */ setq(STRargv, blk2short(tempv), &shvhed); /* * Set up the prompt. */ if (prompt) { set(STRprompt, Strsave(uid == 0 ? STRsymhash : STRsymcent)); /* that's a meta-questionmark */ set(STRprompt2, Strsave(STRmquestion)); } /* * If we are an interactive shell, then start fiddling with the signals; * this is a tricky game. */ shpgrp = getpgrp(); opgrp = tpgrp = -1; if (setintr) { **argv = '-'; if (!quitit) /* Wary! */ (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGINT, pintr); sigemptyset(&nsigset); (void)sigaddset(&nsigset, SIGINT); (void)sigprocmask(SIG_BLOCK, &nsigset, NULL); (void)signal(SIGTERM, SIG_IGN); if (quitit == 0 && arginp == 0) { (void)signal(SIGTSTP, SIG_IGN); (void)signal(SIGTTIN, SIG_IGN); (void)signal(SIGTTOU, SIG_IGN); /* * Wait till in foreground, in case someone stupidly runs csh & * dont want to try to grab away the tty. */ if (isatty(FSHERR)) f = FSHERR; else if (isatty(FSHOUT)) f = FSHOUT; else if (isatty(OLDSTD)) f = OLDSTD; else f = -1; retry: if ((tpgrp = tcgetpgrp(f)) != -1) { if (tpgrp != shpgrp) { sig_t old = signal(SIGTTIN, SIG_DFL); (void)kill(0, SIGTTIN); (void)signal(SIGTTIN, old); goto retry; } opgrp = shpgrp; shpgrp = getpid(); tpgrp = shpgrp; /* * Setpgid will fail if we are a session leader and * mypid == mypgrp (POSIX 4.3.3) */ if (opgrp != shpgrp) if (setpgid(0, shpgrp) == -1) goto notty; /* * We do that after we set our process group, to make sure * that the process group belongs to a process in the same * session as the tty (our process and our group) (POSIX 7.2.4) */ if (tcsetpgrp(f, shpgrp) == -1) goto notty; (void)ioctl(dcopy(f, FSHTTY), FIOCLEX, NULL); } if (tpgrp == -1) { notty: (void)fprintf(csherr, "Warning: no access to tty (%s).\n", strerror(errno)); (void)fprintf(csherr, "Thus no job control in this shell.\n"); } } } if ((setintr == 0) && (parintr == SIG_DFL)) setintr = 1; (void)signal(SIGCHLD, pchild); /* while signals not ready */ /* * Set an exit here in case of an interrupt or error reading the shell * start-up scripts. */ reenter = setexit(); /* PWP */ haderr = 0; /* In case second time through */ if (!fast && reenter == 0) { /* Will have value(STRhome) here because set fast if don't */ { sig_t oparintr; sigset_t osigset; int osetintr; oparintr = parintr; osetintr = setintr; sigemptyset(&nsigset); (void)sigaddset(&nsigset, SIGINT); (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); setintr = 0; parintr = SIG_IGN; /* Disable onintr */ #ifdef _PATH_DOTCSHRC (void)srcfile(_PATH_DOTCSHRC, 0, 0); #endif if (!fast && !arginp && !onelflg) dohash(NULL, NULL); #ifdef _PATH_DOTLOGIN if (loginsh) (void)srcfile(_PATH_DOTLOGIN, 0, 0); #endif (void)sigprocmask(SIG_SETMASK, &osigset, NULL); setintr = osetintr; parintr = oparintr; } (void)srccat(value(STRhome), STRsldotcshrc); if (!fast && !arginp && !onelflg && !havhash) dohash(NULL, NULL); /* * Source history before .login so that it is available in .login */ if ((cp = value(STRhistfile)) != STRNULL) loadhist[2] = cp; dosource(loadhist, NULL); if (loginsh) (void)srccat(value(STRhome), STRsldotlogin); } /* * Now are ready for the -v and -x flags */ if (nverbose) setNS(STRverbose); if (nexececho) setNS(STRecho); /* * All the rest of the world is inside this call. The argument to process * indicates whether it should catch "error unwinds". Thus if we are a * interactive shell our call here will never return by being blown past on * an error. */ process(setintr); /* * Mop-up. */ if (intty) { if (loginsh) { (void)fprintf(cshout, "logout\n"); (void)close(SHIN); child = 1; goodbye(); } else { (void)fprintf(cshout, "exit\n"); } } rechist(); exitstat(); /* NOTREACHED */ }
/* * dcanon - canonicalize the pathname, removing excess ./ and ../ etc. * we are of course assuming that the file system is standardly * constructed (always have ..'s, directories have links) */ Char * dcanon(Char *cp, Char *p) { Char *sp; Char *p1, *p2; /* general purpose */ int slash; #ifdef HAVE_SLASHSLASH int slashslash; #endif /* HAVE_SLASHSLASH */ size_t clen; #ifdef S_IFLNK /* if we have symlinks */ Char *mlink, *newcp; char *tlink; size_t cc; #endif /* S_IFLNK */ clen = Strlen(cp); /* * christos: if the path given does not start with a slash prepend cwd. If * cwd does not start with a slash or the result would be too long try to * correct it. */ if (!ABSOLUTEP(cp)) { Char *tmpdir; size_t len; p1 = varval(STRcwd); if (p1 == STRNULL || !ABSOLUTEP(p1)) { Char *new_cwd = agetcwd(); if (new_cwd == NULL) { xprintf("%s: %s\n", progname, strerror(errno)); setcopy(STRcwd, str2short("/"), VAR_READWRITE|VAR_NOGLOB); } else setv(STRcwd, new_cwd, VAR_READWRITE|VAR_NOGLOB); p1 = varval(STRcwd); } len = Strlen(p1); tmpdir = xmalloc((len + clen + 2) * sizeof (*tmpdir)); (void) Strcpy(tmpdir, p1); (void) Strcat(tmpdir, STRslash); (void) Strcat(tmpdir, cp); xfree(cp); cp = p = tmpdir; } #ifdef HAVE_SLASHSLASH slashslash = (cp[0] == '/' && cp[1] == '/'); #endif /* HAVE_SLASHSLASH */ while (*p) { /* for each component */ sp = p; /* save slash address */ while (*++p == '/') /* flush extra slashes */ continue; if (p != ++sp) for (p1 = sp, p2 = p; (*p1++ = *p2++) != '\0';) continue; p = sp; /* save start of component */ slash = 0; if (*p) while (*++p) /* find next slash or end of path */ if (*p == '/') { slash = 1; *p = 0; break; } #ifdef HAVE_SLASHSLASH if (&cp[1] == sp && sp[0] == '.' && sp[1] == '.' && sp[2] == '\0') slashslash = 1; #endif /* HAVE_SLASHSLASH */ if (*sp == '\0') { /* if component is null */ if (--sp == cp) /* if path is one char (i.e. /) */ break; else *sp = '\0'; } else if (sp[0] == '.' && sp[1] == 0) { if (slash) { for (p1 = sp, p2 = p + 1; (*p1++ = *p2++) != '\0';) continue; p = --sp; } else if (--sp != cp) *sp = '\0'; else sp[1] = '\0'; } else if (sp[0] == '.' && sp[1] == '.' && sp[2] == 0) { /* * We have something like "yyy/xxx/..", where "yyy" can be null or * a path starting at /, and "xxx" is a single component. Before * compressing "xxx/..", we want to expand "yyy/xxx", if it is a * symbolic link. */ *--sp = 0; /* form the pathname for readlink */ #ifdef S_IFLNK /* if we have symlinks */ if (sp != cp && /* symlinks != SYM_IGNORE && */ (tlink = areadlink(short2str(cp))) != NULL) { mlink = str2short(tlink); xfree(tlink); if (slash) *p = '/'; /* * Point p to the '/' in "/..", and restore the '/'. */ *(p = sp) = '/'; if (*mlink != '/') { /* * Relative path, expand it between the "yyy/" and the * "/..". First, back sp up to the character past "yyy/". */ while (*--sp != '/') continue; sp++; *sp = 0; /* * New length is "yyy/" + mlink + "/.." and rest */ p1 = newcp = xmalloc(((sp - cp) + Strlen(mlink) + Strlen(p) + 1) * sizeof(Char)); /* * Copy new path into newcp */ for (p2 = cp; (*p1++ = *p2++) != '\0';) continue; for (p1--, p2 = mlink; (*p1++ = *p2++) != '\0';) continue; for (p1--, p2 = p; (*p1++ = *p2++) != '\0';) continue; /* * Restart canonicalization at expanded "/xxx". */ p = sp - cp - 1 + newcp; } else { newcp = Strspl(mlink, p); /* * Restart canonicalization at beginning */ p = newcp; } xfree(cp); cp = newcp; #ifdef HAVE_SLASHSLASH slashslash = (cp[0] == '/' && cp[1] == '/'); #endif /* HAVE_SLASHSLASH */ continue; /* canonicalize the link */ } #endif /* S_IFLNK */ *sp = '/'; if (sp != cp) while (*--sp != '/') continue; if (slash) { for (p1 = sp + 1, p2 = p + 1; (*p1++ = *p2++) != '\0';) continue; p = sp; } else if (cp == sp) *++sp = '\0'; else *sp = '\0'; } else { /* normal dir name (not . or .. or nothing) */ #ifdef S_IFLNK /* if we have symlinks */ if (sp != cp && symlinks == SYM_CHASE && (tlink = areadlink(short2str(cp))) != NULL) { mlink = str2short(tlink); xfree(tlink); /* * restore the '/'. */ if (slash) *p = '/'; /* * point sp to p (rather than backing up). */ sp = p; if (*mlink != '/') { /* * Relative path, expand it between the "yyy/" and the * remainder. First, back sp up to the character past * "yyy/". */ while (*--sp != '/') continue; sp++; *sp = 0; /* * New length is "yyy/" + mlink + "/.." and rest */ p1 = newcp = xmalloc(((sp - cp) + Strlen(mlink) + Strlen(p) + 1) * sizeof(Char)); /* * Copy new path into newcp */ for (p2 = cp; (*p1++ = *p2++) != '\0';) continue; for (p1--, p2 = mlink; (*p1++ = *p2++) != '\0';) continue; for (p1--, p2 = p; (*p1++ = *p2++) != '\0';) continue; /* * Restart canonicalization at expanded "/xxx". */ p = sp - cp - 1 + newcp; } else { newcp = Strspl(mlink, p); /* * Restart canonicalization at beginning */ p = newcp; } xfree(cp); cp = newcp; #ifdef HAVE_SLASHSLASH slashslash = (cp[0] == '/' && cp[1] == '/'); #endif /* HAVE_SLASHSLASH */ continue; /* canonicalize the mlink */ } #endif /* S_IFLNK */ if (slash) *p = '/'; } } /* * fix home... */ #ifdef S_IFLNK p1 = varval(STRhome); cc = Strlen(p1); /* * See if we're not in a subdir of STRhome */ if (p1 && *p1 == '/' && (Strncmp(p1, cp, cc) != 0 || (cp[cc] != '/' && cp[cc] != '\0'))) { static ino_t home_ino = (ino_t) -1; static dev_t home_dev = (dev_t) -1; static Char *home_ptr = NULL; struct stat statbuf; int found; Char *copy; /* * Get dev and ino of STRhome */ if (home_ptr != p1 && stat(short2str(p1), &statbuf) != -1) { home_dev = statbuf.st_dev; home_ino = statbuf.st_ino; home_ptr = p1; } /* * Start comparing dev & ino backwards */ p2 = copy = Strsave(cp); found = 0; while (*p2 && stat(short2str(p2), &statbuf) != -1) { if (DEV_DEV_COMPARE(statbuf.st_dev, home_dev) && statbuf.st_ino == home_ino) { found = 1; break; } if ((sp = Strrchr(p2, '/')) != NULL) *sp = '\0'; } /* * See if we found it */ if (*p2 && found) { /* * Use STRhome to make '~' work */ newcp = Strspl(p1, cp + Strlen(p2)); xfree(cp); cp = newcp; } xfree(copy); } #endif /* S_IFLNK */ #ifdef HAVE_SLASHSLASH if (slashslash) { if (cp[1] != '/') { p = xmalloc((Strlen(cp) + 2) * sizeof(Char)); *p = '/'; (void) Strcpy(&p[1], cp); xfree(cp); cp = p; } } if (cp[1] == '/' && cp[2] == '/') { for (p1 = &cp[1], p2 = &cp[2]; (*p1++ = *p2++) != '\0';) continue; } #endif /* HAVE_SLASHSLASH */ return cp; }
/*ARGSUSED*/ void dosched(Char **v, struct command *c) { struct sched_event *tp, **pp; time_t cur_time; int count, hours, minutes, dif_hour, dif_min; Char *cp; int relative; /* time specified as +hh:mm */ struct tm *ltp; USE(c); /* This is a major kludge because of a gcc linker */ /* Problem. It may or may not be needed for you */ #if defined(_MINIX) && !defined(_MINIX_VMD) char kludge[10]; extern char *sprintf(); sprintf(kludge, CGETS(24, 1, "kludge")); #endif /* _MINIX && !_MINIX_VMD */ v++; cp = *v++; if (cp == NULL) { const Char *fmt; if ((fmt = varval(STRsched)) == STRNULL) fmt = str2short("%h\t%T\t%R\n"); /* print list of scheduled events */ for (count = 1, tp = sched_ptr; tp; count++, tp = tp->t_next) { Char *buf, *str; buf = blkexpand(tp->t_lex); cleanup_push(buf, xfree); str = tprintf(FMT_SCHED, fmt, short2str(buf), tp->t_when, &count); cleanup_until(buf); cleanup_push(str, xfree); for (cp = str; *cp;) xputwchar(*cp++); cleanup_until(str); } return; } if (*cp == '-') { /* remove item from list */ if (!sched_ptr) stderror(ERR_NOSCHED); if (*v) stderror(ERR_SCHEDUSAGE); count = atoi(short2str(++cp)); if (count <= 0) stderror(ERR_SCHEDUSAGE); pp = &sched_ptr; tp = sched_ptr; while (--count) { if (tp->t_next == 0) break; else { pp = &tp->t_next; tp = tp->t_next; } } if (count) stderror(ERR_SCHEDEV); *pp = tp->t_next; blkfree(tp->t_lex); xfree(tp); return; } /* else, add an item to the list */ if (!*v) stderror(ERR_SCHEDCOM); relative = 0; if (!Isdigit(*cp)) { /* not abs. time */ if (*cp != '+') stderror(ERR_SCHEDUSAGE); cp++, relative++; } minutes = 0; hours = atoi(short2str(cp)); while (*cp && *cp != ':' && *cp != 'a' && *cp != 'p') cp++; if (*cp && *cp == ':') minutes = atoi(short2str(++cp)); if ((hours < 0) || (minutes < 0) || (hours > 23) || (minutes > 59)) stderror(ERR_SCHEDTIME); while (*cp && *cp != 'p' && *cp != 'a') cp++; if (*cp && relative) stderror(ERR_SCHEDREL); if (*cp == 'p') hours += 12; (void) time(&cur_time); ltp = localtime(&cur_time); if (relative) { dif_hour = hours; dif_min = minutes; } else { if ((dif_hour = hours - ltp->tm_hour) < 0) dif_hour += 24; if ((dif_min = minutes - ltp->tm_min) < 0) { dif_min += 60; if ((--dif_hour) < 0) dif_hour = 23; } } tp = xcalloc(1, sizeof *tp); #ifdef _SX tp->t_when = cur_time - ltp->tm_sec + dif_hour * 3600 + dif_min * 60; #else /* _SX */ tp->t_when = cur_time - ltp->tm_sec + dif_hour * 3600L + dif_min * 60L; #endif /* _SX */ /* use of tm_sec: get to beginning of minute. */ for (pp = &sched_ptr; *pp != NULL && tp->t_when >= (*pp)->t_when; pp = &(*pp)->t_next) ; tp->t_next = *pp; *pp = tp; tp->t_lex = saveblk(v); }
/*ARGSUSED*/ void dosetpath(Char **arglist, struct command *c) { extern char *getenv(); Char **pathvars, **cmdargs; char **spaths, **cpaths, **cmds; char *tcp; unsigned int npaths, ncmds; int i, sysflag; pintr_disabled++; cleanup_push(&pintr_disabled, disabled_cleanup); /* * setpath(3) uses stdio and we want 0, 1, 2 to work... */ if (!didfds) { (void) dcopy(SHIN, 0); (void) dcopy(SHOUT, 1); (void) dcopy(SHDIAG, 2); didfds = 1; } for (i = 1; arglist[i] && (arglist[i][0] != '-'); i++); npaths = i - 1; cmdargs = &arglist[i]; for (; arglist[i]; i++); ncmds = i - npaths - 1; if (npaths) { sysflag = 0; pathvars = &arglist[1]; } else { sysflag = 1; npaths = (sizeof syspaths / sizeof *syspaths) - 1; pathvars = syspaths; } /* note that npaths != 0 */ spaths = xmalloc(npaths * sizeof *spaths); setzero(spaths, npaths * sizeof *spaths); cpaths = xmalloc((npaths + 1) * sizeof *cpaths); setzero(cpaths, (npaths + 1) * sizeof *cpaths); cmds = xmalloc((ncmds + 1) * sizeof *cmds); setzero(cmds, (ncmds + 1) * sizeof *cmds); for (i = 0; i < npaths; i++) { char *val = getenv(short2str(pathvars[i])); if (val == NULL) val = ""; spaths[i] = xmalloc((Strlen(pathvars[i]) + strlen(val) + 2) * sizeof **spaths); (void) strcpy(spaths[i], short2str(pathvars[i])); (void) strcat(spaths[i], "="); (void) strcat(spaths[i], val); cpaths[i] = spaths[i]; } for (i = 0; i < ncmds; i++) { Char *val = globone(cmdargs[i], G_ERROR);/*FIXRESET*/ if (val == NULL) goto abortpath; cmds[i] = strsave(short2str(val)); } if (setpath(cpaths, cmds, LOCALSYSPATH, sysflag, 1) < 0) { abortpath: if (spaths) { for (i = 0; i < npaths; i++) xfree(spaths[i]); xfree(spaths); } xfree(cpaths); if (cmds) { for (i = 0; i < ncmds; i++) xfree(cmds[i]); xfree(cmds); } cleanup_until(&pintr_disabled); donefds(); return; } for (i = 0; i < npaths; i++) { Char *val, *name; name = str2short(cpaths[i]); for (val = str2short(cpaths[i]); val && *val && *val != '='; val++); if (val && *val == '=') { *val++ = '\0'; tsetenv(name, val);/*FIXRESET*/ if (Strcmp(name, STRKPATH) == 0) { importpath(val);/*FIXRESET*/ if (havhash) dohash(NULL, NULL);/*FIXRESET*/ } *--val = '='; } } cleanup_until(&pintr_disabled); donefds(); }
static int tellmewhat(struct wordent *lexp, Char *str, int len) { int i; struct biltins *bptr; struct wordent *sp = lexp->next; bool aliased = 0, found; Char *s0, *s1, *s2, *cmd; Char qc; if (adrof1(sp->word, &aliases)) { alias(lexp); sp = lexp->next; aliased = 1; } s0 = sp->word; /* to get the memory freeing right... */ /* handle quoted alias hack */ if ((*(sp->word) & (QUOTE | TRIM)) == QUOTE) (sp->word)++; /* do quoting, if it hasn't been done */ s1 = s2 = sp->word; while (*s2) switch (*s2) { case '\'': case '"': qc = *s2++; while (*s2 && *s2 != qc) *s1++ = *s2++ | QUOTE; if (*s2) s2++; break; case '\\': if (*++s2) *s1++ = *s2++ | QUOTE; break; default: *s1++ = *s2++; } *s1 = '\0'; for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) { if (eq(sp->word, str2short(bptr->bname))) { if (str == NULL) { if (aliased) prlex(cshout, lexp); (void) fprintf(cshout, "%s: shell built-in command.\n", vis_str(sp->word)); } else (void) Strlcpy(str, sp->word, len/sizeof(Char)); sp->word = s0; /* we save and then restore this */ return 1; } } sp->word = cmd = globone(sp->word, G_IGNORE); if ((i = iscommand(sp->word)) != 0) { Char **pv; struct varent *v; bool slash = any(short2str(sp->word), '/'); v = adrof(STRpath); if (v == 0 || v->vec[0] == 0 || slash) pv = justabs; else pv = v->vec; while (--i) pv++; if (pv[0][0] == 0 || eq(pv[0], STRdot)) { if (!slash) { sp->word = Strspl(STRdotsl, sp->word); prlex(cshout, lexp); xfree(sp->word); } else prlex(cshout, lexp); } else { s1 = Strspl(*pv, STRslash); sp->word = Strspl(s1, sp->word); xfree(s1); if (str == NULL) prlex(cshout, lexp); else (void) Strlcpy(str, sp->word, len/sizeof(Char)); xfree(sp->word); } found = 1; } else { if (str == NULL) { if (aliased) prlex(cshout, lexp); (void) fprintf(csherr, "%s: Command not found.\n", vis_str(sp->word)); } else (void) Strlcpy(str, sp->word, len/sizeof(Char)); found = 0; } sp->word = s0; /* we save and then restore this */ xfree(cmd); return found; }
void getmachine (void) { char temp[256]; char *vendor, *ostype; OSVERSIONINFO osver; SYSTEM_INFO sysinfo; memset(&osver,0,sizeof(osver)); memset(&sysinfo,0,sizeof(sysinfo)); vendor = "Microsoft"; tsetenv(STRVENDOR,str2short(vendor)); osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (!GetVersionEx(&osver)) { MessageBox(NULL,"GetVersionEx failed in getmachine", "tcsh",MB_ICONHAND); ExitProcess(0xFF); } GetSystemInfo(&sysinfo); if(osver.dwPlatformId == VER_PLATFORM_WIN32_NT) { char *ostr; switch(osver.dwMajorVersion) { case 5: switch (osver.dwMinorVersion) { case 0: ostype = "Windows2000"; ostr = "Windows 2000"; break; case 1: ostype = "WindowsXP"; ostr = "Windows XP"; break; case 2: ostype = "WindowsServer2003"; ostr = "Windows Server 2003"; break; default: ostype = "Windows-Post-2000"; ostr = "Windows Post Windows-2000"; } break; default: ostype = "WindowsNT"; ostr = "Windows NT"; } wsprintf(temp,"%s %d.%d Build %d (%s)", ostr, osver.dwMajorVersion,osver.dwMinorVersion, osver.dwBuildNumber, osver.szCSDVersion[0]?osver.szCSDVersion:""); tsetenv(STRHOSTTYPE,str2short(temp)); } else if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { ostype = "Windows9x"; wsprintf(temp,"Win9x %d.%d:%d",osver.dwMajorVersion,osver.dwMinorVersion, LOWORD(osver.dwBuildNumber)); tsetenv(STRHOSTTYPE,str2short(temp)); } else { MessageBox(NULL,"Unknown platform","tcsh",MB_ICONHAND); } tsetenv(STROSTYPE,str2short(ostype)); switch (sysinfo.wProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_INTEL: if ( ( sysinfo.wProcessorLevel < 3) || ( sysinfo.wProcessorLevel > 9) ) sysinfo.wProcessorLevel = 3; wsprintf(temp,"i%d86",sysinfo.wProcessorLevel); break; case PROCESSOR_ARCHITECTURE_ALPHA: wsprintf(temp,"Alpha"); break; case PROCESSOR_ARCHITECTURE_MIPS: wsprintf(temp,"Mips"); break; case PROCESSOR_ARCHITECTURE_PPC: wsprintf(temp,"PPC"); break; default: wsprintf(temp,"Unknown"); break; } tsetenv(STRMACHTYPE,str2short(temp)); }