alias.c revision 90111
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. 351556Srgrimes */ 361556Srgrimes 371556Srgrimes#ifndef lint 3836150Scharnier#if 0 3936150Scharnierstatic char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95"; 4036150Scharnier#endif 4136150Scharnierstatic const char rcsid[] = 4250471Speter "$FreeBSD: head/bin/sh/alias.c 90111 2002-02-02 06:50:57Z imp $"; 431556Srgrimes#endif /* not lint */ 441556Srgrimes 4517987Speter#include <stdlib.h> 461556Srgrimes#include "shell.h" 471556Srgrimes#include "input.h" 481556Srgrimes#include "output.h" 491556Srgrimes#include "error.h" 501556Srgrimes#include "memalloc.h" 511556Srgrimes#include "mystring.h" 521556Srgrimes#include "alias.h" 531556Srgrimes#include "options.h" /* XXX for argptr (should remove?) */ 541556Srgrimes 551556Srgrimes#define ATABSIZE 39 561556Srgrimes 571556Srgrimesstruct alias *atab[ATABSIZE]; 581556Srgrimes 5990111SimpSTATIC void setalias(char *, char *); 6090111SimpSTATIC int unalias(char *); 6190111SimpSTATIC struct alias **hashalias(char *); 621556Srgrimes 631556SrgrimesSTATIC 6417987Spetervoid 6590111Simpsetalias(char *name, char *val) 6617987Speter{ 671556Srgrimes struct alias *ap, **app; 681556Srgrimes 691556Srgrimes app = hashalias(name); 701556Srgrimes for (ap = *app; ap; ap = ap->next) { 711556Srgrimes if (equal(name, ap->name)) { 721556Srgrimes INTOFF; 731556Srgrimes ckfree(ap->val); 741556Srgrimes ap->val = savestr(val); 751556Srgrimes INTON; 761556Srgrimes return; 771556Srgrimes } 781556Srgrimes } 791556Srgrimes /* not found */ 801556Srgrimes INTOFF; 811556Srgrimes ap = ckmalloc(sizeof (struct alias)); 821556Srgrimes ap->name = savestr(name); 831556Srgrimes /* 841556Srgrimes * XXX - HACK: in order that the parser will not finish reading the 851556Srgrimes * alias value off the input before processing the next alias, we 861556Srgrimes * dummy up an extra space at the end of the alias. This is a crock 871556Srgrimes * and should be re-thought. The idea (if you feel inclined to help) 881556Srgrimes * is to avoid alias recursions. The mechanism used is: when 891556Srgrimes * expanding an alias, the value of the alias is pushed back on the 901556Srgrimes * input as a string and a pointer to the alias is stored with the 911556Srgrimes * string. The alias is marked as being in use. When the input 9246684Skris * routine finishes reading the string, it marks the alias not 931556Srgrimes * in use. The problem is synchronization with the parser. Since 941556Srgrimes * it reads ahead, the alias is marked not in use before the 951556Srgrimes * resulting token(s) is next checked for further alias sub. The 961556Srgrimes * H A C K is that we add a little fluff after the alias value 971556Srgrimes * so that the string will not be exhausted. This is a good 981556Srgrimes * idea ------- ***NOT*** 991556Srgrimes */ 1001556Srgrimes#ifdef notyet 1011556Srgrimes ap->val = savestr(val); 1021556Srgrimes#else /* hack */ 1031556Srgrimes { 1041556Srgrimes int len = strlen(val); 1051556Srgrimes ap->val = ckmalloc(len + 2); 10617987Speter memcpy(ap->val, val, len); 1071556Srgrimes ap->val[len] = ' '; /* fluff */ 1081556Srgrimes ap->val[len+1] = '\0'; 1091556Srgrimes } 1101556Srgrimes#endif 11163223Ssada ap->flag = 0; 1121556Srgrimes ap->next = *app; 1131556Srgrimes *app = ap; 1141556Srgrimes INTON; 1151556Srgrimes} 1161556Srgrimes 1171556SrgrimesSTATIC int 11890111Simpunalias(char *name) 11990111Simp{ 1201556Srgrimes struct alias *ap, **app; 1211556Srgrimes 1221556Srgrimes app = hashalias(name); 1231556Srgrimes 1241556Srgrimes for (ap = *app; ap; app = &(ap->next), ap = ap->next) { 1251556Srgrimes if (equal(name, ap->name)) { 1261556Srgrimes /* 1271556Srgrimes * if the alias is currently in use (i.e. its 1281556Srgrimes * buffer is being used by the input routine) we 1291556Srgrimes * just null out the name instead of freeing it. 1301556Srgrimes * We could clear it out later, but this situation 1311556Srgrimes * is so rare that it hardly seems worth it. 1321556Srgrimes */ 1331556Srgrimes if (ap->flag & ALIASINUSE) 1341556Srgrimes *ap->name = '\0'; 1351556Srgrimes else { 1361556Srgrimes INTOFF; 1371556Srgrimes *app = ap->next; 1381556Srgrimes ckfree(ap->name); 1391556Srgrimes ckfree(ap->val); 1401556Srgrimes ckfree(ap); 1411556Srgrimes INTON; 1421556Srgrimes } 1431556Srgrimes return (0); 1441556Srgrimes } 1451556Srgrimes } 1461556Srgrimes 1471556Srgrimes return (1); 1481556Srgrimes} 1491556Srgrimes 1501556Srgrimes#ifdef mkinit 1511556SrgrimesMKINIT void rmaliases(); 1521556Srgrimes 1531556SrgrimesSHELLPROC { 1541556Srgrimes rmaliases(); 1551556Srgrimes} 1561556Srgrimes#endif 1571556Srgrimes 1581556Srgrimesvoid 15990111Simprmaliases(void) 16090111Simp{ 1611556Srgrimes struct alias *ap, *tmp; 1621556Srgrimes int i; 1631556Srgrimes 1641556Srgrimes INTOFF; 1651556Srgrimes for (i = 0; i < ATABSIZE; i++) { 1661556Srgrimes ap = atab[i]; 1671556Srgrimes atab[i] = NULL; 1681556Srgrimes while (ap) { 1691556Srgrimes ckfree(ap->name); 1701556Srgrimes ckfree(ap->val); 1711556Srgrimes tmp = ap; 1721556Srgrimes ap = ap->next; 1731556Srgrimes ckfree(tmp); 1741556Srgrimes } 1751556Srgrimes } 1761556Srgrimes INTON; 1771556Srgrimes} 1781556Srgrimes 1791556Srgrimesstruct alias * 18090111Simplookupalias(char *name, int check) 18117987Speter{ 1821556Srgrimes struct alias *ap = *hashalias(name); 1831556Srgrimes 1841556Srgrimes for (; ap; ap = ap->next) { 1851556Srgrimes if (equal(name, ap->name)) { 1861556Srgrimes if (check && (ap->flag & ALIASINUSE)) 1871556Srgrimes return (NULL); 1881556Srgrimes return (ap); 1891556Srgrimes } 1901556Srgrimes } 1911556Srgrimes 1921556Srgrimes return (NULL); 1931556Srgrimes} 1941556Srgrimes 1951556Srgrimes/* 1961556Srgrimes * TODO - sort output 1971556Srgrimes */ 19817987Speterint 19990111Simpaliascmd(int argc, char **argv) 20017987Speter{ 2011556Srgrimes char *n, *v; 2021556Srgrimes int ret = 0; 2031556Srgrimes struct alias *ap; 2041556Srgrimes 2051556Srgrimes if (argc == 1) { 2061556Srgrimes int i; 2071556Srgrimes 2081556Srgrimes for (i = 0; i < ATABSIZE; i++) 2091556Srgrimes for (ap = atab[i]; ap; ap = ap->next) { 2101556Srgrimes if (*ap->name != '\0') 2111556Srgrimes out1fmt("alias %s=%s\n", ap->name, ap->val); 2121556Srgrimes } 2131556Srgrimes return (0); 2141556Srgrimes } 21517987Speter while ((n = *++argv) != NULL) { 2161556Srgrimes if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */ 2171556Srgrimes if ((ap = lookupalias(n, 0)) == NULL) { 2181556Srgrimes outfmt(out2, "alias: %s not found\n", n); 2191556Srgrimes ret = 1; 2201556Srgrimes } else 2211556Srgrimes out1fmt("alias %s=%s\n", n, ap->val); 2221556Srgrimes else { 2231556Srgrimes *v++ = '\0'; 2241556Srgrimes setalias(n, v); 2251556Srgrimes } 2261556Srgrimes } 2271556Srgrimes 2281556Srgrimes return (ret); 2291556Srgrimes} 2301556Srgrimes 23117987Speterint 23290111Simpunaliascmd(int argc __unused, char **argv __unused) 23317987Speter{ 2341556Srgrimes int i; 2358855Srgrimes 2361556Srgrimes while ((i = nextopt("a")) != '\0') { 2371556Srgrimes if (i == 'a') { 2381556Srgrimes rmaliases(); 2391556Srgrimes return (0); 2401556Srgrimes } 2411556Srgrimes } 2421556Srgrimes for (i = 0; *argptr; argptr++) 2431556Srgrimes i = unalias(*argptr); 2441556Srgrimes 2451556Srgrimes return (i); 2461556Srgrimes} 2471556Srgrimes 2481556SrgrimesSTATIC struct alias ** 24990111Simphashalias(char *p) 25090111Simp{ 2511556Srgrimes unsigned int hashval; 2521556Srgrimes 2531556Srgrimes hashval = *p << 4; 2541556Srgrimes while (*p) 2551556Srgrimes hashval+= *p++; 2561556Srgrimes return &atab[hashval % ATABSIZE]; 2571556Srgrimes} 258