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