xref: /netbsd-src/usr.bin/mail/cmd4.c (revision c0179c282a5968435315a82f4128c61372c68fc3)
1 /*	$NetBSD: cmd4.c,v 1.1 2006/10/31 22:37:19 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.1 2006/10/31 22:37:19 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  */
58 
59 #ifdef SMOPTS_CMD
60 
61 #if 0	/* XXX - debugging stuff - to be removed */
62 void showname(struct name *);
63 void
64 showname(struct name *np)
65 {
66 	for (/*EMPTY*/; np; np = np->n_flink)
67 		(void)printf("np: %p  np->n_type: %d  np->n_name: '%s' (%p)\n",
68 		    np, np->n_type, np->n_name, np->n_name);
69 }
70 
71 __unused
72 static void
73 showsmopts(struct smopts_s *sp)
74 {
75 	(void)printf("%s (%p)\n", sp->s_name, sp);
76 	showname(sp->s_smopts);
77 }
78 #endif	/* XXX - debugging stuff - to be removed */
79 
80 
81 static int
82 hashcase(const char *key)
83 {
84 	char *lckey;
85 	lckey = salloc(strlen(key) + 1);
86 	istrcpy(lckey, key);
87 	return hash(lckey);
88 }
89 
90 static struct smopts_s *
91 findsmopts_core(const char *name)
92 {
93 	struct smopts_s *sh;
94 
95 	for (sh = smoptstbl[hashcase(name)]; sh; sh = sh->s_link)
96 		if (strcasecmp(sh->s_name, name) == 0)
97 			return(sh);
98 	return NULL;
99 }
100 
101 struct smopts_s *
102 findsmopts(const char *name, int top_only)
103 {
104 	const char *cp;
105 	struct smopts_s *sh;
106 
107 	if ((sh = findsmopts_core(name)) != NULL)
108 		return sh;
109 
110 	if (top_only)
111 		return NULL;
112 
113 	for (cp = strchr(name, '@'); cp; cp = strchr(cp + 1, '.'))
114 		if ((sh = findsmopts_core(cp)) != NULL)
115 			return sh;
116 
117 	return findsmopts_core(".");
118 }
119 
120 /****************************************
121  *
122  */
123 static void
124 printsmopts(char *name)
125 {
126 	struct smopts_s *sp;
127 
128 	if ((sp = findsmopts(name, 1)) == NULL) {
129 		(void)printf("%s:\n", name);
130 		return;
131 	}
132 	(void)printf("%s:\t%s\n", sp->s_name, detract(sp->s_smopts, GSMOPTS));
133 }
134 
135 static void
136 printsmoptstbl(void)
137 {
138 	struct smopts_s *sp;
139 	char **argv, **ap;
140 	int h;
141 	int cnt;
142 
143 	cnt = 1;
144 	for (h = 0; h < sizeofarray(smoptstbl); h++ )
145 		for (sp = smoptstbl[h]; sp && sp->s_name != NULL; sp = sp->s_link)
146 			cnt++;
147 
148 	argv = salloc(cnt * sizeof(*argv));
149 	ap = argv;
150 	for (h = 0; h < sizeofarray(smoptstbl); h++ )
151 		for (sp = smoptstbl[h]; sp && sp->s_name != NULL; sp = sp->s_link)
152 			*ap++ = sp->s_name;
153 	*ap = NULL;
154 	sort(argv);
155 	for (ap = argv; *ap != NULL; ap++)
156 		printsmopts(*ap);
157 }
158 
159 static struct name *
160 name_expand(char *sname, int ntype)
161 {
162 	struct grouphead *gh;
163 	struct name *np;
164 
165 	if ((gh = findgroup(sname)) != NULL) {
166 		np = gexpand(NULL, gh, 0, ntype);
167 	}
168 	else {
169 		np = csalloc(1, sizeof(*np));
170 		np->n_name = sname;
171 		np->n_type = ntype;
172 	}
173 	return np;
174 }
175 
176 static struct name *
177 ncalloc(char *str, int ntype)
178 {
179 	struct name *np;
180 
181 	np = ecalloc(1, sizeof *np);
182 	np->n_type = ntype;
183 	np->n_name = vcopy(str);
184 	return(np);
185 }
186 
187 static void
188 smopts_core(const char *sname, char **argv)
189 {
190 	struct smopts_s *sp;
191 	struct name *np, *t;
192 	int h;
193 	char **ap;
194 
195 	if ((sp = findsmopts(sname, 1)) != NULL) {
196 		char *cp;
197 		cp = detract(sp->s_smopts, GSMOPTS);
198 		(void)printf("%s already defined as: %s\n", sname, cp);
199 		return;
200 	}
201 	h = hashcase(sname);
202 	sp = ecalloc(1, sizeof *sp);
203 	sp->s_name = vcopy(sname);
204 	if (smoptstbl[h])
205 		sp->s_link = smoptstbl[h];
206 	smoptstbl[h] = sp;
207 
208 	np = NULL;
209 	for (ap = argv + 1; *ap != NULL; ap++) {
210 		t = ncalloc(*ap, GSMOPTS);
211 		if (sp->s_smopts == NULL)
212 			sp->s_smopts = t;
213 		else
214 			np->n_flink = t;
215 		t->n_blink = np;
216 		np = t;
217 	}
218 }
219 
220 int
221 smoptscmd(void *v)
222 {
223 	struct name *np;
224 	char **argv = v;
225 
226 	if (*argv == NULL) {
227 		printsmoptstbl();
228 		return 0;
229 	}
230 	np = name_expand(argv[0], GTO);
231 
232 	if (argv[1] == NULL) {
233 		for (/*EMPTY*/; np; np = np->n_flink)
234 			printsmopts(np->n_name);
235 		return 0;
236 	}
237 	for (/*EMPTY*/; np; np = np->n_flink)
238 		smopts_core(np->n_name, argv);
239 
240 	return 0;
241 }
242 
243 static void
244 free_name(struct name *np)
245 {
246 	struct name *next_np;
247 	for (/*EMPTY*/; np; np = next_np) {
248 		next_np = np->n_flink;
249 		free(next_np);
250 	}
251 }
252 
253 static void
254 delsmopts(char *name)
255 {
256 	struct smopts_s *sp;
257 	struct smopts_s **last_link;
258 
259 	last_link = &smoptstbl[hashcase(name)];
260 	for (sp = *last_link; sp; sp = sp->s_link) {
261 		if (strcasecmp(sp->s_name, name) == 0) {
262 			*last_link = sp->s_link;
263 			free_name(sp->s_smopts);
264 			free(sp);
265 		}
266 	}
267 }
268 
269 int
270 unsmopts(void *v)
271 {
272 	struct name *np;
273 	char **argv, **ap;
274 
275 	argv = v;
276 	for (ap = argv; *ap != NULL; ap++)
277 		for (np = name_expand(*ap, GTO); np; np = np->n_flink)
278 			delsmopts(np->n_name);
279 	return 0;
280 }
281 #endif /* SMOPTS_CMD */
282