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