1 /* $NetBSD: cmd4.c,v 1.5 2009/04/10 13:08:24 christos Exp $ */
4 * Copyright (c) 2006 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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>
36 static char sccsid
[] = "@(#)cmd3.c 8.2 (Berkeley) 4/20/95";
38 __RCSID("$NetBSD: cmd4.c,v 1.5 2009/04/10 13:08:24 christos Exp $");
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
*);
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
);
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 */
76 hashcase(const char *key
)
80 lckey
= salloc(strlen(key
) + 1);
85 static struct smopts_s
*
86 findsmopts_core(const char *name
)
90 for (sh
= smoptstbl
[hashcase(name
)]; sh
; sh
= sh
->s_link
)
91 if (strcasecmp(sh
->s_name
, name
) == 0)
97 * The exported smopts lookup routine.
99 PUBLIC
struct smopts_s
*
100 findsmopts(const char *name
, int top_only
)
105 if ((sh
= findsmopts_core(name
)) != NULL
)
111 for (cp
= strchr(name
, '@'); cp
; cp
= strchr(cp
+ 1, '.'))
112 if ((sh
= findsmopts_core(cp
)) != NULL
)
115 return findsmopts_core(".");
119 printsmopts(const char *name
)
123 if ((sp
= findsmopts(name
, 1)) == NULL
) {
124 (void)printf("%s:\n", name
);
127 (void)printf("%s:\t%s\n", sp
->s_name
, detract(sp
->s_smopts
, GSMOPTS
));
140 for (h
= 0; h
< (int)__arraycount(smoptstbl
); h
++)
141 for (sp
= smoptstbl
[h
]; sp
&& sp
->s_name
!= NULL
; sp
= sp
->s_link
)
144 argv
= salloc(cnt
* sizeof(*argv
));
146 for (h
= 0; h
< (int)__arraycount(smoptstbl
); h
++)
147 for (sp
= smoptstbl
[h
]; sp
&& sp
->s_name
!= NULL
; sp
= sp
->s_link
)
151 for (ap
= argv
; *ap
!= NULL
; ap
++)
156 name_expand(char *sname
, int ntype
)
158 struct grouphead
*gh
;
161 if ((gh
= findgroup(sname
)) != NULL
) {
162 np
= gexpand(NULL
, gh
, 0, ntype
);
165 np
= csalloc(1, sizeof(*np
));
173 ncalloc(char *str
, int ntype
)
177 np
= ecalloc(1, sizeof(*np
));
179 np
->n_name
= vcopy(str
);
184 smopts_core(const char *sname
, char **argv
)
192 if ((sp
= findsmopts(sname
, 1)) != NULL
) {
194 cp
= detract(sp
->s_smopts
, GSMOPTS
);
195 (void)printf("%s already defined as: %s\n", sname
, cp
);
199 sp
= ecalloc(1, sizeof(*sp
));
200 sp
->s_name
= vcopy(sname
);
202 sp
->s_link
= smoptstbl
[h
];
206 for (ap
= argv
+ 1; *ap
!= NULL
; ap
++) {
207 t
= ncalloc(*ap
, GSMOPTS
);
208 if (sp
->s_smopts
== NULL
)
218 * Takes a list of entries, expands them, and adds the results to the
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
);
239 for (/*EMPTY*/; np
; np
= np
->n_flink
)
240 smopts_core(np
->n_name
, argv
);
246 free_name(struct name
*np
)
248 struct name
*next_np
;
250 for (/*EMPTY*/; np
; np
= next_np
) {
251 next_np
= np
->n_flink
;
257 delsmopts(char *name
)
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
);
273 * Takes a list of entries and removes them from the smoptstbl.
281 for (ap
= v
; *ap
!= NULL
; ap
++)
282 for (np
= name_expand(*ap
, GTO
); np
; np
= np
->n_flink
)
283 delsmopts(np
->n_name
);
288 alloc_Header(char *str
)
293 * Don't use salloc() routines here as these strings must persist.
295 np
= ecalloc(1, sizeof(*np
));
296 np
->n_name
= estrdup(str
);
302 free_Header(char *str
)
305 struct name
*next_np
;
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
;
315 extra_headers
->n_blink
= NULL
;
337 * Takes a string and includes it in the header.
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
);
359 * Check for a valid header line: find the end of its name.
361 for (p
= str
; *p
!= '\0' && *p
!= ':' && !is_WSP(*p
); p
++)
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
);
375 np
= alloc_Header(str
);
376 if (extra_headers
== NULL
)
381 for (tp
= extra_headers
; tp
->n_flink
; tp
= tp
->n_flink
)