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