cmd4.c revision 1.3 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