xref: /netbsd-src/usr.bin/mail/cmd4.c (revision 267197ec1eebfcb9810ea27a89625b6ddf68e3e7)
1 /*	$NetBSD: cmd4.c,v 1.3 2007/10/29 23:20:37 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.3 2007/10/29 23:20:37 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