1 1.24 kre /* $NetBSD: alias.c,v 1.24 2025/05/12 02:45:28 kre Exp $ */ 2 1.5 cgd 3 1.1 jtc /*- 4 1.1 jtc * Copyright (c) 1993 5 1.1 jtc * The Regents of the University of California. All rights reserved. 6 1.1 jtc * 7 1.1 jtc * This code is derived from software contributed to Berkeley by 8 1.1 jtc * Kenneth Almquist. 9 1.1 jtc * 10 1.1 jtc * Redistribution and use in source and binary forms, with or without 11 1.1 jtc * modification, are permitted provided that the following conditions 12 1.1 jtc * are met: 13 1.1 jtc * 1. Redistributions of source code must retain the above copyright 14 1.1 jtc * notice, this list of conditions and the following disclaimer. 15 1.1 jtc * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 jtc * notice, this list of conditions and the following disclaimer in the 17 1.1 jtc * documentation and/or other materials provided with the distribution. 18 1.12 agc * 3. Neither the name of the University nor the names of its contributors 19 1.1 jtc * may be used to endorse or promote products derived from this software 20 1.1 jtc * without specific prior written permission. 21 1.1 jtc * 22 1.1 jtc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.1 jtc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.1 jtc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.1 jtc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.1 jtc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.1 jtc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.1 jtc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.1 jtc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.1 jtc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.1 jtc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.1 jtc * SUCH DAMAGE. 33 1.1 jtc */ 34 1.1 jtc 35 1.9 christos #include <sys/cdefs.h> 36 1.1 jtc #ifndef lint 37 1.5 cgd #if 0 38 1.6 christos static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95"; 39 1.5 cgd #else 40 1.24 kre __RCSID("$NetBSD: alias.c,v 1.24 2025/05/12 02:45:28 kre Exp $"); 41 1.5 cgd #endif 42 1.1 jtc #endif /* not lint */ 43 1.1 jtc 44 1.6 christos #include <stdlib.h> 45 1.1 jtc #include "shell.h" 46 1.1 jtc #include "input.h" 47 1.1 jtc #include "output.h" 48 1.1 jtc #include "error.h" 49 1.1 jtc #include "memalloc.h" 50 1.1 jtc #include "mystring.h" 51 1.1 jtc #include "alias.h" 52 1.1 jtc #include "options.h" /* XXX for argptr (should remove?) */ 53 1.14 christos #include "builtins.h" 54 1.11 christos #include "var.h" 55 1.1 jtc 56 1.1 jtc #define ATABSIZE 39 57 1.1 jtc 58 1.1 jtc struct alias *atab[ATABSIZE]; 59 1.1 jtc 60 1.11 christos STATIC void setalias(char *, char *); 61 1.17 rillig STATIC int by_name(const void *, const void *); 62 1.17 rillig STATIC void list_aliases(void); 63 1.11 christos STATIC int unalias(char *); 64 1.20 kre STATIC struct alias **freealias(struct alias **, int); 65 1.15 christos STATIC struct alias **hashalias(const char *); 66 1.21 kre STATIC int countaliases(void); 67 1.1 jtc 68 1.1 jtc STATIC 69 1.4 cgd void 70 1.11 christos setalias(char *name, char *val) 71 1.4 cgd { 72 1.1 jtc struct alias *ap, **app; 73 1.1 jtc 74 1.19 kre (void) unalias(name); /* old one (if any) is now gone */ 75 1.1 jtc app = hashalias(name); 76 1.19 kre 77 1.1 jtc INTOFF; 78 1.1 jtc ap = ckmalloc(sizeof (struct alias)); 79 1.1 jtc ap->name = savestr(name); 80 1.13 stacktic ap->flag = 0; 81 1.20 kre ap->val = savestr(val); 82 1.20 kre ap->next = *app; 83 1.20 kre *app = ap; 84 1.20 kre INTON; 85 1.20 kre } 86 1.20 kre 87 1.20 kre STATIC struct alias ** 88 1.20 kre freealias(struct alias **app, int force) 89 1.20 kre { 90 1.20 kre struct alias *ap = *app; 91 1.20 kre 92 1.20 kre if (ap == NULL) 93 1.20 kre return app; 94 1.20 kre 95 1.1 jtc /* 96 1.20 kre * if the alias is currently in use (i.e. its 97 1.20 kre * buffer is being used by the input routine) we 98 1.20 kre * just null out the name instead of discarding it. 99 1.20 kre * If we encounter it later, when it is idle, 100 1.20 kre * we will finish freeing it then. 101 1.20 kre * 102 1.20 kre * Unless we want to simply free everything (INIT) 103 1.1 jtc */ 104 1.20 kre if (ap->flag & ALIASINUSE && !force) { 105 1.20 kre *ap->name = '\0'; 106 1.20 kre return &ap->next; 107 1.1 jtc } 108 1.20 kre 109 1.20 kre INTOFF; 110 1.20 kre *app = ap->next; 111 1.20 kre ckfree(ap->name); 112 1.20 kre ckfree(ap->val); 113 1.20 kre ckfree(ap); 114 1.1 jtc INTON; 115 1.20 kre 116 1.20 kre return app; 117 1.1 jtc } 118 1.1 jtc 119 1.1 jtc STATIC int 120 1.11 christos unalias(char *name) 121 1.11 christos { 122 1.1 jtc struct alias *ap, **app; 123 1.1 jtc 124 1.1 jtc app = hashalias(name); 125 1.20 kre while ((ap = *app) != NULL) { 126 1.1 jtc if (equal(name, ap->name)) { 127 1.20 kre (void) freealias(app, 0); 128 1.18 kre return 0; 129 1.1 jtc } 130 1.20 kre app = &ap->next; 131 1.1 jtc } 132 1.1 jtc 133 1.18 kre return 1; 134 1.1 jtc } 135 1.1 jtc 136 1.1 jtc #ifdef mkinit 137 1.20 kre MKINIT void rmaliases(int); 138 1.1 jtc 139 1.1 jtc SHELLPROC { 140 1.20 kre rmaliases(1); 141 1.1 jtc } 142 1.1 jtc #endif 143 1.1 jtc 144 1.1 jtc void 145 1.20 kre rmaliases(int force) 146 1.11 christos { 147 1.20 kre struct alias **app; 148 1.1 jtc int i; 149 1.1 jtc 150 1.1 jtc INTOFF; 151 1.1 jtc for (i = 0; i < ATABSIZE; i++) { 152 1.20 kre app = &atab[i]; 153 1.20 kre while (*app) 154 1.20 kre app = freealias(app, force); 155 1.1 jtc } 156 1.1 jtc INTON; 157 1.1 jtc } 158 1.1 jtc 159 1.1 jtc struct alias * 160 1.15 christos lookupalias(const char *name, int check) 161 1.4 cgd { 162 1.1 jtc struct alias *ap = *hashalias(name); 163 1.1 jtc 164 1.20 kre while (ap != NULL) { 165 1.1 jtc if (equal(name, ap->name)) { 166 1.1 jtc if (check && (ap->flag & ALIASINUSE)) 167 1.18 kre return NULL; 168 1.18 kre return ap; 169 1.1 jtc } 170 1.20 kre ap = ap->next; 171 1.1 jtc } 172 1.1 jtc 173 1.18 kre return NULL; 174 1.1 jtc } 175 1.1 jtc 176 1.15 christos const char * 177 1.15 christos alias_text(void *dummy __unused, const char *name) 178 1.11 christos { 179 1.11 christos struct alias *ap; 180 1.11 christos 181 1.11 christos ap = lookupalias(name, 0); 182 1.11 christos if (ap == NULL) 183 1.11 christos return NULL; 184 1.11 christos return ap->val; 185 1.11 christos } 186 1.11 christos 187 1.17 rillig STATIC int 188 1.17 rillig by_name(const void *a, const void *b) 189 1.17 rillig { 190 1.17 rillig 191 1.17 rillig return strcmp( 192 1.17 rillig (*(const struct alias * const *)a)->name, 193 1.17 rillig (*(const struct alias * const *)b)->name); 194 1.17 rillig } 195 1.17 rillig 196 1.17 rillig STATIC void 197 1.17 rillig list_aliases(void) 198 1.17 rillig { 199 1.21 kre int i, j, n; 200 1.17 rillig const struct alias **aliases; 201 1.17 rillig const struct alias *ap; 202 1.17 rillig 203 1.20 kre INTOFF; 204 1.20 kre n = countaliases(); 205 1.21 kre aliases = stalloc(n * (int)(sizeof aliases[0])); 206 1.17 rillig 207 1.17 rillig j = 0; 208 1.17 rillig for (i = 0; i < ATABSIZE; i++) 209 1.17 rillig for (ap = atab[i]; ap != NULL; ap = ap->next) 210 1.17 rillig if (ap->name[0] != '\0') 211 1.17 rillig aliases[j++] = ap; 212 1.20 kre if (j != n) 213 1.20 kre error("Alias count botch"); 214 1.20 kre INTON; 215 1.17 rillig 216 1.17 rillig qsort(aliases, n, sizeof aliases[0], by_name); 217 1.17 rillig 218 1.17 rillig for (i = 0; i < n; i++) { 219 1.17 rillig out1fmt("alias %s=", aliases[i]->name); 220 1.17 rillig print_quoted(aliases[i]->val); 221 1.17 rillig out1c('\n'); 222 1.17 rillig } 223 1.17 rillig 224 1.21 kre stunalloc(aliases); 225 1.17 rillig } 226 1.17 rillig 227 1.20 kre /* 228 1.20 kre * Count how many aliases are defined (skipping any 229 1.20 kre * that have been deleted, but don't know it yet). 230 1.20 kre * Use this opportunity to clean up any of those 231 1.20 kre * zombies that are no longer needed. 232 1.20 kre */ 233 1.21 kre STATIC int 234 1.20 kre countaliases(void) 235 1.20 kre { 236 1.20 kre struct alias *ap, **app; 237 1.20 kre size_t n; 238 1.20 kre int i; 239 1.20 kre 240 1.20 kre n = 0; 241 1.20 kre for (i = 0; i < ATABSIZE; i++) 242 1.20 kre for (app = &atab[i]; (ap = *app) != NULL;) { 243 1.20 kre if (ap->name[0] != '\0') 244 1.20 kre n++; 245 1.20 kre else { 246 1.20 kre app = freealias(app, 0); 247 1.20 kre continue; 248 1.20 kre } 249 1.20 kre app = &ap->next; 250 1.20 kre } 251 1.20 kre 252 1.20 kre return n; 253 1.20 kre } 254 1.20 kre 255 1.23 rillig /* ARGSUSED */ 256 1.4 cgd int 257 1.23 rillig aliascmd(int argc, char **argv) 258 1.4 cgd { 259 1.1 jtc char *n, *v; 260 1.1 jtc int ret = 0; 261 1.1 jtc struct alias *ap; 262 1.1 jtc 263 1.22 kre (void) nextopt(NULL); /* consume possible "--" */ 264 1.22 kre 265 1.22 kre if (*argptr == NULL) { 266 1.17 rillig list_aliases(); 267 1.18 kre return 0; 268 1.1 jtc } 269 1.17 rillig 270 1.22 kre while ((n = *argptr++) != NULL) { 271 1.24 kre if (n[0] == '\0') { 272 1.24 kre outfmt(out2, "alias: '' not found\n"); 273 1.24 kre ret = 1; 274 1.24 kre continue; 275 1.24 kre } 276 1.10 christos if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */ 277 1.1 jtc if ((ap = lookupalias(n, 0)) == NULL) { 278 1.1 jtc outfmt(out2, "alias: %s not found\n", n); 279 1.1 jtc ret = 1; 280 1.11 christos } else { 281 1.11 christos out1fmt("alias %s=", n); 282 1.11 christos print_quoted(ap->val); 283 1.11 christos out1c('\n'); 284 1.11 christos } 285 1.11 christos } else { 286 1.1 jtc *v++ = '\0'; 287 1.1 jtc setalias(n, v); 288 1.1 jtc } 289 1.1 jtc } 290 1.1 jtc 291 1.18 kre return ret; 292 1.1 jtc } 293 1.1 jtc 294 1.4 cgd int 295 1.11 christos unaliascmd(int argc, char **argv) 296 1.4 cgd { 297 1.1 jtc int i; 298 1.7 christos 299 1.1 jtc while ((i = nextopt("a")) != '\0') { 300 1.1 jtc if (i == 'a') { 301 1.20 kre rmaliases(0); 302 1.18 kre return 0; 303 1.1 jtc } 304 1.1 jtc } 305 1.20 kre 306 1.20 kre (void)countaliases(); /* delete any dead ones */ 307 1.1 jtc for (i = 0; *argptr; argptr++) 308 1.20 kre i |= unalias(*argptr); 309 1.1 jtc 310 1.18 kre return i; 311 1.1 jtc } 312 1.1 jtc 313 1.1 jtc STATIC struct alias ** 314 1.15 christos hashalias(const char *p) 315 1.11 christos { 316 1.1 jtc unsigned int hashval; 317 1.1 jtc 318 1.16 kre hashval = *(const unsigned char *)p << 4; 319 1.1 jtc while (*p) 320 1.16 kre hashval += *p++; 321 1.1 jtc return &atab[hashval % ATABSIZE]; 322 1.1 jtc } 323