alias.c revision 1556
180708Sjake/*- 280708Sjake * Copyright (c) 1993 3223126Smarius * The Regents of the University of California. All rights reserved. 480708Sjake * 580708Sjake * This code is derived from software contributed to Berkeley by 680708Sjake * Kenneth Almquist. 780708Sjake * 880708Sjake * Redistribution and use in source and binary forms, with or without 980708Sjake * modification, are permitted provided that the following conditions 1080708Sjake * are met: 1180708Sjake * 1. Redistributions of source code must retain the above copyright 1280708Sjake * notice, this list of conditions and the following disclaimer. 1380708Sjake * 2. Redistributions in binary form must reproduce the above copyright 1480708Sjake * notice, this list of conditions and the following disclaimer in the 1581334Sobrien * documentation and/or other materials provided with the distribution. 1680708Sjake * 3. All advertising materials mentioning features or use of this software 1780708Sjake * must display the following acknowledgement: 1881334Sobrien * This product includes software developed by the University of 1980708Sjake * California, Berkeley and its contributors. 2080708Sjake * 4. Neither the name of the University nor the names of its contributors 2180708Sjake * may be used to endorse or promote products derived from this software 2280708Sjake * without specific prior written permission. 2380708Sjake * 2480708Sjake * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2580708Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2680708Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2780708Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2880708Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2980708Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3080708Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3180708Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3280708Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33183142Smarius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34183142Smarius * SUCH DAMAGE. 35182730Smarius */ 36182730Smarius 37182730Smarius#ifndef lint 38182730Smariusstatic char sccsid[] = "@(#)alias.c 8.1 (Berkeley) 5/31/93"; 3989051Sjake#endif /* not lint */ 4089051Sjake 4189051Sjake#include "shell.h" 42222813Sattilio#include "input.h" 43209695Smarius#include "output.h" 44209695Smarius#include "error.h" 45245850Smarius#include "memalloc.h" 46209695Smarius#include "mystring.h" 4791157Sjake#include "alias.h" 48169730Skan#include "options.h" /* XXX for argptr (should remove?) */ 4991617Sjake 5091157Sjake#define ATABSIZE 39 51170846Smarius 52170846Smariusstruct alias *atab[ATABSIZE]; 53170846Smarius 54170846SmariusSTATIC struct alias **hashalias __P((char *)); 55170846Smarius 56170846SmariusSTATIC 5789051Sjakesetalias(name, val) 58169796Smarius char *name, *val; 59170846Smarius { 60169796Smarius struct alias *ap, **app; 6189051Sjake 6289051Sjake app = hashalias(name); 63178048Smarius for (ap = *app; ap; ap = ap->next) { 64210601Smav if (equal(name, ap->name)) { 6589051Sjake INTOFF; 66196196Sattilio ckfree(ap->val); 6789051Sjake ap->val = savestr(val); 68135943Skensmith INTON; 6989051Sjake return; 7089051Sjake } 7191783Sjake } 7289051Sjake /* not found */ 7389051Sjake INTOFF; 7491783Sjake ap = ckmalloc(sizeof (struct alias)); 7591617Sjake ap->name = savestr(name); 76182730Smarius /* 7791617Sjake * XXX - HACK: in order that the parser will not finish reading the 7891617Sjake * alias value off the input before processing the next alias, we 7989051Sjake * dummy up an extra space at the end of the alias. This is a crock 8089051Sjake * and should be re-thought. The idea (if you feel inclined to help) 8197001Sjake * is to avoid alias recursions. The mechanism used is: when 82222813Sattilio * expanding an alias, the value of the alias is pushed back on the 83113238Sjake * input as a string and a pointer to the alias is stored with the 8497001Sjake * string. The alias is marked as being in use. When the input 8597001Sjake * routine finishes reading the string, it markes the alias not 86211071Smarius * in use. The problem is synchronization with the parser. Since 87222813Sattilio * it reads ahead, the alias is marked not in use before the 88211071Smarius * resulting token(s) is next checked for further alias sub. The 89211071Smarius * H A C K is that we add a little fluff after the alias value 90211071Smarius * so that the string will not be exhausted. This is a good 9189051Sjake * idea ------- ***NOT*** 92222813Sattilio */ 9391783Sjake#ifdef notyet 9489051Sjake ap->val = savestr(val); 9589051Sjake#else /* hack */ 9689051Sjake { 9789051Sjake int len = strlen(val); 9889051Sjake ap->val = ckmalloc(len + 2); 9989051Sjake bcopy(val, ap->val, len); 10089051Sjake ap->val[len] = ' '; /* fluff */ 101152022Sjhb ap->val[len+1] = '\0'; 102152022Sjhb } 10389051Sjake#endif 10492199Sjake ap->next = *app; 10589051Sjake *app = ap; 106222813Sattilio INTON; 107170846Smarius} 108211050Smarius 109211050SmariusSTATIC int 11089051Sjakeunalias(name) 111204152Smarius char *name; 11291617Sjake { 113108187Sjake struct alias *ap, **app; 114211071Smarius 115108187Sjake app = hashalias(name); 11689051Sjake 11791617Sjake for (ap = *app; ap; app = &(ap->next), ap = ap->next) { 11891617Sjake if (equal(name, ap->name)) { 11991617Sjake /* 12091617Sjake * if the alias is currently in use (i.e. its 12191617Sjake * buffer is being used by the input routine) we 12291617Sjake * just null out the name instead of freeing it. 12391617Sjake * We could clear it out later, but this situation 124112399Sjake * is so rare that it hardly seems worth it. 125112399Sjake */ 126112399Sjake if (ap->flag & ALIASINUSE) 127112399Sjake *ap->name = '\0'; 12889051Sjake else { 129211071Smarius INTOFF; 130211071Smarius *app = ap->next; 131211071Smarius ckfree(ap->name); 132211071Smarius ckfree(ap->val); 13389051Sjake ckfree(ap); 13489051Sjake INTON; 13589051Sjake } 13689051Sjake return (0); 137183142Smarius } 138183142Smarius } 139183142Smarius 140223126Smarius return (1); 14189051Sjake} 142223126Smarius 143223126Smarius#ifdef mkinit 144223126SmariusMKINIT void rmaliases(); 145183142Smarius 146183142SmariusSHELLPROC { 147183142Smarius rmaliases(); 148222813Sattilio} 149183142Smarius#endif 150183142Smarius 151183142Smariusvoid 152183142Smariusrmaliases() { 153183142Smarius struct alias *ap, *tmp; 154210939Sjhb int i; 155210939Sjhb 156210939Sjhb INTOFF; 157210939Sjhb for (i = 0; i < ATABSIZE; i++) { 158211050Smarius ap = atab[i]; 159210939Sjhb atab[i] = NULL; 160210939Sjhb while (ap) { 161108187Sjake ckfree(ap->name); 162108187Sjake ckfree(ap->val); 16397001Sjake tmp = ap; 164113238Sjake ap = ap->next; 16597001Sjake ckfree(tmp); 16697001Sjake } 16797001Sjake } 16897001Sjake INTON; 16997001Sjake} 170209695Smarius 17197001Sjakestruct alias * 172239864Smariuslookupalias(name, check) 17397001Sjake char *name; 174223126Smarius { 17597001Sjake struct alias *ap = *hashalias(name); 176223126Smarius 17797001Sjake for (; ap; ap = ap->next) { 17897001Sjake if (equal(name, ap->name)) { 17997001Sjake if (check && (ap->flag & ALIASINUSE)) 18097001Sjake return (NULL); 181113238Sjake return (ap); 18297001Sjake } 18397001Sjake } 18497001Sjake 18597001Sjake return (NULL); 18697001Sjake} 187209695Smarius 18897001Sjake/* 189239864Smarius * TODO - sort output 19097001Sjake */ 191223126Smariusaliascmd(argc, argv) 19297001Sjake char **argv; 193223126Smarius { 19497001Sjake char *n, *v; 19597001Sjake int ret = 0; 19697001Sjake struct alias *ap; 19789051Sjake 198211071Smarius if (argc == 1) { 199211071Smarius int i; 200211071Smarius 201211071Smarius for (i = 0; i < ATABSIZE; i++) 202211071Smarius for (ap = atab[i]; ap; ap = ap->next) { 203211071Smarius if (*ap->name != '\0') 204211071Smarius out1fmt("alias %s=%s\n", ap->name, ap->val); 205211071Smarius } 206245850Smarius return (0); 207223126Smarius } 208211071Smarius while (n = *++argv) { 209211071Smarius if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */ 210211071Smarius if ((ap = lookupalias(n, 0)) == NULL) { 211211071Smarius outfmt(out2, "alias: %s not found\n", n); 212211071Smarius ret = 1; 213211071Smarius } else 21491783Sjake out1fmt("alias %s=%s\n", n, ap->val); 21589051Sjake else { 21689051Sjake *v++ = '\0'; 217222813Sattilio setalias(n, v); 21889051Sjake } 21991783Sjake } 22089051Sjake 221209695Smarius return (ret); 222222813Sattilio} 223223126Smarius 224223126Smariusunaliascmd(argc, argv) 225222813Sattilio char **argv; 226209695Smarius { 22791783Sjake int i; 228209695Smarius 22989051Sjake while ((i = nextopt("a")) != '\0') { 230239864Smarius if (i == 'a') { 231222813Sattilio rmaliases(); 23291783Sjake return (0); 23391783Sjake } 23491783Sjake } 23592199Sjake for (i = 0; *argptr; argptr++) 23689051Sjake i = unalias(*argptr); 23789051Sjake 23889051Sjake return (i); 239100718Sjake} 24089051Sjake 24189051SjakeSTATIC struct alias ** 242222813Sattiliohashalias(p) 24389051Sjake register char *p; 24491783Sjake { 24589051Sjake unsigned int hashval; 246209695Smarius 247222813Sattilio hashval = *p << 4; 248223126Smarius while (*p) 249223126Smarius hashval+= *p++; 250222813Sattilio return &atab[hashval % ATABSIZE]; 251209695Smarius} 25291783Sjake