1*60701Sbostic /*- 2*60701Sbostic * Copyright (c) 1993 3*60701Sbostic * The Regents of the University of California. All rights reserved. 4*60701Sbostic * 5*60701Sbostic * This code is derived from software contributed to Berkeley by 6*60701Sbostic * Kenneth Almquist. 7*60701Sbostic * 8*60701Sbostic * %sccs.include.redist.c% 9*60701Sbostic */ 10*60701Sbostic 11*60701Sbostic #ifndef lint 12*60701Sbostic static char sccsid[] = "@(#)alias.c 1.3 (Berkeley) 05/31/93"; 13*60701Sbostic #endif /* not lint */ 14*60701Sbostic 1553651Smarc #include "shell.h" 1653651Smarc #include "input.h" 1753651Smarc #include "output.h" 1853651Smarc #include "error.h" 1953651Smarc #include "memalloc.h" 2053651Smarc #include "mystring.h" 2153651Smarc #include "alias.h" 2253651Smarc #include "options.h" /* XXX for argptr (should remove?) */ 2353651Smarc 2453651Smarc #define ATABSIZE 39 2553651Smarc 2653651Smarc struct alias *atab[ATABSIZE]; 2753651Smarc 2853651Smarc STATIC struct alias **hashalias __P((char *)); 2953651Smarc 3053651Smarc STATIC 3153651Smarc setalias(name, val) 3253651Smarc char *name, *val; 3353651Smarc { 3453651Smarc struct alias *ap, **app; 3553651Smarc 3653651Smarc app = hashalias(name); 3753651Smarc for (ap = *app; ap; ap = ap->next) { 3853651Smarc if (equal(name, ap->name)) { 3953651Smarc INTOFF; 4053651Smarc ckfree(ap->val); 4153651Smarc ap->val = savestr(val); 4253651Smarc INTON; 4353651Smarc return; 4453651Smarc } 4553651Smarc } 4653651Smarc /* not found */ 4753651Smarc INTOFF; 4853651Smarc ap = ckmalloc(sizeof (struct alias)); 4953651Smarc ap->name = savestr(name); 5053651Smarc /* 5153651Smarc * XXX - HACK: in order that the parser will not finish reading the 5253651Smarc * alias value off the input before processing the next alias, we 5353651Smarc * dummy up an extra space at the end of the alias. This is a crock 5453651Smarc * and should be re-thought. The idea (if you feel inclined to help) 5553651Smarc * is to avoid alias recursions. The mechanism used is: when 5653651Smarc * expanding an alias, the value of the alias is pushed back on the 5753651Smarc * input as a string and a pointer to the alias is stored with the 5853651Smarc * string. The alias is marked as being in use. When the input 5953651Smarc * routine finishes reading the string, it markes the alias not 6053651Smarc * in use. The problem is synchronization with the parser. Since 6153651Smarc * it reads ahead, the alias is marked not in use before the 6253651Smarc * resulting token(s) is next checked for further alias sub. The 6353651Smarc * H A C K is that we add a little fluff after the alias value 6453651Smarc * so that the string will not be exhausted. This is a good 6553651Smarc * idea ------- ***NOT*** 6653651Smarc */ 6753651Smarc #ifdef notyet 6853651Smarc ap->val = savestr(val); 6953651Smarc #else /* hack */ 7053651Smarc { 7153651Smarc int len = strlen(val); 7253651Smarc ap->val = ckmalloc(len + 2); 7353651Smarc bcopy(val, ap->val, len); 7453651Smarc ap->val[len] = ' '; /* fluff */ 7553651Smarc ap->val[len+1] = '\0'; 7653651Smarc } 7753651Smarc #endif 7853651Smarc ap->next = *app; 7953651Smarc *app = ap; 8053651Smarc INTON; 8153651Smarc } 8253651Smarc 8353651Smarc STATIC int 8453651Smarc unalias(name) 8553651Smarc char *name; 8653651Smarc { 8753651Smarc struct alias *ap, **app; 8853651Smarc 8953651Smarc app = hashalias(name); 9053651Smarc 9153651Smarc for (ap = *app; ap; app = &(ap->next), ap = ap->next) { 9253651Smarc if (equal(name, ap->name)) { 9353651Smarc /* 9453651Smarc * if the alias is currently in use (i.e. its 9553651Smarc * buffer is being used by the input routine) we 9653651Smarc * just null out the name instead of freeing it. 9753651Smarc * We could clear it out later, but this situation 9853651Smarc * is so rare that it hardly seems worth it. 9953651Smarc */ 10053651Smarc if (ap->flag & ALIASINUSE) 10153651Smarc *ap->name = '\0'; 10253651Smarc else { 10353651Smarc INTOFF; 10453651Smarc *app = ap->next; 10553651Smarc ckfree(ap->name); 10653651Smarc ckfree(ap->val); 10753651Smarc ckfree(ap); 10853651Smarc INTON; 10953651Smarc } 11053651Smarc return (0); 11153651Smarc } 11253651Smarc } 11353651Smarc 11453651Smarc return (1); 11553651Smarc } 11653651Smarc 11753651Smarc #ifdef mkinit 11853651Smarc MKINIT void rmaliases(); 11953651Smarc 12053651Smarc SHELLPROC { 12153651Smarc rmaliases(); 12253651Smarc } 12353651Smarc #endif 12453651Smarc 12553651Smarc void 12653651Smarc rmaliases() { 12753651Smarc struct alias *ap, *tmp; 12853651Smarc int i; 12953651Smarc 13053651Smarc INTOFF; 13153651Smarc for (i = 0; i < ATABSIZE; i++) { 13253651Smarc ap = atab[i]; 13353651Smarc atab[i] = NULL; 13453651Smarc while (ap) { 13553651Smarc ckfree(ap->name); 13653651Smarc ckfree(ap->val); 13753651Smarc tmp = ap; 13853651Smarc ap = ap->next; 13953651Smarc ckfree(tmp); 14053651Smarc } 14153651Smarc } 14253651Smarc INTON; 14353651Smarc } 14453651Smarc 14553651Smarc struct alias * 14653651Smarc lookupalias(name, check) 14753651Smarc char *name; 14853651Smarc { 14953651Smarc struct alias *ap = *hashalias(name); 15053651Smarc 15153651Smarc for (; ap; ap = ap->next) { 15253651Smarc if (equal(name, ap->name)) { 15353651Smarc if (check && (ap->flag & ALIASINUSE)) 15453651Smarc return (NULL); 15553651Smarc return (ap); 15653651Smarc } 15753651Smarc } 15853651Smarc 15953651Smarc return (NULL); 16053651Smarc } 16153651Smarc 16253651Smarc /* 16353651Smarc * TODO - sort output 16453651Smarc */ 16553651Smarc aliascmd(argc, argv) 16653651Smarc char **argv; 16753651Smarc { 16853651Smarc char *n, *v; 16953651Smarc int ret = 0; 17053651Smarc struct alias *ap; 17153651Smarc 17253651Smarc if (argc == 1) { 17353651Smarc int i; 17453651Smarc 17553651Smarc for (i = 0; i < ATABSIZE; i++) 17653651Smarc for (ap = atab[i]; ap; ap = ap->next) { 17753651Smarc if (*ap->name != '\0') 17853651Smarc out1fmt("alias %s=%s\n", ap->name, ap->val); 17953651Smarc } 18053651Smarc return (0); 18153651Smarc } 18253651Smarc while (n = *++argv) { 18353651Smarc if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */ 18453651Smarc if ((ap = lookupalias(n, 0)) == NULL) { 18553651Smarc outfmt(out2, "alias: %s not found\n", n); 18653651Smarc ret = 1; 18753651Smarc } else 18853651Smarc out1fmt("alias %s=%s\n", n, ap->val); 18953651Smarc else { 19053651Smarc *v++ = '\0'; 19153651Smarc setalias(n, v); 19253651Smarc } 19353651Smarc } 19453651Smarc 19553651Smarc return (ret); 19653651Smarc } 19753651Smarc 19853651Smarc unaliascmd(argc, argv) 19953651Smarc char **argv; 20053651Smarc { 20153651Smarc int i; 20253651Smarc 20353651Smarc while ((i = nextopt("a")) != '\0') { 20453651Smarc if (i == 'a') { 20553651Smarc rmaliases(); 20653651Smarc return (0); 20753651Smarc } 20853651Smarc } 20953651Smarc for (i = 0; *argptr; argptr++) 21053651Smarc i = unalias(*argptr); 21153651Smarc 21253651Smarc return (i); 21353651Smarc } 21453651Smarc 21553651Smarc STATIC struct alias ** 21653651Smarc hashalias(p) 21753651Smarc register char *p; 21853651Smarc { 21953651Smarc unsigned int hashval; 22053651Smarc 22153651Smarc hashval = *p << 4; 22253651Smarc while (*p) 22353651Smarc hashval+= *p++; 22453651Smarc return &atab[hashval % ATABSIZE]; 22553651Smarc } 226