Home | History | Annotate | Line # | Download | only in mail
cmd4.c revision 1.4
      1 /*	$NetBSD: cmd4.c,v 1.4 2008/04/28 20:24:14 martin Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2006 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Anon Ymous.
      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  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 
     33 #include <sys/cdefs.h>
     34 #ifndef lint
     35 #if 0
     36 static char sccsid[] = "@(#)cmd3.c	8.2 (Berkeley) 4/20/95";
     37 #else
     38 __RCSID("$NetBSD: cmd4.c,v 1.4 2008/04/28 20:24:14 martin Exp $");
     39 #endif
     40 #endif /* not lint */
     41 
     42 #include "rcv.h"
     43 #include <util.h>
     44 #include "extern.h"
     45 
     46 /*
     47  * Mail -- a mail program
     48  *
     49  * Still more user commands.
     50  * XXX - should this be renamed smopts.c?
     51  */
     52 
     53 #if 0	/* XXX - debugging stuff - to be removed */
     54 void showname(struct name *);
     55 void
     56 showname(struct name *np)
     57 {
     58 	for (/*EMPTY*/; np; np = np->n_flink)
     59 		(void)printf("np: %p  np->n_type: %d  np->n_name: '%s' (%p)\n",
     60 		    np, np->n_type, np->n_name, np->n_name);
     61 }
     62 
     63 __unused
     64 static void
     65 showsmopts(struct smopts_s *sp)
     66 {
     67 	(void)printf("%s (%p)\n", sp->s_name, sp);
     68 	showname(sp->s_smopts);
     69 }
     70 #endif	/* XXX - debugging stuff - to be removed */
     71 
     72 
     73 static int
     74 hashcase(const char *key)
     75 {
     76 	char *lckey;
     77 	lckey = salloc(strlen(key) + 1);
     78 	istrcpy(lckey, key);
     79 	return hash(lckey);
     80 }
     81 
     82 static struct smopts_s *
     83 findsmopts_core(const char *name)
     84 {
     85 	struct smopts_s *sh;
     86 
     87 	for (sh = smoptstbl[hashcase(name)]; sh; sh = sh->s_link)
     88 		if (strcasecmp(sh->s_name, name) == 0)
     89 			return sh;
     90 	return NULL;
     91 }
     92 
     93 /*
     94  * The exported smopts lookup routine.
     95  */
     96 PUBLIC struct smopts_s *
     97 findsmopts(const char *name, int top_only)
     98 {
     99 	const char *cp;
    100 	struct smopts_s *sh;
    101 
    102 	if ((sh = findsmopts_core(name)) != NULL)
    103 		return sh;
    104 
    105 	if (top_only)
    106 		return NULL;
    107 
    108 	for (cp = strchr(name, '@'); cp; cp = strchr(cp + 1, '.'))
    109 		if ((sh = findsmopts_core(cp)) != NULL)
    110 			return sh;
    111 
    112 	return findsmopts_core(".");
    113 }
    114 
    115 static void
    116 printsmopts(const char *name)
    117 {
    118 	struct smopts_s *sp;
    119 
    120 	if ((sp = findsmopts(name, 1)) == NULL) {
    121 		(void)printf("%s:\n", name);
    122 		return;
    123 	}
    124 	(void)printf("%s:\t%s\n", sp->s_name, detract(sp->s_smopts, GSMOPTS));
    125 }
    126 
    127 static void
    128 printsmoptstbl(void)
    129 {
    130 	struct smopts_s *sp;
    131 	const char **argv, **ap;
    132 	int h;
    133 	int cnt;
    134 
    135 	cnt = 1;
    136 	for (h = 0; h < (int)sizeofarray(smoptstbl); h++ )
    137 		for (sp = smoptstbl[h]; sp && sp->s_name != NULL; sp = sp->s_link)
    138 			cnt++;
    139 
    140 	argv = salloc(cnt * sizeof(*argv));
    141 	ap = argv;
    142 	for (h = 0; h < (int)sizeofarray(smoptstbl); h++ )
    143 		for (sp = smoptstbl[h]; sp && sp->s_name != NULL; sp = sp->s_link)
    144 			*ap++ = sp->s_name;
    145 	*ap = NULL;
    146 	sort(argv);
    147 	for (ap = argv; *ap != NULL; ap++)
    148 		printsmopts(*ap);
    149 }
    150 
    151 static struct name *
    152 name_expand(char *sname, int ntype)
    153 {
    154 	struct grouphead *gh;
    155 	struct name *np;
    156 
    157 	if ((gh = findgroup(sname)) != NULL) {
    158 		np = gexpand(NULL, gh, 0, ntype);
    159 	}
    160 	else {
    161 		np = csalloc(1, sizeof(*np));
    162 		np->n_name = sname;
    163 		np->n_type = ntype;
    164 	}
    165 	return np;
    166 }
    167 
    168 static struct name *
    169 ncalloc(char *str, int ntype)
    170 {
    171 	struct name *np;
    172 
    173 	np = ecalloc(1, sizeof(*np));
    174 	np->n_type = ntype;
    175 	np->n_name = vcopy(str);
    176 	return np;
    177 }
    178 
    179 static void
    180 smopts_core(const char *sname, char **argv)
    181 {
    182 	struct smopts_s *sp;
    183 	struct name *np, *t;
    184 	int h;
    185 	char **ap;
    186 
    187 	if ((sp = findsmopts(sname, 1)) != NULL) {
    188 		char *cp;
    189 		cp = detract(sp->s_smopts, GSMOPTS);
    190 		(void)printf("%s already defined as: %s\n", sname, cp);
    191 		return;
    192 	}
    193 	h = hashcase(sname);
    194 	sp = ecalloc(1, sizeof(*sp));
    195 	sp->s_name = vcopy(sname);
    196 	if (smoptstbl[h])
    197 		sp->s_link = smoptstbl[h];
    198 	smoptstbl[h] = sp;
    199 
    200 	np = NULL;
    201 	for (ap = argv + 1; *ap != NULL; ap++) {
    202 		t = ncalloc(*ap, GSMOPTS);
    203 		if (sp->s_smopts == NULL)
    204 			sp->s_smopts = t;
    205 		else
    206 			np->n_flink = t;
    207 		t->n_blink = np;
    208 		np = t;
    209 	}
    210 }
    211 
    212 /*
    213  * Takes a list of entries, expands them, and adds the results to the
    214  * smopts table.
    215  */
    216 PUBLIC int
    217 smoptscmd(void *v)
    218 {
    219 	struct name *np;
    220 	char **argv = v;
    221 
    222 	if (*argv == NULL) {
    223 		printsmoptstbl();
    224 		return 0;
    225 	}
    226 	np = name_expand(argv[0], GTO);
    227 
    228 	if (argv[1] == NULL) {
    229 		for (/*EMPTY*/; np; np = np->n_flink)
    230 			printsmopts(np->n_name);
    231 		return 0;
    232 	}
    233 	for (/*EMPTY*/; np; np = np->n_flink)
    234 		smopts_core(np->n_name, argv);
    235 
    236 	return 0;
    237 }
    238 
    239 static void
    240 free_name(struct name *np)
    241 {
    242 	struct name *next_np;
    243 	for (/*EMPTY*/; np; np = next_np) {
    244 		next_np = np->n_flink;
    245 		free(next_np);
    246 	}
    247 }
    248 
    249 static void
    250 delsmopts(char *name)
    251 {
    252 	struct smopts_s *sp;
    253 	struct smopts_s **last_link;
    254 
    255 	last_link = &smoptstbl[hashcase(name)];
    256 	for (sp = *last_link; sp; sp = sp->s_link) {
    257 		if (strcasecmp(sp->s_name, name) == 0) {
    258 			*last_link = sp->s_link;
    259 			free_name(sp->s_smopts);
    260 			free(sp);
    261 		}
    262 	}
    263 }
    264 
    265 /*
    266  * Takes a list of entries and removes them from the smoptstbl.
    267  */
    268 PUBLIC int
    269 unsmoptscmd(void *v)
    270 {
    271 	struct name *np;
    272 	char **argv, **ap;
    273 
    274 	argv = v;
    275 	for (ap = argv; *ap != NULL; ap++)
    276 		for (np = name_expand(*ap, GTO); np; np = np->n_flink)
    277 			delsmopts(np->n_name);
    278 	return 0;
    279 }
    280