Subversion Repositories HelenOS

Rev

Rev 2714 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*  $NetBSD: alias.c,v 1.10 1998/05/20 00:27:56 christos Exp $  */
  2.  
  3. /*-
  4.  * Copyright (c) 1993
  5.  *  The Regents of the University of California.  All rights reserved.
  6.  *
  7.  * This code is derived from software contributed to Berkeley by
  8.  * Kenneth Almquist.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *  This product includes software developed by the University of
  21.  *  California, Berkeley and its contributors.
  22.  * 4. Neither the name of the University nor the names of its contributors
  23.  *    may be used to endorse or promote products derived from this software
  24.  *    without specific prior written permission.
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  */
  38.  
  39. //#include <sys/cdefs.h>
  40. #ifndef lint
  41. #if 0
  42. static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95";
  43. #else
  44. __RCSID("$NetBSD: alias.c,v 1.10 1998/05/20 00:27:56 christos Exp $");
  45. #endif
  46. #endif /* not lint */
  47.  
  48. #include <stdlib.h>
  49. #include "shell.h"
  50. #include "input.h"
  51. #include "output.h"
  52. #include "error.h"
  53. #include "memalloc.h"
  54. #include "mystring.h"
  55. #include "alias.h"
  56. #include "options.h"    /* XXX for argptr (should remove?) */
  57.  
  58. #define ATABSIZE 39
  59.  
  60. struct alias *atab[ATABSIZE];
  61.  
  62. STATIC void setalias (char *, char *);
  63. STATIC int unalias (char *);
  64. STATIC struct alias **hashalias (char *);
  65.  
  66. STATIC
  67. void
  68. setalias(char *name, char *val)
  69. {
  70.     struct alias *ap, **app;
  71.  
  72.     app = hashalias(name);
  73.     for (ap = *app; ap; ap = ap->next) {
  74.         if (equal(name, ap->name)) {
  75.             INTOFF;
  76.             ckfree(ap->val);
  77.             ap->val = savestr(val);
  78.             INTON;
  79.             return;
  80.         }
  81.     }
  82.     /* not found */
  83.     INTOFF;
  84.     ap = ckmalloc(sizeof (struct alias));
  85.     ap->name = savestr(name);
  86.     /*
  87.      * XXX - HACK: in order that the parser will not finish reading the
  88.      * alias value off the input before processing the next alias, we
  89.      * dummy up an extra space at the end of the alias.  This is a crock
  90.      * and should be re-thought.  The idea (if you feel inclined to help)
  91.      * is to avoid alias recursions.  The mechanism used is: when
  92.      * expanding an alias, the value of the alias is pushed back on the
  93.      * input as a string and a pointer to the alias is stored with the
  94.      * string.  The alias is marked as being in use.  When the input
  95.      * routine finishes reading the string, it markes the alias not
  96.      * in use.  The problem is synchronization with the parser.  Since
  97.      * it reads ahead, the alias is marked not in use before the
  98.      * resulting token(s) is next checked for further alias sub.  The
  99.      * H A C K is that we add a little fluff after the alias value
  100.      * so that the string will not be exhausted.  This is a good
  101.      * idea ------- ***NOT***
  102.      */
  103. #ifdef notyet
  104.     ap->val = savestr(val);
  105. #else /* hack */
  106.     {
  107.     int len = strlen(val);
  108.     ap->val = ckmalloc(len + 2);
  109.     memcpy(ap->val, val, len);
  110.     ap->val[len] = ' '; /* fluff */
  111.     ap->val[len+1] = '\0';
  112.     }
  113. #endif
  114.     ap->next = *app;
  115.     *app = ap;
  116.     INTON;
  117. }
  118.  
  119. STATIC int
  120. unalias(name)
  121.     char *name;
  122.     {
  123.     struct alias *ap, **app;
  124.  
  125.     app = hashalias(name);
  126.  
  127.     for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
  128.         if (equal(name, ap->name)) {
  129.             /*
  130.              * if the alias is currently in use (i.e. its
  131.              * buffer is being used by the input routine) we
  132.              * just null out the name instead of freeing it.
  133.              * We could clear it out later, but this situation
  134.              * is so rare that it hardly seems worth it.
  135.              */
  136.             if (ap->flag & ALIASINUSE)
  137.                 *ap->name = '\0';
  138.             else {
  139.                 INTOFF;
  140.                 *app = ap->next;
  141.                 ckfree(ap->name);
  142.                 ckfree(ap->val);
  143.                 ckfree(ap);
  144.                 INTON;
  145.             }
  146.             return (0);
  147.         }
  148.     }
  149.  
  150.     return (1);
  151. }
  152.  
  153. #ifdef mkinit
  154. MKINIT void rmaliases (void);
  155.  
  156. SHELLPROC {
  157.     rmaliases();
  158. }
  159. #endif
  160.  
  161. void
  162. rmaliases() {
  163.     struct alias *ap, *tmp;
  164.     int i;
  165.  
  166.     INTOFF;
  167.     for (i = 0; i < ATABSIZE; i++) {
  168.         ap = atab[i];
  169.         atab[i] = NULL;
  170.         while (ap) {
  171.             ckfree(ap->name);
  172.             ckfree(ap->val);
  173.             tmp = ap;
  174.             ap = ap->next;
  175.             ckfree(tmp);
  176.         }
  177.     }
  178.     INTON;
  179. }
  180.  
  181. struct alias *
  182. lookupalias(name, check)
  183.     char *name;
  184.     int check;
  185. {
  186.     struct alias *ap = *hashalias(name);
  187.  
  188.     for (; ap; ap = ap->next) {
  189.         if (equal(name, ap->name)) {
  190.             if (check && (ap->flag & ALIASINUSE))
  191.                 return (NULL);
  192.             return (ap);
  193.         }
  194.     }
  195.  
  196.     return (NULL);
  197. }
  198.  
  199. /*
  200.  * TODO - sort output
  201.  */
  202. int
  203. aliascmd(argc, argv)
  204.     int argc;
  205.     char **argv;
  206. {
  207.     char *n, *v;
  208.     int ret = 0;
  209.     struct alias *ap;
  210.  
  211.     if (argc == 1) {
  212.         int i;
  213.  
  214.         for (i = 0; i < ATABSIZE; i++)
  215.             for (ap = atab[i]; ap; ap = ap->next) {
  216.                 if (*ap->name != '\0')
  217.                     out1fmt("alias %s=%s\n", ap->name, ap->val);
  218.             }
  219.         return (0);
  220.     }
  221.     while ((n = *++argv) != NULL) {
  222.         if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
  223.             if ((ap = lookupalias(n, 0)) == NULL) {
  224.                 outfmt(out2, "alias: %s not found\n", n);
  225.                 ret = 1;
  226.             } else
  227.                 out1fmt("alias %s=%s\n", n, ap->val);
  228.         }
  229.         else {
  230.             *v++ = '\0';
  231.             setalias(n, v);
  232.         }
  233.     }
  234.  
  235.     return (ret);
  236. }
  237.  
  238. int
  239. unaliascmd(argc, argv)
  240.     int argc;
  241.     char **argv;
  242. {
  243.     int i;
  244.  
  245.     while ((i = nextopt("a")) != '\0') {
  246.         if (i == 'a') {
  247.             rmaliases();
  248.             return (0);
  249.         }
  250.     }
  251.     for (i = 0; *argptr; argptr++)
  252.         i = unalias(*argptr);
  253.  
  254.     return (i);
  255. }
  256.  
  257. STATIC struct alias **
  258. hashalias(p)
  259.     char *p;
  260.     {
  261.     unsigned int hashval;
  262.  
  263.     hashval = *p << 4;
  264.     while (*p)
  265.         hashval+= *p++;
  266.     return &atab[hashval % ATABSIZE];
  267. }
  268.