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