No empty .Rs/.Re
[netbsd-mini2440.git] / usr.bin / mail / cmd4.c
blobacc5ee6dd8fee1e7970228b7724baef43ec25777
1 /* $NetBSD: cmd4.c,v 1.5 2009/04/10 13:08:24 christos Exp $ */
3 /*-
4 * Copyright (c) 2006 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Anon Ymous.
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.
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.
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.5 2009/04/10 13:08:24 christos Exp $");
39 #endif
40 #endif /* not lint */
42 #include "rcv.h"
43 #include <util.h>
44 #include "extern.h"
47 * Mail -- a mail program
49 * Still more user commands.
50 * XXX - should this be renamed smopts.c?
53 #if 0 /* XXX - debugging stuff - to be removed */
54 void showname(struct name *);
55 void
56 showname(struct name *np)
59 for (/*EMPTY*/; np; np = np->n_flink)
60 (void)printf("np: %p np->n_type: %d np->n_name: '%s' (%p)\n",
61 np, np->n_type, np->n_name, np->n_name);
64 __unused
65 static void
66 showsmopts(struct smopts_s *sp)
69 (void)printf("%s (%p)\n", sp->s_name, sp);
70 showname(sp->s_smopts);
72 #endif /* XXX - debugging stuff - to be removed */
75 static int
76 hashcase(const char *key)
78 char *lckey;
80 lckey = salloc(strlen(key) + 1);
81 istrcpy(lckey, key);
82 return hash(lckey);
85 static struct smopts_s *
86 findsmopts_core(const char *name)
88 struct smopts_s *sh;
90 for (sh = smoptstbl[hashcase(name)]; sh; sh = sh->s_link)
91 if (strcasecmp(sh->s_name, name) == 0)
92 return sh;
93 return NULL;
97 * The exported smopts lookup routine.
99 PUBLIC struct smopts_s *
100 findsmopts(const char *name, int top_only)
102 const char *cp;
103 struct smopts_s *sh;
105 if ((sh = findsmopts_core(name)) != NULL)
106 return sh;
108 if (top_only)
109 return NULL;
111 for (cp = strchr(name, '@'); cp; cp = strchr(cp + 1, '.'))
112 if ((sh = findsmopts_core(cp)) != NULL)
113 return sh;
115 return findsmopts_core(".");
118 static void
119 printsmopts(const char *name)
121 struct smopts_s *sp;
123 if ((sp = findsmopts(name, 1)) == NULL) {
124 (void)printf("%s:\n", name);
125 return;
127 (void)printf("%s:\t%s\n", sp->s_name, detract(sp->s_smopts, GSMOPTS));
130 static void
131 printsmoptstbl(void)
133 struct smopts_s *sp;
134 const char **argv;
135 const char **ap;
136 int h;
137 int cnt;
139 cnt = 1;
140 for (h = 0; h < (int)__arraycount(smoptstbl); h++)
141 for (sp = smoptstbl[h]; sp && sp->s_name != NULL; sp = sp->s_link)
142 cnt++;
144 argv = salloc(cnt * sizeof(*argv));
145 ap = argv;
146 for (h = 0; h < (int)__arraycount(smoptstbl); h++)
147 for (sp = smoptstbl[h]; sp && sp->s_name != NULL; sp = sp->s_link)
148 *ap++ = sp->s_name;
149 *ap = NULL;
150 sort(argv);
151 for (ap = argv; *ap != NULL; ap++)
152 printsmopts(*ap);
155 static struct name *
156 name_expand(char *sname, int ntype)
158 struct grouphead *gh;
159 struct name *np;
161 if ((gh = findgroup(sname)) != NULL) {
162 np = gexpand(NULL, gh, 0, ntype);
164 else {
165 np = csalloc(1, sizeof(*np));
166 np->n_name = sname;
167 np->n_type = ntype;
169 return np;
172 static struct name *
173 ncalloc(char *str, int ntype)
175 struct name *np;
177 np = ecalloc(1, sizeof(*np));
178 np->n_type = ntype;
179 np->n_name = vcopy(str);
180 return np;
183 static void
184 smopts_core(const char *sname, char **argv)
186 struct smopts_s *sp;
187 struct name *np;
188 struct name *t;
189 int h;
190 char **ap;
192 if ((sp = findsmopts(sname, 1)) != NULL) {
193 char *cp;
194 cp = detract(sp->s_smopts, GSMOPTS);
195 (void)printf("%s already defined as: %s\n", sname, cp);
196 return;
198 h = hashcase(sname);
199 sp = ecalloc(1, sizeof(*sp));
200 sp->s_name = vcopy(sname);
201 if (smoptstbl[h])
202 sp->s_link = smoptstbl[h];
203 smoptstbl[h] = sp;
205 np = NULL;
206 for (ap = argv + 1; *ap != NULL; ap++) {
207 t = ncalloc(*ap, GSMOPTS);
208 if (sp->s_smopts == NULL)
209 sp->s_smopts = t;
210 else
211 np->n_flink = t;
212 t->n_blink = np;
213 np = t;
218 * Takes a list of entries, expands them, and adds the results to the
219 * smopts table.
221 PUBLIC int
222 smoptscmd(void *v)
224 struct name *np;
225 char **argv;
227 argv = v;
228 if (*argv == NULL) {
229 printsmoptstbl();
230 return 0;
232 np = name_expand(argv[0], GTO);
234 if (argv[1] == NULL) {
235 for (/*EMPTY*/; np; np = np->n_flink)
236 printsmopts(np->n_name);
237 return 0;
239 for (/*EMPTY*/; np; np = np->n_flink)
240 smopts_core(np->n_name, argv);
242 return 0;
245 static void
246 free_name(struct name *np)
248 struct name *next_np;
250 for (/*EMPTY*/; np; np = next_np) {
251 next_np = np->n_flink;
252 free(next_np);
256 static void
257 delsmopts(char *name)
259 struct smopts_s *sp;
260 struct smopts_s **last_link;
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);
273 * Takes a list of entries and removes them from the smoptstbl.
275 PUBLIC int
276 unsmoptscmd(void *v)
278 struct name *np;
279 char **ap;
281 for (ap = v; *ap != NULL; ap++)
282 for (np = name_expand(*ap, GTO); np; np = np->n_flink)
283 delsmopts(np->n_name);
284 return 0;
287 static struct name *
288 alloc_Header(char *str)
290 struct name *np;
293 * Don't use salloc() routines here as these strings must persist.
295 np = ecalloc(1, sizeof(*np));
296 np->n_name = estrdup(str);
297 np->n_type = GMISC;
298 return np;
301 static int
302 free_Header(char *str)
304 struct name *np;
305 struct name *next_np;
306 size_t len;
308 len = strlen(str);
309 for (np = extra_headers; np != NULL; np = next_np) {
310 next_np = np->n_flink;
311 if (strncasecmp(np->n_name, str, len) == 0) {
312 if (np == extra_headers) {
313 extra_headers = np->n_flink;
314 if (extra_headers)
315 extra_headers->n_blink = NULL;
317 else {
318 struct name *bp;
319 struct name *fp;
321 bp = np->n_blink;
322 fp = np->n_flink;
323 if (bp)
324 bp->n_flink = fp;
325 if (fp)
326 fp->n_blink = bp;
328 if (np->n_name)
329 free(np->n_name);
330 free(np);
333 return 0;
337 * Takes a string and includes it in the header.
339 PUBLIC int
340 Header(void *v)
342 struct name *np;
343 char *str;
344 char *p;
346 str = v;
347 if (str == NULL)
348 return 0;
350 (void)strip_WSP(str); /* strip trailing whitespace */
352 if (str[0] == '\0') { /* Show the extra headers */
353 for (np = extra_headers; np != NULL; np = np->n_flink)
354 (void)printf("%s\n", np->n_name);
355 return 0;
359 * Check for a valid header line: find the end of its name.
361 for (p = str; *p != '\0' && *p != ':' && !is_WSP(*p); p++)
362 continue;
364 if (p[0] == ':' && p[1] == '\0') /* free headers of this type */
365 return free_Header(str);
368 * Check for a valid header name.
370 if (*p != ':' || !is_WSP(p[1])) {
371 (void)printf("invalid header string: `%s'\n", str);
372 return 0;
375 np = alloc_Header(str);
376 if (extra_headers == NULL)
377 extra_headers = np;
378 else {
379 struct name *tp;
381 for (tp = extra_headers; tp->n_flink; tp = tp->n_flink)
382 continue;
383 tp->n_flink = np;
384 np->n_blink = tp;
386 return 0;