alias.c revision 8855
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 * 3. All advertising materials mentioning features or use of this software 171556Srgrimes * must display the following acknowledgement: 181556Srgrimes * This product includes software developed by the University of 191556Srgrimes * California, Berkeley and its contributors. 201556Srgrimes * 4. Neither the name of the University nor the names of its contributors 211556Srgrimes * may be used to endorse or promote products derived from this software 221556Srgrimes * without specific prior written permission. 231556Srgrimes * 241556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341556Srgrimes * SUCH DAMAGE. 353044Sdg * 368855Srgrimes * $Id: alias.c,v 1.2 1994/09/24 02:57:20 davidg Exp $ 371556Srgrimes */ 381556Srgrimes 391556Srgrimes#ifndef lint 401556Srgrimesstatic char sccsid[] = "@(#)alias.c 8.1 (Berkeley) 5/31/93"; 411556Srgrimes#endif /* not lint */ 421556Srgrimes 431556Srgrimes#include "shell.h" 441556Srgrimes#include "input.h" 451556Srgrimes#include "output.h" 461556Srgrimes#include "error.h" 471556Srgrimes#include "memalloc.h" 481556Srgrimes#include "mystring.h" 491556Srgrimes#include "alias.h" 501556Srgrimes#include "options.h" /* XXX for argptr (should remove?) */ 511556Srgrimes 521556Srgrimes#define ATABSIZE 39 531556Srgrimes 541556Srgrimesstruct alias *atab[ATABSIZE]; 551556Srgrimes 561556SrgrimesSTATIC struct alias **hashalias __P((char *)); 571556Srgrimes 581556SrgrimesSTATIC 591556Srgrimessetalias(name, val) 601556Srgrimes char *name, *val; 611556Srgrimes { 621556Srgrimes struct alias *ap, **app; 631556Srgrimes 641556Srgrimes app = hashalias(name); 651556Srgrimes for (ap = *app; ap; ap = ap->next) { 661556Srgrimes if (equal(name, ap->name)) { 671556Srgrimes INTOFF; 681556Srgrimes ckfree(ap->val); 691556Srgrimes ap->val = savestr(val); 701556Srgrimes INTON; 711556Srgrimes return; 721556Srgrimes } 731556Srgrimes } 741556Srgrimes /* not found */ 751556Srgrimes INTOFF; 761556Srgrimes ap = ckmalloc(sizeof (struct alias)); 771556Srgrimes ap->name = savestr(name); 781556Srgrimes /* 791556Srgrimes * XXX - HACK: in order that the parser will not finish reading the 801556Srgrimes * alias value off the input before processing the next alias, we 811556Srgrimes * dummy up an extra space at the end of the alias. This is a crock 821556Srgrimes * and should be re-thought. The idea (if you feel inclined to help) 831556Srgrimes * is to avoid alias recursions. The mechanism used is: when 841556Srgrimes * expanding an alias, the value of the alias is pushed back on the 851556Srgrimes * input as a string and a pointer to the alias is stored with the 861556Srgrimes * string. The alias is marked as being in use. When the input 871556Srgrimes * routine finishes reading the string, it markes the alias not 881556Srgrimes * in use. The problem is synchronization with the parser. Since 891556Srgrimes * it reads ahead, the alias is marked not in use before the 901556Srgrimes * resulting token(s) is next checked for further alias sub. The 911556Srgrimes * H A C K is that we add a little fluff after the alias value 921556Srgrimes * so that the string will not be exhausted. This is a good 931556Srgrimes * idea ------- ***NOT*** 941556Srgrimes */ 951556Srgrimes#ifdef notyet 961556Srgrimes ap->val = savestr(val); 971556Srgrimes#else /* hack */ 981556Srgrimes { 991556Srgrimes int len = strlen(val); 1001556Srgrimes ap->val = ckmalloc(len + 2); 1011556Srgrimes bcopy(val, ap->val, len); 1021556Srgrimes ap->val[len] = ' '; /* fluff */ 1031556Srgrimes ap->val[len+1] = '\0'; 1041556Srgrimes } 1051556Srgrimes#endif 1061556Srgrimes ap->next = *app; 1071556Srgrimes *app = ap; 1081556Srgrimes INTON; 1091556Srgrimes} 1101556Srgrimes 1111556SrgrimesSTATIC int 1121556Srgrimesunalias(name) 1131556Srgrimes char *name; 1141556Srgrimes { 1151556Srgrimes struct alias *ap, **app; 1161556Srgrimes 1171556Srgrimes app = hashalias(name); 1181556Srgrimes 1191556Srgrimes for (ap = *app; ap; app = &(ap->next), ap = ap->next) { 1201556Srgrimes if (equal(name, ap->name)) { 1211556Srgrimes /* 1221556Srgrimes * if the alias is currently in use (i.e. its 1231556Srgrimes * buffer is being used by the input routine) we 1241556Srgrimes * just null out the name instead of freeing it. 1251556Srgrimes * We could clear it out later, but this situation 1261556Srgrimes * is so rare that it hardly seems worth it. 1271556Srgrimes */ 1281556Srgrimes if (ap->flag & ALIASINUSE) 1291556Srgrimes *ap->name = '\0'; 1301556Srgrimes else { 1311556Srgrimes INTOFF; 1321556Srgrimes *app = ap->next; 1331556Srgrimes ckfree(ap->name); 1341556Srgrimes ckfree(ap->val); 1351556Srgrimes ckfree(ap); 1361556Srgrimes INTON; 1371556Srgrimes } 1381556Srgrimes return (0); 1391556Srgrimes } 1401556Srgrimes } 1411556Srgrimes 1421556Srgrimes return (1); 1431556Srgrimes} 1441556Srgrimes 1451556Srgrimes#ifdef mkinit 1461556SrgrimesMKINIT void rmaliases(); 1471556Srgrimes 1481556SrgrimesSHELLPROC { 1491556Srgrimes rmaliases(); 1501556Srgrimes} 1511556Srgrimes#endif 1521556Srgrimes 1531556Srgrimesvoid 1541556Srgrimesrmaliases() { 1551556Srgrimes struct alias *ap, *tmp; 1561556Srgrimes int i; 1571556Srgrimes 1581556Srgrimes INTOFF; 1591556Srgrimes for (i = 0; i < ATABSIZE; i++) { 1601556Srgrimes ap = atab[i]; 1611556Srgrimes atab[i] = NULL; 1621556Srgrimes while (ap) { 1631556Srgrimes ckfree(ap->name); 1641556Srgrimes ckfree(ap->val); 1651556Srgrimes tmp = ap; 1661556Srgrimes ap = ap->next; 1671556Srgrimes ckfree(tmp); 1681556Srgrimes } 1691556Srgrimes } 1701556Srgrimes INTON; 1711556Srgrimes} 1721556Srgrimes 1731556Srgrimesstruct alias * 1741556Srgrimeslookupalias(name, check) 1751556Srgrimes char *name; 1761556Srgrimes { 1771556Srgrimes struct alias *ap = *hashalias(name); 1781556Srgrimes 1791556Srgrimes for (; ap; ap = ap->next) { 1801556Srgrimes if (equal(name, ap->name)) { 1811556Srgrimes if (check && (ap->flag & ALIASINUSE)) 1821556Srgrimes return (NULL); 1831556Srgrimes return (ap); 1841556Srgrimes } 1851556Srgrimes } 1861556Srgrimes 1871556Srgrimes return (NULL); 1881556Srgrimes} 1891556Srgrimes 1901556Srgrimes/* 1911556Srgrimes * TODO - sort output 1921556Srgrimes */ 1931556Srgrimesaliascmd(argc, argv) 1941556Srgrimes char **argv; 1951556Srgrimes { 1961556Srgrimes char *n, *v; 1971556Srgrimes int ret = 0; 1981556Srgrimes struct alias *ap; 1991556Srgrimes 2001556Srgrimes if (argc == 1) { 2011556Srgrimes int i; 2021556Srgrimes 2031556Srgrimes for (i = 0; i < ATABSIZE; i++) 2041556Srgrimes for (ap = atab[i]; ap; ap = ap->next) { 2051556Srgrimes if (*ap->name != '\0') 2061556Srgrimes out1fmt("alias %s=%s\n", ap->name, ap->val); 2071556Srgrimes } 2081556Srgrimes return (0); 2091556Srgrimes } 2101556Srgrimes while (n = *++argv) { 2111556Srgrimes if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */ 2121556Srgrimes if ((ap = lookupalias(n, 0)) == NULL) { 2131556Srgrimes outfmt(out2, "alias: %s not found\n", n); 2141556Srgrimes ret = 1; 2151556Srgrimes } else 2161556Srgrimes out1fmt("alias %s=%s\n", n, ap->val); 2171556Srgrimes else { 2181556Srgrimes *v++ = '\0'; 2191556Srgrimes setalias(n, v); 2201556Srgrimes } 2211556Srgrimes } 2221556Srgrimes 2231556Srgrimes return (ret); 2241556Srgrimes} 2251556Srgrimes 2261556Srgrimesunaliascmd(argc, argv) 2271556Srgrimes char **argv; 2281556Srgrimes { 2291556Srgrimes int i; 2308855Srgrimes 2311556Srgrimes while ((i = nextopt("a")) != '\0') { 2321556Srgrimes if (i == 'a') { 2331556Srgrimes rmaliases(); 2341556Srgrimes return (0); 2351556Srgrimes } 2361556Srgrimes } 2371556Srgrimes for (i = 0; *argptr; argptr++) 2381556Srgrimes i = unalias(*argptr); 2391556Srgrimes 2401556Srgrimes return (i); 2411556Srgrimes} 2421556Srgrimes 2431556SrgrimesSTATIC struct alias ** 2441556Srgrimeshashalias(p) 2451556Srgrimes register char *p; 2461556Srgrimes { 2471556Srgrimes unsigned int hashval; 2481556Srgrimes 2491556Srgrimes hashval = *p << 4; 2501556Srgrimes while (*p) 2511556Srgrimes hashval+= *p++; 2521556Srgrimes return &atab[hashval % ATABSIZE]; 2531556Srgrimes} 254