home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / ssh-1.7 / part02 / vars.c < prev   
Encoding:
C/C++ Source or Header  |  1993-04-15  |  20.4 KB  |  928 lines

  1. /* $Copyright:    $
  2.  * Copyright (c) 1991,1992,1993 by Steve Baker
  3.  * All rights reserved
  4.  *  
  5.  * This software is provided as is without any express or implied
  6.  * warranties, including, without limitation, the implied warranties
  7.  * of merchantability and fitness for a particular purpose.
  8.  */
  9. #include "shell.h"
  10.  
  11. char *malloc(), *strcpy();
  12. char numbuf[10];
  13. extern struct _setvar *sets[37];
  14. extern char **PATH, **_mbox, newmail, *_home, **_mailnotice, **_homedirs, **_cdpath;
  15. extern char _insert, *_prompt, *_statline, **history, _noassigns, *_term[11];
  16. extern char _echo, _verbose, _glob, _notypeahead, _nonomatch, _noclobber;
  17. extern int _maxhist, curhist, _joblimit, _failat, _mailchkint, _statint;
  18. extern char _nodots, _restricted, _nohup, _nobgnull, buf[1025], path[1025];
  19. extern struct timeval *_timeout, timeout;
  20. extern int a,b,c,d;
  21.  
  22. char **evalw(), *getvalidenv(), *string(), *UPPER();
  23. struct _setvar *getvalidset(), *getset(), *find_var(), *add_var();
  24.  
  25. enum {
  26.   VAR_CDPATH, VAR_CWD, VAR_ECHO, VAR_FAILAT, VAR_HISTORY, VAR_HOME,
  27.   VAR_HOMEDIRS, VAR_INSERT, VAR_JOBLIMIT, VAR_MAIL, VAR_MAILCHKINT,
  28.   VAR_MAILNOTICE, VAR_NOBGNULL, VAR_NOCLOBBER, VAR_NOGLOB, VAR_NONOMATCH,
  29.   VAR_NOTYPEAHEAD, VAR_PATH, VAR_PROMPT, VAR_STATINT, VAR_STATLINE, VAR_TERM,
  30.   VAR_TIMEOUT, VAR_USER, VAR_VERBOSE, VAR_NOASSIGNS, VAR_RESTRICTED,
  31.   VAR_NODOTS, VAR_NOHUP
  32. };
  33.  
  34. #define hash(x)    (isalpha(x)? (x & 31) + 10 : isdigit(x)? x - '0' : x == '_' ? 10 : -1)
  35.  
  36. /*
  37.  *  Parse our shell vars here...
  38.  */
  39.  
  40. char ***parse_shellvars(arg)
  41. char ***arg;
  42. {
  43.   int i;
  44.   char **evalvars();
  45.  
  46.   for(i=0;arg[i];i++)
  47.     arg[i] = evalvars(arg[i]);
  48.  
  49.   return arg;
  50. }
  51.  
  52. char **evalvars(w)
  53. char **w;
  54. {
  55.   char **tmp, **etmp;
  56.   int i,j,nst,nt,wrd;
  57.  
  58.   tmp = (char **)calloc(nt=5,sizeof(char *));
  59.  
  60.   wrd = nst = 0;
  61.   for(i=0;w[i];i++) {
  62.     if (w[i][0] == '(' && !w[i][1]) nst++;
  63.     if (w[i][0] == ')' && !w[i][1]) nst -= (nst?1:0);
  64.  
  65.     if (nst) {
  66.       if (wrd == nt) tmp = (char **)realloc(tmp,sizeof(char *) * (nt+=5));
  67.       tmp[wrd++] = w[i];
  68.     } else {
  69.       etmp = evalw(w[i]);
  70.       for(j=0;etmp[j];j++) {
  71.     if (wrd == nt) tmp = (char **)realloc(tmp,sizeof(char *) * (nt+=5));
  72.     tmp[wrd++] = etmp[j];
  73.       }
  74.       if (w[i] != etmp[0]) free(w[i]);
  75.       free(etmp);
  76.     }
  77.   }
  78.   if (wrd == nt) tmp = (char **)realloc(tmp,sizeof(char *) * (++nt));
  79.   tmp[wrd] = NULL;
  80.   free(w);
  81.   return tmp;
  82. }
  83.  
  84. /*
  85.     String/Numeric vars: $        Environment vars: $$
  86.     var  var[x]  ?var  ?var[x]  #var  #var[x]
  87.     {var}  {var[x]}  ?{var}  ?{var[x]}  #{var}  #{var[x]}
  88. */
  89.  
  90. char **evalw(wrd)
  91. char *wrd;
  92. {
  93.   struct _setvar *SET;
  94.   char **etmp, **tmp, *w;
  95.   int i,j,z,nt,bp,tp,pos;
  96.  
  97.   tp = pos = bp = 0;
  98.  
  99.   tmp = (char **)calloc(nt = 2,sizeof(char *));
  100.   if (*wrd == '\'' || !index(wrd,'$')) {
  101.     tmp[0] = wrd;
  102.     tmp[1] = NULL;
  103.     return tmp;
  104.   }
  105.   while(*wrd) {
  106.     switch(*wrd++) {
  107.       case '$':
  108.     if (*wrd == '$') {
  109.       if (*++wrd == '?') {
  110.         ++wrd;
  111.         w = getvalidenv(&wrd,&pos);
  112.         if (w) buf[bp++] = '1';
  113.         else buf[bp++] = '0';
  114.         free(w);
  115.         break;
  116.       }
  117.       if (*wrd == '#') {
  118.         wrd++;
  119.         i = 0;
  120.         w = getvalidenv(&wrd,&pos);
  121.         if (w) {
  122.           if (pos < 0) {
  123.         for(i=1,j=0;w[j];j++) if (w[j] == ':') i++;
  124.           } else i = strlen(w);
  125.         }
  126.         sprintf(path,"%d",i);
  127.         for(i=0;path[i];i++) buf[bp++] = path[i];
  128.         break;
  129.       }
  130.       w = getvalidenv(&wrd,&pos);
  131.       while (*w) buf[bp++] = *w++;
  132.       free(w);
  133.       break;
  134.     }
  135.     if (*wrd == '<') {
  136.       wrd++;
  137.       fgets(path,1024,stdin);
  138.       for(i=0;path[i] != '\n';i++) buf[bp++] = path[i];
  139.       break;
  140.     }
  141.     if (*wrd == '?') {
  142.       wrd++;
  143.       if (SET = getvalidset(&wrd,&pos)) buf[bp++] = SET->type + '1';
  144.       else buf[bp++] = '0';
  145.       break;
  146.     }
  147.     if (*wrd == '#') {
  148.       wrd++;
  149.       if (SET = getvalidset(&wrd,&pos)) {
  150.         if (pos < 0) i = SET->nwrds;
  151.         else i = strlen(SET->sv.wrd[pos]);
  152.       } else i = 0;
  153.       sprintf(path,"%d",i);
  154.       for(i=0;path[i];i++) buf[bp++] = path[i];
  155.       break;
  156.     }
  157.     SET = getvalidset(&wrd,&pos);
  158.     if (!SET) break;
  159.     if (SET->type == T_INTEGER) {
  160.       sprintf(numbuf,"%d",SET->sv.val);
  161.       for(i=0;numbuf[i];i++) buf[bp++] = numbuf[i];
  162.     } else if (SET->type == T_STRING && pos < 0) {
  163.       buf[bp] = 0;
  164.       w = (char *)strcpy((char *)malloc(bp+1),buf);
  165.       etmp = evalw(wrd);
  166.       for(i=0;SET->sv.wrd[i];i++) {
  167.         for(z=0;etmp[z];z++) {
  168.           if (tp == nt) tmp = (char **)realloc(tmp,sizeof(char *) * (nt+=5));
  169.           tmp[tp] = (char *)malloc(strlen(SET->sv.wrd[i])+bp+strlen(etmp[z])+2);
  170.           sprintf(tmp[tp++],"%s%s%s",w,SET->sv.wrd[i],etmp[z]);
  171.         }
  172.       }
  173.       free_list(etmp);
  174.       free(w);
  175.       if (tp == nt) tmp = (char **)realloc(tmp,sizeof(char *) * (nt+=1));
  176.       tmp[tp] = NULL;
  177.       return tmp;
  178.     } else if (SET->type == T_STRING) {
  179.       for(j=0;SET->sv.wrd[pos][j];j++) buf[bp++] = SET->sv.wrd[pos][j];
  180.     }
  181.     break;
  182.       case '\\':
  183.     buf[bp++] = *wrd++;
  184.     break;
  185.       default:
  186.     buf[bp++] = *(wrd-1);
  187.     break;
  188.     }
  189.   }
  190.   buf[bp] = 0;
  191.   if (tp >= (nt-1)) tmp = (char **)realloc(tmp,sizeof(char *) * (nt+=2));
  192.   tmp[tp++] = (char *)strcpy((char *)malloc(bp+1),buf);
  193.   tmp[tp] = NULL;
  194.   return tmp;
  195. }
  196.  
  197. struct _setvar *getvalidset(wrd,pos)
  198. char **wrd;
  199. int *pos;
  200. {
  201.   struct _setvar *SET;
  202.  
  203.   if (**wrd == '{') {
  204.     (*wrd)++;
  205.     SET = getset(wrd,pos);
  206.     if (**wrd == '}') (*wrd)++;
  207.   } else SET = getset(wrd,pos);
  208.   return SET;
  209. }
  210.  
  211. char *getvalidenv(wrd,p)
  212. char **wrd;
  213. int *p;
  214. {
  215.   int bp = 0, pos;
  216.   char brac = FALSE;
  217.   char *s,*env,nest;
  218.  
  219.   *p = -1;
  220.   if (**wrd == '{') {
  221.     brac = TRUE;
  222.     (*wrd)++;
  223.   }
  224.   while(isalnum(**wrd) || **wrd == '_') path[bp++] = *(*wrd)++;
  225.   path[bp] = 0;
  226.   env = (char *)getenv(path);
  227.   if (**wrd == '[') {
  228.     nest = 0;
  229.     (*wrd)++;
  230.     if (!env) {
  231.       while(**wrd && **wrd != ']') {
  232.     if (**wrd == '[') nest++;
  233.         (*wrd)++;
  234.     if (nest && **wrd == ']') {
  235.       nest--;
  236.       (*wrd)++;
  237.     }
  238.       }
  239.       if (**wrd) (*wrd)++;
  240.       if (brac) {
  241.         while(**wrd && **wrd != '}') (*wrd)++;
  242.     if (**wrd) (*wrd)++;
  243.       }
  244.     } else {
  245.       for(bp = 0; **wrd && **wrd != ']';) path[bp++] = *(*wrd)++;
  246.       path[bp] = 0;
  247.       if (**wrd) (*wrd)++;
  248.       if (brac) {
  249.         while(**wrd && **wrd != '}') (*wrd)++;
  250.     if (**wrd) (*wrd)++;
  251.       }
  252.       *p = pos = expr(path);
  253.       for(bp=0;bp<pos;bp++) {
  254.         env = (char *)index(env,':');
  255.     if (!env) return NULL;
  256.     env++;
  257.       }
  258.       bp = 0;
  259.       while(*env && *env != ':') path[bp++] = *env++;
  260.       path[bp] = 0;
  261.       env = (char*)malloc(bp+1);
  262.       strcpy(env,path);
  263.     }
  264.     return env;
  265.   }
  266.   if (!env) return NULL;
  267.   s = (char *)malloc(strlen(env)+1);
  268.   strcpy(s,env);
  269.   return s;
  270. }
  271.  
  272. struct _setvar *getset(pat,pos)
  273. char **pat;
  274. int *pos;
  275. {
  276.   int i=0;
  277.   char buf[81],bp=0;
  278.   struct _setvar *SET;
  279.  
  280.   *pos = -1;
  281.  
  282.   while((isalpha(**pat) || isdigit(**pat) || **pat == '_') && bp < 80)
  283.     buf[bp++] = *(*pat)++;
  284.   buf[bp] = 0;
  285.  
  286.   if ((SET = find_var(buf)) == NULL) return NULL;
  287.   if (SET->type != T_STRING) return SET;
  288.   if (**pat == '[') {
  289.     (*pat)++;
  290.     if (!SET) {
  291.       while(**pat && **pat != ']') (*pat)++;
  292.       if (**pat) (*pat)++;
  293.     } else {
  294.       i = 0;
  295.       while(**pat && **pat != ']') path[i++] = *(*pat)++;
  296.       path[i] = 0;
  297.       if (!**pat) return NULL;
  298.       if (**pat) (*pat)++;
  299.       *pos = expr(path);
  300.       if (*pos < 0 || (SET->nwrds-1 < *pos)) {
  301.     *pos = -2;
  302.     return NULL;
  303.       }
  304.     }
  305.   }
  306.   return SET;
  307. }
  308.  
  309. SET(n,arg,in,out,err)
  310. int n;
  311. char **arg;
  312. FILE *in,*out,*err;
  313. {
  314.   static char *signs[] = {
  315.     "=","+=","-=","*=","/=","%=","&=","|=","<<=",">>=","^=","++","--",0
  316.   };
  317.   union setval st;
  318.   struct _setvar *s;
  319.   char *t, *tmp;
  320.  
  321.   if (n == 1) {
  322.     for(a=0;a<37;a++) {
  323.       s = sets[a];
  324.       while(s) {
  325.         fprt(out,s->var);
  326.     fputc('\t',out);
  327.     if (s->type == T_STRING) {
  328.       fprt(out,t = (char *)string(s->sv.wrd));
  329.       free(t);
  330.     } else if (s->type == T_INTEGER) fprintf(out,"%d",s->sv.val);
  331.     fputc('\n',out);
  332.     s = s->nxt;
  333.       }
  334.     }
  335.     return 0;
  336.   }
  337.   for(c=0;signs[c];c++) if (!strcmp(arg[2],signs[c])) break;
  338.   if (arg[2] && !signs[c]) {
  339.     fprintf(err,"%s: missing assignment operator. '=' expected.\n",arg[0]);
  340.     return 1;
  341.   }
  342.   if (strlen(arg[1]) > 80) {
  343.     fprintf(err,"set: variable name too long.\n");
  344.     return 1;
  345.   }
  346.   t = strcpy(malloc(strlen(arg[1])+1),arg[1]);
  347.   if (n == 2) {
  348.     a = T_NULL;
  349.     st.val = 0;
  350.     if (!(s = add_var(t,st,a,0))) return 0;
  351.     check_and_export(s);
  352.     return 0;
  353.   }
  354.   if (strcmp("set",arg[0])) {
  355.     a = T_INTEGER;
  356.     if (c < 11) {
  357.       tmp = (char *)grab(arg,3,NULL,&b);
  358.       st.val = expr(tmp);
  359.     } else tmp = NULL;
  360.     if (c > 0 && (s = find_var(t))) {
  361.       if (s->type != T_INTEGER) s->sv.val = 0;
  362.       switch (c) {
  363.         case 1:
  364.       st.val += s->sv.val;
  365.       break;
  366.     case 2:
  367.       st.val = s->sv.val - st.val;
  368.       break;
  369.     case 3:
  370.       st.val *= s->sv.val;
  371.       break;
  372.     case 4:
  373.       st.val = s->sv.val / st.val;
  374.       break;
  375.     case 5:
  376.       st.val = s->sv.val % st.val;
  377.       break;
  378.     case 6:
  379.       st.val = s->sv.val & st.val;
  380.       break;
  381.     case 7:
  382.       st.val = s->sv.val | st.val;
  383.       break;
  384.     case 8:
  385.       st.val = s->sv.val << st.val;
  386.       break;
  387.     case 9:
  388.       st.val = s->sv.val >> st.val;
  389.       break;
  390.     case 10:
  391.       st.val = s->sv.val ^ st.val;
  392.       break;
  393.     case 11:
  394.       st.val = s->sv.val+1;
  395.       break;
  396.     case 12:
  397.       st.val = s->sv.val-1;
  398.       break;
  399.       }
  400.     }
  401.     if (tmp) free(tmp);
  402.   } else {
  403.     if (c > 1) {
  404.       fprintf(stderr,"set: invalid assignment operator: '%s'.\n",signs[c]);
  405.       return 1;
  406.     }
  407.     if (n <= 3) {
  408.       fprintf(stderr,"set: assignment expected.\n");
  409.       return 1;
  410.     }
  411.     a = 0;
  412.     if (c && (s = find_var(t))) {
  413.       st.wrd = (char **)calloc((n-2)+s->nwrds,sizeof(char *));
  414.       for(b=0;s->sv.wrd[b];b++)
  415.     st.wrd[a++] = strcpy(malloc(strlen(s->sv.wrd[b])+1),s->sv.wrd[b]);
  416.     } else st.wrd = (char **)calloc(n - 2,sizeof(char *));
  417.     for(b=3;arg[b];b++) st.wrd[a++] = strcpy(malloc(strlen(arg[b])+1),arg[b]);
  418.     st.wrd[a] = NULL;
  419.     a = T_STRING;
  420.   }
  421.   if (!(s = add_var(t,st,a,0))) return 0;
  422.   check_and_export(s);
  423.   return 0;
  424. }
  425.  
  426.  struct _vars {
  427.    char *name, val;
  428.  } vars[] = {
  429.   "cdpath",VAR_CDPATH,
  430.   "cwd", VAR_CWD,
  431.   "echo",VAR_ECHO,
  432.   "failat",VAR_FAILAT,
  433.   "history",VAR_HISTORY,
  434.   "home",VAR_HOME,
  435.   "homedirs",VAR_HOMEDIRS,
  436.   "insert",VAR_INSERT,
  437.   "joblimit",VAR_JOBLIMIT,
  438.   "mail",VAR_MAIL,
  439.   "mailchkint",VAR_MAILCHKINT,
  440.   "mailnotice",VAR_MAILNOTICE,
  441.   "noassigns",VAR_NOASSIGNS,
  442.   "nobgnull", VAR_NOBGNULL,
  443.   "noclobber",VAR_NOCLOBBER,
  444.   "nodots",VAR_NODOTS,
  445.   "noglob",VAR_NOGLOB,
  446.   "nohup",VAR_NOHUP,
  447.   "nonomatch",VAR_NONOMATCH,
  448.   "notypeahead",VAR_NOTYPEAHEAD,
  449.   "path",VAR_PATH,
  450.   "prompt",VAR_PROMPT,
  451.   "restricted",VAR_RESTRICTED,
  452.   "statint",VAR_STATINT,
  453.   "statline",VAR_STATLINE,
  454.   "term",VAR_TERM,
  455.   "timeout",VAR_TIMEOUT,
  456.   "user",VAR_USER,
  457.   "verbose",VAR_VERBOSE
  458. };
  459. #define NVARS    28
  460.  
  461. check_and_export(v)
  462. struct _setvar *v;
  463. {
  464.   int tmp;
  465.   char s=0, e=NVARS, m=NVARS/2;
  466.  
  467.   while(s <= e) {
  468.     if (!(d = strcmp(v->var,vars[m].name))) break;
  469.     if (d < 0) e = m - 1;
  470.     else s = m + 1;
  471.     m = (s+e)/2;
  472.   }
  473.   if (d) return;
  474.   switch(vars[m].val) {
  475.     case VAR_CDPATH:
  476.       if (v->type != T_STRING) return;
  477.       _cdpath = v->sv.wrd;
  478.       return;
  479.     case VAR_CWD:
  480.       if (v->type != T_STRING) return;
  481.       export(v);
  482.       return;
  483.     case VAR_ECHO:
  484.       _echo = TRUE;
  485.       return;
  486.     case VAR_FAILAT:
  487.       if (v->type != T_INTEGER) return;
  488.       _failat = (int)(v->sv.val? v->sv.val : 1);
  489.       return;
  490.     case VAR_HISTORY:
  491.       if (v->type != T_INTEGER) return;
  492.       _maxhist = tmp = (int)(v->sv.val);
  493.       if (tmp < curhist) for(d=tmp;d<curhist;d++) free(history[d]);
  494.       history = (char **)realloc(history,sizeof(char *)*(tmp?tmp+1:2));
  495.       if (curhist > tmp) curhist = tmp;
  496.       return;
  497.     case VAR_HOME:
  498.       if (v->type != T_STRING) return;
  499.       export(v);
  500.       if (_home) free(_home);
  501.       _home = string(v->sv.wrd);
  502.       return;
  503.     case VAR_HOMEDIRS:
  504.       if (v->type != T_STRING) return;
  505.       _homedirs = v->sv.wrd;
  506.       return;
  507.     case VAR_INSERT:
  508.       _insert = TRUE;
  509.       return;
  510.     case VAR_JOBLIMIT:
  511.       if (v->type != T_INTEGER) return;
  512.       _joblimit = (int)(v->sv.val);
  513.       return;
  514.     case VAR_MAIL:
  515.       if (v->type != T_STRING) return;
  516.       export(v);
  517.       _mbox = v->sv.wrd;
  518.       newmail = TRUE;
  519.       check_mail(TRUE);
  520.       return;
  521.     case VAR_MAILCHKINT:
  522.       if (v->type != T_INTEGER) return;
  523.       _mailchkint = (int)(v->sv.val);
  524.       return;
  525.     case VAR_MAILNOTICE:
  526.       if (v->type != T_STRING) return;
  527.       _mailnotice = v->sv.wrd;
  528.       return;
  529.     case VAR_NOASSIGNS:
  530.       _noassigns = TRUE;
  531.       return;
  532.     case VAR_NOBGNULL:
  533.       _nobgnull = TRUE;
  534.       return;
  535.     case VAR_NOCLOBBER:
  536.       _noclobber = TRUE;
  537.       return;
  538.     case VAR_NODOTS:
  539.       _nodots = TRUE;
  540.       return;
  541.     case VAR_NOHUP:
  542.       _nohup = TRUE;
  543.       return;
  544.     case VAR_NOGLOB:
  545.       _glob = FALSE;
  546.       return;
  547.     case VAR_NONOMATCH:
  548.       _nonomatch = TRUE;
  549.       return;
  550.     case VAR_NOTYPEAHEAD:
  551.       _notypeahead = TRUE;
  552.       return;
  553.     case VAR_PATH:
  554.       if (v->type != T_STRING) return;
  555.       PATH = v->sv.wrd;
  556.       export(v);
  557.       return;
  558.     case VAR_PROMPT:
  559.       if (v->type != T_STRING) return;
  560.       if (_prompt) free(_prompt);
  561.       _prompt = string(v->sv.wrd);
  562.       return;
  563.     case VAR_RESTRICTED:
  564.       v->protect = TRUE;
  565.       _restricted = TRUE;
  566.       break;
  567.     case VAR_STATINT:
  568.       if (v->type != T_INTEGER) return;
  569.       _statint = (int)(v->sv.val);
  570.       return;
  571.     case VAR_STATLINE:
  572.       if (v->type != T_STRING) return;
  573.       if (_statline) free(_statline);
  574.       _statline = string(v->sv.wrd);
  575.       return;
  576.     case VAR_TIMEOUT:
  577.       if (v->type != T_INTEGER) return;
  578.       if (v->sv.val < 1) _timeout = NULL;
  579.       else {
  580.         timeout.tv_sec = v->sv.val;
  581.     _timeout = &timeout;
  582.       }
  583.       return;
  584.     case VAR_TERM:
  585.       if (v->type != T_STRING) return;
  586.       export(v);
  587.       if (v->sv.wrd[0]) set_term(v->sv.wrd[0]);
  588.       return;
  589.     case VAR_USER:
  590.       if (v->type != T_STRING) return;
  591.       export(v);
  592.       return;
  593.     case VAR_VERBOSE:
  594.       _verbose = TRUE;
  595.       return;
  596.   }
  597. }
  598.  
  599. export(v)
  600. struct _setvar *v;
  601. {
  602.   char *name = UPPER(v->var),*val;
  603.   int len=0;
  604.  
  605.   for(d=0;v->sv.wrd[d];d++) len += strlen(v->sv.wrd[d])+1;
  606.   val = (char *)malloc(len);
  607.   strcpy(val,v->sv.wrd[0]);
  608.   for(d=1;v->sv.wrd[d];d++) {
  609.     strcat(val,":");
  610.     strcat(val,v->sv.wrd[d]);
  611.   }
  612.   setenv(name,val,1);
  613.   free(name);
  614.   free(val);
  615. }
  616.  
  617. UNSET(n,arg,in,out,err)
  618. int n;
  619. char **arg;
  620. FILE *in,*out,*err;
  621. {
  622.   if (n == 1) return 0;
  623.   for(a=1;arg[a];a++)
  624.     if (remove_var(arg[a])) unexport(arg[a]);
  625.     else {
  626.       fprintf(err,"unset: no such variable: %s\n",arg[a]);
  627.       return -1;
  628.     }
  629.   return 0;
  630. }
  631.  
  632. unexport(v)
  633. char *v;
  634. {
  635.   char s=0, e=NVARS, m=NVARS/2;
  636.  
  637.   while(s <= e) {
  638.     if (!(b = strcmp(v,vars[m].name))) break;
  639.     if (b < 0) e = m - 1;
  640.     else s = m + 1;
  641.     m = (s+e)/2;
  642.   }
  643.   if (b) return;
  644.   switch(vars[m].val) {
  645.     case VAR_CDPATH:
  646.       _cdpath = NULL;
  647.       return;
  648.     case VAR_ECHO:
  649.       _echo = FALSE;
  650.       return;
  651.     case VAR_FAILAT:
  652.       _failat = 1;
  653.       return;
  654.     case VAR_HISTORY:
  655.       _maxhist = c = 1;
  656.       if (c < curhist) for(b=c;b<curhist;b++) free(history[b]);
  657.       history = (char **)realloc(history,sizeof(char *)*2);
  658.       if (curhist > c) curhist = c;
  659.       return;
  660.     case VAR_HOME:
  661.       free(_home);
  662.       _home = NULL;
  663.       return;
  664.     case VAR_HOMEDIRS:
  665.       _homedirs = NULL;
  666.       return;
  667.     case VAR_INSERT:
  668.       _insert = FALSE;
  669.       return;
  670.     case VAR_JOBLIMIT:
  671.       _joblimit = -1;
  672.       return;
  673.     case VAR_MAIL:
  674.       _mbox = NULL;
  675.       return;
  676.     case VAR_MAILCHKINT:
  677.       _mailchkint = 60;
  678.       return;
  679.     case VAR_MAILNOTICE:
  680.       _mailnotice = NULL;
  681.       return;
  682.     case VAR_NOASSIGNS:
  683.       _noassigns = FALSE;
  684.       return;
  685.     case VAR_NOBGNULL:
  686.       _nobgnull = FALSE;
  687.       return;
  688.     case VAR_NOCLOBBER:
  689.       _noclobber = FALSE;
  690.       return;
  691.     case VAR_NODOTS:
  692.       _nodots = FALSE;
  693.       return;
  694.     case VAR_NOGLOB:
  695.       _glob = TRUE;
  696.       return;
  697.     case VAR_NOHUP:
  698.       _nohup = FALSE;
  699.       return;
  700.     case VAR_NONOMATCH:
  701.       _nonomatch = FALSE;
  702.       return;
  703.     case VAR_NOTYPEAHEAD:
  704.       _notypeahead = FALSE;
  705.       return;
  706.     case VAR_PATH:
  707.       PATH = (char **) malloc(sizeof(char *) * 2);
  708.       PATH[0] = ".";
  709.       PATH[1] = 0;
  710.       return;
  711.     case VAR_PROMPT:
  712.       free(_prompt);
  713.       _prompt = "";
  714.       return;
  715.     case VAR_STATINT:
  716.       _statint = 30;
  717.       return;
  718.     case VAR_STATLINE:
  719.       printf("%s%s%s",_term[TS],_term[CE],_term[FS]);
  720.       free(_statline);
  721.       _statline = NULL;
  722.       return;
  723.     case VAR_TIMEOUT:
  724.       _timeout = NULL;
  725.       return;
  726.     case VAR_VERBOSE:
  727.       _verbose = FALSE;
  728.       return;
  729.   }
  730. }
  731.  
  732. /* shift <nshifts> <var> [<var> ... <var>] - shifts words to the left.*/
  733. SHIFT(n,arg,ferr)
  734. int n;
  735. char **arg;
  736. FILE *ferr;
  737. {
  738.   struct _setvar *S;
  739.   int i, j, ns;
  740.  
  741.   if (n < 3) {
  742.     fprintf(ferr,"shift: not enough arguments!\n");
  743.     return 1;
  744.   }
  745.   if ((ns = atoi(arg[1])) <= 0) {
  746.     fprintf(ferr,"shift: shift specifier should be greater than zero.\n");
  747.     return 1;
  748.   }
  749.   for(i=2;i<n;i++) {
  750.     if ((S = find_var(arg[i])) == NULL) {
  751.       fprintf(ferr,"shift: variable '%s' not defined.\n",arg[i]);
  752.       continue;
  753.     }
  754.     if (S->type) {
  755.       fprintf(ferr,"shift: variable '%s' not a string type.\n",arg[i]);
  756.       continue;
  757.     }
  758.     if (S->protect) {
  759.       fprintf(ferr,"shift: variable '%s' is protected and not changed.\n",arg[i]);
  760.       continue;
  761.     }
  762.     if (S->nwrds <= ns) {
  763.       fprintf(ferr,"shift: too many words would be shifted for variable '%s'.\n",arg[i]);
  764.       continue;
  765.     }
  766.     for(j=0;j<ns;j++) free(S->sv.wrd[j]);
  767.     for(j=ns;j<=S->nwrds;j++) S->sv.wrd[j-ns] = S->sv.wrd[j];
  768.     S->nwrds -= ns;
  769.     S->sv.wrd = (char **)realloc(S->sv.wrd,sizeof(char **) * (S->nwrds+1));
  770.   }
  771.   return 0;
  772. }
  773.  
  774. struct _setvar *find_var(pat)
  775. char *pat;
  776. {
  777.   int i, hv = hash(*pat);
  778.   struct _setvar *p = sets[hv];
  779.  
  780.   while (p) {
  781.     if (!(i = strcmp(pat,p->var))) return p;
  782.     if (i < 0) return NULL;
  783.     p = p->nxt;
  784.   }
  785.   return NULL;
  786. }
  787.  
  788. struct _setvar *add_var(var,stuff,type,pro)
  789. char *var;
  790. union setval stuff;
  791. BYTE type,pro;
  792. {
  793.   int i, hv = hash(*var);
  794.   struct _setvar *p = sets[hv], *s = p, *t = (struct _setvar *)malloc(sizeof(struct _setvar));
  795.  
  796.   while (p) {
  797.     if (!(i = strcmp(var,p->var))) {
  798.       if (p->protect) {
  799.     if (type == T_STRING) free_list(stuff.wrd);
  800.     return NULL;
  801.       }
  802.       if (p->type == T_STRING) free_list(p->sv.wrd);
  803.       p->sv = stuff;
  804.       p->type = type;
  805.       if (type == T_STRING) {
  806.         for(i=0;stuff.wrd[i];i++);
  807.     p->nwrds = i;
  808.       }
  809.       return p;
  810.     }
  811.     if (i < 0) break;
  812.     s = p;
  813.     p = p->nxt;
  814.   }
  815.   t->var = (char *)strcpy((char *)malloc(strlen(var)+1),var);
  816.   t->type = type;
  817.   t->nwrds = 0;
  818.   t->protect = pro?1:0;
  819.   switch(type) {
  820.     case T_STRING:
  821.       t->sv.wrd = stuff.wrd;
  822.       for(i=0;stuff.wrd[i];i++);
  823.       t->nwrds = i;
  824.       break;
  825.     case T_INTEGER:
  826.       t->sv.val = stuff.val;
  827.       break;
  828.     case T_NULL:
  829.       t->sv.val = 0;
  830.       break;
  831.   }
  832.   t->nxt = p;
  833.   if (p == sets[hv] && s == sets[hv]) sets[hv] = t;
  834.   else s->nxt = t;
  835.   return t;
  836. }
  837.  
  838. remove_var(var)
  839. char *var;
  840. {
  841.   int i, hv = hash(*var);
  842.   struct _setvar *p = sets[hv], *s = p;
  843.  
  844.   while (p) {
  845.     if (!(i = strcmp(var,p->var))) {
  846.       if (p->protect) return TRUE;
  847.       if (p == sets[hv]) sets[hv] = p->nxt;
  848.       else s->nxt = p->nxt;
  849.       free(p->var);
  850.       if (p->type == T_STRING) free_list(p->sv.wrd);
  851.       free(p);
  852.       return TRUE;
  853.     }
  854.     if (i < 0) break;
  855.     s = p;
  856.     p = p->nxt;
  857.   }
  858.   return FALSE;
  859. }
  860.  
  861. struct _setvar *makenvar(var,num)
  862. char *var;
  863. long num;
  864. {
  865.   union setval st;
  866.   struct _setvar *s;
  867.  
  868.   st.val = num;
  869.   if (!(s = add_var(var,st,T_INTEGER,0))) return NULL;
  870.   check_and_export(s);
  871.   return s;
  872. }
  873.  
  874. struct _setvar *makenull(var)
  875. char *var;
  876. {
  877.   union setval st;
  878.   struct _setvar *s;
  879.  
  880.   st.val = 0;
  881.   if (!(s = add_var(var,st,T_NULL,0))) return NULL;
  882.   check_and_export(s);
  883.   return s;
  884. }
  885.  
  886. struct _setvar *makeset(var,wrd)
  887. char *var, *wrd;
  888. {
  889.   union setval st;
  890.   struct _setvar *s;
  891.  
  892.   st.wrd = (char **)calloc(2,sizeof(char *));
  893.   st.wrd[0] = strcpy(malloc(strlen(wrd)+1),wrd);
  894.   st.wrd[1] = NULL;
  895.   if (!(s = add_var(var,st,T_STRING,0))) return NULL;
  896.   check_and_export(s);
  897.   return s;
  898. }
  899.  
  900. struct _setvar *makewset(var,wrd)
  901. char *var, *wrd;
  902. {
  903.   union setval st;
  904.   struct _setvar *s;
  905.   int i,j,k, n = 5,p = 0;
  906.  
  907.   st.wrd = (char **)calloc(n,sizeof(char *));
  908.   i = 0;
  909.   while(buf[i] == ' ' || buf[i] == '\t') i++;
  910.   j = i;
  911.   while(1) {
  912.     if (buf[i] == ' ' || buf[i] == '\t' || !buf[i]) {
  913.       if (!buf[i] && (i-j) == 0) break;
  914.       if (p == (n-1)) st.wrd = (char **)realloc(st.wrd,(n+=2) * sizeof(char *));
  915.       st.wrd[p] = (char *)malloc((i-j)+1);
  916.       for(k=j;k<i;k++) st.wrd[p][k-j] = buf[k];
  917.       st.wrd[p++][k-j] = 0;
  918.       if (!buf[i]) break;
  919.       while(buf[i] == ' ' || buf[i] == '\t') i++;
  920.       j = i;
  921.     } else i++;
  922.   }
  923.   st.wrd[p] = NULL;
  924.   if (!(s = add_var(var,st,T_STRING,0))) return NULL;
  925.   check_and_export(s);
  926.   return s;
  927. }
  928.