1*53651Smarc #include "shell.h" 2*53651Smarc #include "input.h" 3*53651Smarc #include "output.h" 4*53651Smarc #include "error.h" 5*53651Smarc #include "memalloc.h" 6*53651Smarc #include "mystring.h" 7*53651Smarc #include "alias.h" 8*53651Smarc #include "options.h" /* XXX for argptr (should remove?) */ 9*53651Smarc 10*53651Smarc #define ATABSIZE 39 11*53651Smarc 12*53651Smarc struct alias *atab[ATABSIZE]; 13*53651Smarc 14*53651Smarc STATIC struct alias **hashalias __P((char *)); 15*53651Smarc 16*53651Smarc STATIC 17*53651Smarc setalias(name, val) 18*53651Smarc char *name, *val; 19*53651Smarc { 20*53651Smarc struct alias *ap, **app; 21*53651Smarc 22*53651Smarc app = hashalias(name); 23*53651Smarc for (ap = *app; ap; ap = ap->next) { 24*53651Smarc if (equal(name, ap->name)) { 25*53651Smarc INTOFF; 26*53651Smarc ckfree(ap->val); 27*53651Smarc ap->val = savestr(val); 28*53651Smarc INTON; 29*53651Smarc return; 30*53651Smarc } 31*53651Smarc } 32*53651Smarc /* not found */ 33*53651Smarc INTOFF; 34*53651Smarc ap = ckmalloc(sizeof (struct alias)); 35*53651Smarc ap->name = savestr(name); 36*53651Smarc /* 37*53651Smarc * XXX - HACK: in order that the parser will not finish reading the 38*53651Smarc * alias value off the input before processing the next alias, we 39*53651Smarc * dummy up an extra space at the end of the alias. This is a crock 40*53651Smarc * and should be re-thought. The idea (if you feel inclined to help) 41*53651Smarc * is to avoid alias recursions. The mechanism used is: when 42*53651Smarc * expanding an alias, the value of the alias is pushed back on the 43*53651Smarc * input as a string and a pointer to the alias is stored with the 44*53651Smarc * string. The alias is marked as being in use. When the input 45*53651Smarc * routine finishes reading the string, it markes the alias not 46*53651Smarc * in use. The problem is synchronization with the parser. Since 47*53651Smarc * it reads ahead, the alias is marked not in use before the 48*53651Smarc * resulting token(s) is next checked for further alias sub. The 49*53651Smarc * H A C K is that we add a little fluff after the alias value 50*53651Smarc * so that the string will not be exhausted. This is a good 51*53651Smarc * idea ------- ***NOT*** 52*53651Smarc */ 53*53651Smarc #ifdef notyet 54*53651Smarc ap->val = savestr(val); 55*53651Smarc #else /* hack */ 56*53651Smarc { 57*53651Smarc int len = strlen(val); 58*53651Smarc ap->val = ckmalloc(len + 2); 59*53651Smarc bcopy(val, ap->val, len); 60*53651Smarc ap->val[len] = ' '; /* fluff */ 61*53651Smarc ap->val[len+1] = '\0'; 62*53651Smarc } 63*53651Smarc #endif 64*53651Smarc ap->next = *app; 65*53651Smarc *app = ap; 66*53651Smarc INTON; 67*53651Smarc } 68*53651Smarc 69*53651Smarc STATIC int 70*53651Smarc unalias(name) 71*53651Smarc char *name; 72*53651Smarc { 73*53651Smarc struct alias *ap, **app; 74*53651Smarc 75*53651Smarc app = hashalias(name); 76*53651Smarc 77*53651Smarc for (ap = *app; ap; app = &(ap->next), ap = ap->next) { 78*53651Smarc if (equal(name, ap->name)) { 79*53651Smarc /* 80*53651Smarc * if the alias is currently in use (i.e. its 81*53651Smarc * buffer is being used by the input routine) we 82*53651Smarc * just null out the name instead of freeing it. 83*53651Smarc * We could clear it out later, but this situation 84*53651Smarc * is so rare that it hardly seems worth it. 85*53651Smarc */ 86*53651Smarc if (ap->flag & ALIASINUSE) 87*53651Smarc *ap->name = '\0'; 88*53651Smarc else { 89*53651Smarc INTOFF; 90*53651Smarc *app = ap->next; 91*53651Smarc ckfree(ap->name); 92*53651Smarc ckfree(ap->val); 93*53651Smarc ckfree(ap); 94*53651Smarc INTON; 95*53651Smarc } 96*53651Smarc return (0); 97*53651Smarc } 98*53651Smarc } 99*53651Smarc 100*53651Smarc return (1); 101*53651Smarc } 102*53651Smarc 103*53651Smarc #ifdef mkinit 104*53651Smarc MKINIT void rmaliases(); 105*53651Smarc 106*53651Smarc SHELLPROC { 107*53651Smarc rmaliases(); 108*53651Smarc } 109*53651Smarc #endif 110*53651Smarc 111*53651Smarc void 112*53651Smarc rmaliases() { 113*53651Smarc struct alias *ap, *tmp; 114*53651Smarc int i; 115*53651Smarc 116*53651Smarc INTOFF; 117*53651Smarc for (i = 0; i < ATABSIZE; i++) { 118*53651Smarc ap = atab[i]; 119*53651Smarc atab[i] = NULL; 120*53651Smarc while (ap) { 121*53651Smarc ckfree(ap->name); 122*53651Smarc ckfree(ap->val); 123*53651Smarc tmp = ap; 124*53651Smarc ap = ap->next; 125*53651Smarc ckfree(tmp); 126*53651Smarc } 127*53651Smarc } 128*53651Smarc INTON; 129*53651Smarc } 130*53651Smarc 131*53651Smarc struct alias * 132*53651Smarc lookupalias(name, check) 133*53651Smarc char *name; 134*53651Smarc { 135*53651Smarc struct alias *ap = *hashalias(name); 136*53651Smarc 137*53651Smarc for (; ap; ap = ap->next) { 138*53651Smarc if (equal(name, ap->name)) { 139*53651Smarc if (check && (ap->flag & ALIASINUSE)) 140*53651Smarc return (NULL); 141*53651Smarc return (ap); 142*53651Smarc } 143*53651Smarc } 144*53651Smarc 145*53651Smarc return (NULL); 146*53651Smarc } 147*53651Smarc 148*53651Smarc /* 149*53651Smarc * TODO - sort output 150*53651Smarc */ 151*53651Smarc aliascmd(argc, argv) 152*53651Smarc char **argv; 153*53651Smarc { 154*53651Smarc char *n, *v; 155*53651Smarc int ret = 0; 156*53651Smarc struct alias *ap; 157*53651Smarc 158*53651Smarc if (argc == 1) { 159*53651Smarc int i; 160*53651Smarc 161*53651Smarc for (i = 0; i < ATABSIZE; i++) 162*53651Smarc for (ap = atab[i]; ap; ap = ap->next) { 163*53651Smarc if (*ap->name != '\0') 164*53651Smarc out1fmt("alias %s=%s\n", ap->name, ap->val); 165*53651Smarc } 166*53651Smarc return (0); 167*53651Smarc } 168*53651Smarc while (n = *++argv) { 169*53651Smarc if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */ 170*53651Smarc if ((ap = lookupalias(n, 0)) == NULL) { 171*53651Smarc outfmt(out2, "alias: %s not found\n", n); 172*53651Smarc ret = 1; 173*53651Smarc } else 174*53651Smarc out1fmt("alias %s=%s\n", n, ap->val); 175*53651Smarc else { 176*53651Smarc *v++ = '\0'; 177*53651Smarc setalias(n, v); 178*53651Smarc } 179*53651Smarc } 180*53651Smarc 181*53651Smarc return (ret); 182*53651Smarc } 183*53651Smarc 184*53651Smarc unaliascmd(argc, argv) 185*53651Smarc char **argv; 186*53651Smarc { 187*53651Smarc int i; 188*53651Smarc 189*53651Smarc while ((i = nextopt("a")) != '\0') { 190*53651Smarc if (i == 'a') { 191*53651Smarc rmaliases(); 192*53651Smarc return (0); 193*53651Smarc } 194*53651Smarc } 195*53651Smarc for (i = 0; *argptr; argptr++) 196*53651Smarc i = unalias(*argptr); 197*53651Smarc 198*53651Smarc return (i); 199*53651Smarc } 200*53651Smarc 201*53651Smarc /* 202*53651Smarc * XXX -- for playing with the builtin command routines -- REMOVE 203*53651Smarc */ 204*53651Smarc foocmd(argc, argv) 205*53651Smarc char **argv; 206*53651Smarc { 207*53651Smarc char **ap; 208*53651Smarc 209*53651Smarc out1fmt("argc: %d argv: %x argptr: %x\n", argc, argv, argptr); 210*53651Smarc out1fmt("ARGV:\n"); 211*53651Smarc ap = argv; 212*53651Smarc while (*ap) 213*53651Smarc out1fmt("%s\n", *ap++); 214*53651Smarc out1fmt("ARGPTR:\n"); 215*53651Smarc ap = argptr; 216*53651Smarc while (*ap) 217*53651Smarc out1fmt("%s\n", *ap++); 218*53651Smarc } 219*53651Smarc 220*53651Smarc STATIC struct alias ** 221*53651Smarc hashalias(p) 222*53651Smarc register char *p; 223*53651Smarc { 224*53651Smarc unsigned int hashval; 225*53651Smarc 226*53651Smarc hashval = *p << 4; 227*53651Smarc while (*p) 228*53651Smarc hashval+= *p++; 229*53651Smarc return &atab[hashval % ATABSIZE]; 230*53651Smarc } 231