/* * Csh - a shell by PJAC * shvars.c - routines that deal with shell variables */ #include "csh.h" extern int status; /* execution status */ struct ik { char *s_name; int s_iflag; }; static struct ik iknow[] = { "echo", L_ECHO, "history", L_HISTORY, "home", L_HOME, "ignoreeof", L_IGNOREEOF, "noglob", L_NOGLOB, "path", L_PATH, "prompt", L_PROMPT, "shell", L_SHELL, "status", L_STATUS, "verbose", L_VERBOSE, 0, 0, }; do_set(argc, argv) char **argv; { struct lvars *lp, *xlp; char lbuf[128]; char *p, *q, **xp; int i; struct ik *ikp; int ind = -1; char *index(); struct lvars *llp; if(argc <= 1){ pr_set(lbuf); return(OK); } /* * first parameter has a equal sign in it, split this parameter up */ if(p = index(argv[1], '=')){ *p++ = 0; if(*p == 0){ free(argv[0]); argv[0] = argv[1]; argv[1] = strsave("="); argv--; ++argc; } } if(argc != 2){ /* set string to a null string */ if(argc < 4 || strcmp(argv[2], "=") != 0) syn_err(); } if(p = index(argv[1], '[')){ if(argc == 2) syn_err(); if(!(q = index(p, ']')) || q[1]) syn_err(); *p++ = 0; if(*p < '0' || *p > '9') syn_err(); ind = atoi(p); } for(llp = 0, lp = Lvars ; lp ; lp = lp->L_next) if((i = strcmp(lp->L_name, argv[1])) == 0) break; else if(i < 0) llp = lp; if(lp == 0){ if(ind != -1){ puterr("Unknown variable.\n"); return(ERR); } if(strcmp(argv[1], "status") == 0) return(OK); lp = (struct lvars *)mmalloc(sizeof(struct lvars)); lp->L_next = 0; if(Lvars == 0) Lvars = lp; else { if(llp == 0){ lp->L_next = Lvars; Lvars = lp; } else if(llp == Lvars){ lp->L_next = Lvars->L_next; Lvars->L_next = lp; } else { lp->L_next = llp->L_next; llp->L_next = lp; } } lp->L_aval = 0; lp->L_name = strsave(argv[1]); lp->L_flags = 0; /* * look up to see if we are setting some well known strings */ for(ikp = iknow; ikp->s_name ; ikp++) if(strcmp(lp->L_name, ikp->s_name) == 0) break; if(ikp->s_name) lp->L_flags = ikp->s_iflag; } if(lp->L_aval){ if(ind != -1){ for(i = 0, xp = lp->L_aval ; *xp ; xp++, i++); if(i < ind || ind == 0) goto memerr; } else { for(xp = lp->L_aval ; *xp ; xp++) free(*xp); free(lp->L_aval); lp->L_aval = 0; } } else if(ind != -1){ memerr:; puterr("Unknown variable member.\n"); return(ERR); } if(argc > 4){ if(ind != -1) syn_err(); if(argc < 6 || *argv[3] != '(' || *argv[argc-1] != ')') syn_err(); lp->L_aval = (char **)mmalloc(sizeof(char *)*(argc - 5 + 1)); xp = argv + 4; for(i = 0 ; i < argc - 5 ; i++) lp->L_aval[i] = strsave(*xp++); lp->L_aval[i] = 0; } else if(argc == 2){ /* give it a null value */ lp->L_aval = (char **)mmalloc(sizeof(char *)); lp->L_aval[0] = 0; } else if(strcmp(argv[3], "(") == 0) /* stop set x = ( */ syn_err(); else { if(ind != -1){ ind--; free(lp->L_aval[ind]); lp->L_aval[ind] = strsave(argv[3]); } else { lp->L_aval = (char **)mmalloc(sizeof(char *)* 2); lp->L_aval[0] = strsave(argv[3]); lp->L_aval[1] = 0; } } if(lp->L_flags) set_svs(lp); /* set shell vars */ return(OK); } /* * doesn't do assignment operators or inc/dec operators */ do_atsign(argc, argv) char **argv; { char lbuf[128]; int res; char *av[5]; if(argc == 1){ pr_set(lbuf); return(OK); } if(argc < 4 || strcmp(argv[2], "=")) syn_err(); if(arg_eval(argc - 3, argv + 3, &res) == ERR) return(ERR); av[0] = 0; av[1] = argv[1]; av[2] = argv[2]; av[3] = my_Itoa(res); av[4] = 0; return(do_set(4, av)); } set_path(xp) char **xp; { char tbuf[128]; char *p, *q; char *av[4]; for(p = tbuf ; (q = *xp++) ; ){ while(*q) *p++ = *q++; if(!*xp) break; #ifdef MSDOS *p++ = ';'; #else *p++ = ':'; #endif } *p = 0; to_fslash(tbuf); /* get all strings to be '/'ed */ to_low(tbuf); if(Path) free(Path); Path = strsave(tbuf); clr_hash(); /* rebuild the hash tables */ bld_hash(); av[1] = "PATH"; av[2] = tbuf; av[3] = 0; do_setenv(3, av); } pr_set(lbuf) char *lbuf; { char *p, **xp; struct lvars *lp; int noval; int seen_status = 0; static char xstatus[] = "status"; for(lp = Lvars ; lp ; lp = lp->L_next){ if(!seen_status && strcmp(lp->L_name, xstatus) >= 0){ seen_status = 1; put_s("status = "); put_s(my_Itoa(status)); put_s("\n"); } noval = 0; switch(lp->L_flags & ~L_SYS){ case L_ECHO: if(in_cshrc && !XVflag) continue; break; case L_VERBOSE: if(in_cshrc && !XVflag) continue; break; case L_IGNOREEOF: case L_NOGLOB: break; default: noval = 1; break; } put_s(lp->L_name); if(noval && lp->L_aval && lp->L_aval[0]){ put_s(" = "); if(lp->L_aval[1]) put_s("( "); for(xp = lp->L_aval ; p = *xp++ ;){ put_s(p); if(*xp) put_s(" "); } if(lp->L_aval[1]) put_s(" )"); } put_s("\n"); } if(!seen_status){ put_s("status = "); put_s(my_Itoa(status)); put_s("\n"); } } do_prtenv(argc, argv) char **argv; { char **xp, *p, *q, *s; char lbuf[128]; for(xp = Real_Environ ; (p = *xp) ; xp++){ q = index(p, '='); if(q == NULL) strcpy(lbuf, p); else { for(s = lbuf ; p < q ; *s++ = *p++); strcpy(s, " = "); strcat(s + 3, q+1); } put_s(lbuf); put_s("\n"); } } do_unset(argc, argv) char **argv; { argc--; argv++; while(*argv) do__unset(*argv++); return(OK); } do__unset(str) char *str; { struct lvars *lp, *xlp; char **xp; for(lp = Lvars ; lp ; lp = lp->L_next) if(strcmp(lp->L_name, str) == 0) break; if(!lp) /* no string with that value */ return; if(lp->L_flags & L_SYS) return; if(lp == Lvars) Lvars = lp->L_next; else { for(xlp = Lvars ; xlp->L_next != lp ; xlp = xlp->L_next); xlp->L_next = lp->L_next; } free(lp->L_name); if(lp->L_aval){ for(xp = lp->L_aval ; *xp ; xp++) free(*xp); free( (char *)lp->L_aval); } switch(lp->L_flags){ case L_ECHO: xflag = 0; break; case L_HISTORY: hist_set(0); break; case L_HOME: HOME[0] = 0; break; case L_IGNOREEOF: igneof = 0; break; case L_NOGLOB: noglob = 0; break; case L_PATH: if(Path) free(Path); Path = 0; break; case L_PROMPT: Prompt[0] = 0; break; case L_SHELL: SHELL[0] = 0; break; case L_VERBOSE: vflag = 0; break; } free( (char *)lp); } /* * called very early on to set up the argv variable, */ set_avl(name, val) char *name, *val; { char *av[1]; av[0] = val; set_avs(name, val ? 1 : 0, av); } set_avs(name, argc, argv) char *name; char **argv; { struct lvars *lp; struct ik *ikp; int i; lp = (struct lvars *)mmalloc(sizeof(struct lvars)); lp->L_next = Lvars; Lvars = lp; lp->L_name = strsave(name); lp->L_flags = 0; for(ikp = iknow; ikp->s_name ; ikp++) if(strcmp(lp->L_name, ikp->s_name) == 0) break; if(ikp->s_name) lp->L_flags = ikp->s_iflag; lp->L_aval = (char **)mmalloc(sizeof(char *)*(argc + 1)); for(i = 0 ; i < argc ; i++) lp->L_aval[i] = strsave(*argv++); lp->L_aval[i] = 0; if(lp->L_flags) set_svs(lp); } set_svs(lp) struct lvars *lp; { char *p; switch(lp->L_flags & ~L_SYS){ case L_ECHO: xflag = 1; break; case L_HISTORY: p = lp->L_aval[0]; if(!p || *p < '0' || *p > '9'){ puterr("History needs a numeric value.\n"); return(ERR); } hist_set(atoi(p)); break; case L_HOME: if(!lp->L_aval[0]) HOME[0] = 0; else strcpy(HOME, lp->L_aval[0]); to_fslash(HOME); to_low(HOME); break; case L_IGNOREEOF: igneof = 1; break; case L_NOGLOB: noglob = 1; break; case L_PATH: set_path(lp->L_aval); break; case L_PROMPT: Prompt[0] = lp->L_aval[0]; break; case L_SHELL: if(!lp->L_aval[0]) SHELL[0] = 0; else strcpy(SHELL, lp->L_aval[0]); to_fslash(SHELL); to_low(SHELL); break; /* case L_STATUS: never called break; */ case L_VERBOSE: vflag = 1; break; } } do_shift(argc, argv) char **argv; { char *p, **xp; struct lvars *lp; if(argc < 2) p = "argv"; else p = argv[1]; for(lp = Lvars ; lp ; lp = lp->L_next) if(strcmp(lp->L_name, p) == 0) break; if(!lp || !lp->L_aval || !lp->L_aval[0]) return(OK); free(lp->L_aval[0]); for(xp = lp->L_aval ; *xp = xp[1] ; xp++); /* do the shift */ return(OK); }