11556Srgrimes/*- 21556Srgrimes * Copyright (c) 1993 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * This code is derived from software contributed to Berkeley by 61556Srgrimes * Kenneth Almquist. 71556Srgrimes * 81556Srgrimes * Redistribution and use in source and binary forms, with or without 91556Srgrimes * modification, are permitted provided that the following conditions 101556Srgrimes * are met: 111556Srgrimes * 1. Redistributions of source code must retain the above copyright 121556Srgrimes * notice, this list of conditions and the following disclaimer. 131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141556Srgrimes * notice, this list of conditions and the following disclaimer in the 151556Srgrimes * documentation and/or other materials provided with the distribution. 161556Srgrimes * 4. Neither the name of the University nor the names of its contributors 171556Srgrimes * may be used to endorse or promote products derived from this software 181556Srgrimes * without specific prior written permission. 191556Srgrimes * 201556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301556Srgrimes * SUCH DAMAGE. 311556Srgrimes */ 321556Srgrimes 331556Srgrimes#ifndef lint 3436150Scharnier#if 0 3536150Scharnierstatic char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95"; 3636150Scharnier#endif 371556Srgrimes#endif /* not lint */ 3899110Sobrien#include <sys/cdefs.h> 3999110Sobrien__FBSDID("$FreeBSD$"); 401556Srgrimes 4117987Speter#include <stdlib.h> 421556Srgrimes#include "shell.h" 431556Srgrimes#include "output.h" 441556Srgrimes#include "error.h" 451556Srgrimes#include "memalloc.h" 461556Srgrimes#include "mystring.h" 471556Srgrimes#include "alias.h" 481556Srgrimes#include "options.h" /* XXX for argptr (should remove?) */ 49223060Sjilles#include "builtins.h" 501556Srgrimes 511556Srgrimes#define ATABSIZE 39 521556Srgrimes 53213760Sobrienstatic struct alias *atab[ATABSIZE]; 54213760Sobrienstatic int aliases; 551556Srgrimes 56213811Sobrienstatic void setalias(const char *, const char *); 57213811Sobrienstatic int unalias(const char *); 58213811Sobrienstatic struct alias **hashalias(const char *); 591556Srgrimes 60213811Sobrienstatic 6117987Spetervoid 62200956Sjillessetalias(const char *name, const char *val) 6317987Speter{ 641556Srgrimes struct alias *ap, **app; 651556Srgrimes 661556Srgrimes app = hashalias(name); 671556Srgrimes for (ap = *app; ap; ap = ap->next) { 681556Srgrimes if (equal(name, ap->name)) { 691556Srgrimes INTOFF; 701556Srgrimes ckfree(ap->val); 711556Srgrimes ap->val = savestr(val); 721556Srgrimes INTON; 731556Srgrimes return; 741556Srgrimes } 751556Srgrimes } 761556Srgrimes /* not found */ 771556Srgrimes INTOFF; 781556Srgrimes ap = ckmalloc(sizeof (struct alias)); 791556Srgrimes ap->name = savestr(name); 801556Srgrimes ap->val = savestr(val); 8163223Ssada ap->flag = 0; 821556Srgrimes ap->next = *app; 831556Srgrimes *app = ap; 84190284Sstefanf aliases++; 851556Srgrimes INTON; 861556Srgrimes} 871556Srgrimes 88213811Sobrienstatic int 89179639Srseunalias(const char *name) 9090111Simp{ 911556Srgrimes struct alias *ap, **app; 921556Srgrimes 931556Srgrimes app = hashalias(name); 941556Srgrimes 951556Srgrimes for (ap = *app; ap; app = &(ap->next), ap = ap->next) { 961556Srgrimes if (equal(name, ap->name)) { 971556Srgrimes /* 981556Srgrimes * if the alias is currently in use (i.e. its 991556Srgrimes * buffer is being used by the input routine) we 1001556Srgrimes * just null out the name instead of freeing it. 1011556Srgrimes * We could clear it out later, but this situation 1021556Srgrimes * is so rare that it hardly seems worth it. 1031556Srgrimes */ 1041556Srgrimes if (ap->flag & ALIASINUSE) 1051556Srgrimes *ap->name = '\0'; 1061556Srgrimes else { 1071556Srgrimes INTOFF; 1081556Srgrimes *app = ap->next; 1091556Srgrimes ckfree(ap->name); 1101556Srgrimes ckfree(ap->val); 1111556Srgrimes ckfree(ap); 1121556Srgrimes INTON; 1131556Srgrimes } 114190284Sstefanf aliases--; 1151556Srgrimes return (0); 1161556Srgrimes } 1171556Srgrimes } 1181556Srgrimes 1191556Srgrimes return (1); 1201556Srgrimes} 1211556Srgrimes 122218306Sjillesstatic void 12390111Simprmaliases(void) 12490111Simp{ 1251556Srgrimes struct alias *ap, *tmp; 1261556Srgrimes int i; 1271556Srgrimes 1281556Srgrimes INTOFF; 1291556Srgrimes for (i = 0; i < ATABSIZE; i++) { 1301556Srgrimes ap = atab[i]; 1311556Srgrimes atab[i] = NULL; 1321556Srgrimes while (ap) { 1331556Srgrimes ckfree(ap->name); 1341556Srgrimes ckfree(ap->val); 1351556Srgrimes tmp = ap; 1361556Srgrimes ap = ap->next; 1371556Srgrimes ckfree(tmp); 1381556Srgrimes } 1391556Srgrimes } 140190284Sstefanf aliases = 0; 1411556Srgrimes INTON; 1421556Srgrimes} 1431556Srgrimes 1441556Srgrimesstruct alias * 145200956Sjilleslookupalias(const char *name, int check) 14617987Speter{ 1471556Srgrimes struct alias *ap = *hashalias(name); 1481556Srgrimes 1491556Srgrimes for (; ap; ap = ap->next) { 1501556Srgrimes if (equal(name, ap->name)) { 1511556Srgrimes if (check && (ap->flag & ALIASINUSE)) 1521556Srgrimes return (NULL); 1531556Srgrimes return (ap); 1541556Srgrimes } 1551556Srgrimes } 1561556Srgrimes 1571556Srgrimes return (NULL); 1581556Srgrimes} 1591556Srgrimes 160213811Sobrienstatic int 161190284Sstefanfcomparealiases(const void *p1, const void *p2) 162190284Sstefanf{ 163190284Sstefanf const struct alias *const *a1 = p1; 164190284Sstefanf const struct alias *const *a2 = p2; 165190284Sstefanf 166190284Sstefanf return strcmp((*a1)->name, (*a2)->name); 167190284Sstefanf} 168190284Sstefanf 169213811Sobrienstatic void 170190284Sstefanfprintalias(const struct alias *a) 171190284Sstefanf{ 172190284Sstefanf out1fmt("%s=", a->name); 173190284Sstefanf out1qstr(a->val); 174190284Sstefanf out1c('\n'); 175190284Sstefanf} 176190284Sstefanf 177213811Sobrienstatic void 178190284Sstefanfprintaliases(void) 179190284Sstefanf{ 180190284Sstefanf int i, j; 181190284Sstefanf struct alias **sorted, *ap; 182190284Sstefanf 183264478Sjilles INTOFF; 184190284Sstefanf sorted = ckmalloc(aliases * sizeof(*sorted)); 185190284Sstefanf j = 0; 186190284Sstefanf for (i = 0; i < ATABSIZE; i++) 187190284Sstefanf for (ap = atab[i]; ap; ap = ap->next) 188190284Sstefanf if (*ap->name != '\0') 189190284Sstefanf sorted[j++] = ap; 190190284Sstefanf qsort(sorted, aliases, sizeof(*sorted), comparealiases); 191264478Sjilles for (i = 0; i < aliases; i++) { 192190284Sstefanf printalias(sorted[i]); 193264478Sjilles if (int_pending()) 194264478Sjilles break; 195264478Sjilles } 196190284Sstefanf ckfree(sorted); 197264478Sjilles INTON; 198190284Sstefanf} 199190284Sstefanf 20017987Speterint 201254849Sjillesaliascmd(int argc __unused, char **argv __unused) 20217987Speter{ 2031556Srgrimes char *n, *v; 2041556Srgrimes int ret = 0; 2051556Srgrimes struct alias *ap; 2061556Srgrimes 207254849Sjilles nextopt(""); 208254849Sjilles 209254849Sjilles if (*argptr == NULL) { 210190284Sstefanf printaliases(); 2111556Srgrimes return (0); 2121556Srgrimes } 213254849Sjilles while ((n = *argptr++) != NULL) { 2141556Srgrimes if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */ 2151556Srgrimes if ((ap = lookupalias(n, 0)) == NULL) { 216222684Sjilles warning("%s: not found", n); 2171556Srgrimes ret = 1; 218190284Sstefanf } else 219190284Sstefanf printalias(ap); 2201556Srgrimes else { 2211556Srgrimes *v++ = '\0'; 2221556Srgrimes setalias(n, v); 2231556Srgrimes } 2241556Srgrimes } 2251556Srgrimes 2261556Srgrimes return (ret); 2271556Srgrimes} 2281556Srgrimes 22917987Speterint 23090111Simpunaliascmd(int argc __unused, char **argv __unused) 23117987Speter{ 2321556Srgrimes int i; 2338855Srgrimes 2341556Srgrimes while ((i = nextopt("a")) != '\0') { 2351556Srgrimes if (i == 'a') { 2361556Srgrimes rmaliases(); 2371556Srgrimes return (0); 2381556Srgrimes } 2391556Srgrimes } 2401556Srgrimes for (i = 0; *argptr; argptr++) 241149743Sstefanf i |= unalias(*argptr); 2421556Srgrimes 2431556Srgrimes return (i); 2441556Srgrimes} 2451556Srgrimes 246213811Sobrienstatic struct alias ** 247179639Srsehashalias(const char *p) 24890111Simp{ 2491556Srgrimes unsigned int hashval; 2501556Srgrimes 2511556Srgrimes hashval = *p << 4; 2521556Srgrimes while (*p) 2531556Srgrimes hashval+= *p++; 2541556Srgrimes return &atab[hashval % ATABSIZE]; 2551556Srgrimes} 256