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