1 /* $NetBSD: cmd4.c,v 1.1 2006/10/31 22:37:19 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.1 2006/10/31 22:37:19 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 */ 58 59 #ifdef SMOPTS_CMD 60 61 #if 0 /* XXX - debugging stuff - to be removed */ 62 void showname(struct name *); 63 void 64 showname(struct name *np) 65 { 66 for (/*EMPTY*/; np; np = np->n_flink) 67 (void)printf("np: %p np->n_type: %d np->n_name: '%s' (%p)\n", 68 np, np->n_type, np->n_name, np->n_name); 69 } 70 71 __unused 72 static void 73 showsmopts(struct smopts_s *sp) 74 { 75 (void)printf("%s (%p)\n", sp->s_name, sp); 76 showname(sp->s_smopts); 77 } 78 #endif /* XXX - debugging stuff - to be removed */ 79 80 81 static int 82 hashcase(const char *key) 83 { 84 char *lckey; 85 lckey = salloc(strlen(key) + 1); 86 istrcpy(lckey, key); 87 return hash(lckey); 88 } 89 90 static struct smopts_s * 91 findsmopts_core(const char *name) 92 { 93 struct smopts_s *sh; 94 95 for (sh = smoptstbl[hashcase(name)]; sh; sh = sh->s_link) 96 if (strcasecmp(sh->s_name, name) == 0) 97 return(sh); 98 return NULL; 99 } 100 101 struct smopts_s * 102 findsmopts(const char *name, int top_only) 103 { 104 const char *cp; 105 struct smopts_s *sh; 106 107 if ((sh = findsmopts_core(name)) != NULL) 108 return sh; 109 110 if (top_only) 111 return NULL; 112 113 for (cp = strchr(name, '@'); cp; cp = strchr(cp + 1, '.')) 114 if ((sh = findsmopts_core(cp)) != NULL) 115 return sh; 116 117 return findsmopts_core("."); 118 } 119 120 /**************************************** 121 * 122 */ 123 static void 124 printsmopts(char *name) 125 { 126 struct smopts_s *sp; 127 128 if ((sp = findsmopts(name, 1)) == NULL) { 129 (void)printf("%s:\n", name); 130 return; 131 } 132 (void)printf("%s:\t%s\n", sp->s_name, detract(sp->s_smopts, GSMOPTS)); 133 } 134 135 static void 136 printsmoptstbl(void) 137 { 138 struct smopts_s *sp; 139 char **argv, **ap; 140 int h; 141 int cnt; 142 143 cnt = 1; 144 for (h = 0; h < sizeofarray(smoptstbl); h++ ) 145 for (sp = smoptstbl[h]; sp && sp->s_name != NULL; sp = sp->s_link) 146 cnt++; 147 148 argv = salloc(cnt * sizeof(*argv)); 149 ap = argv; 150 for (h = 0; h < sizeofarray(smoptstbl); h++ ) 151 for (sp = smoptstbl[h]; sp && sp->s_name != NULL; sp = sp->s_link) 152 *ap++ = sp->s_name; 153 *ap = NULL; 154 sort(argv); 155 for (ap = argv; *ap != NULL; ap++) 156 printsmopts(*ap); 157 } 158 159 static struct name * 160 name_expand(char *sname, int ntype) 161 { 162 struct grouphead *gh; 163 struct name *np; 164 165 if ((gh = findgroup(sname)) != NULL) { 166 np = gexpand(NULL, gh, 0, ntype); 167 } 168 else { 169 np = csalloc(1, sizeof(*np)); 170 np->n_name = sname; 171 np->n_type = ntype; 172 } 173 return np; 174 } 175 176 static struct name * 177 ncalloc(char *str, int ntype) 178 { 179 struct name *np; 180 181 np = ecalloc(1, sizeof *np); 182 np->n_type = ntype; 183 np->n_name = vcopy(str); 184 return(np); 185 } 186 187 static void 188 smopts_core(const char *sname, char **argv) 189 { 190 struct smopts_s *sp; 191 struct name *np, *t; 192 int h; 193 char **ap; 194 195 if ((sp = findsmopts(sname, 1)) != NULL) { 196 char *cp; 197 cp = detract(sp->s_smopts, GSMOPTS); 198 (void)printf("%s already defined as: %s\n", sname, cp); 199 return; 200 } 201 h = hashcase(sname); 202 sp = ecalloc(1, sizeof *sp); 203 sp->s_name = vcopy(sname); 204 if (smoptstbl[h]) 205 sp->s_link = smoptstbl[h]; 206 smoptstbl[h] = sp; 207 208 np = NULL; 209 for (ap = argv + 1; *ap != NULL; ap++) { 210 t = ncalloc(*ap, GSMOPTS); 211 if (sp->s_smopts == NULL) 212 sp->s_smopts = t; 213 else 214 np->n_flink = t; 215 t->n_blink = np; 216 np = t; 217 } 218 } 219 220 int 221 smoptscmd(void *v) 222 { 223 struct name *np; 224 char **argv = v; 225 226 if (*argv == NULL) { 227 printsmoptstbl(); 228 return 0; 229 } 230 np = name_expand(argv[0], GTO); 231 232 if (argv[1] == NULL) { 233 for (/*EMPTY*/; np; np = np->n_flink) 234 printsmopts(np->n_name); 235 return 0; 236 } 237 for (/*EMPTY*/; np; np = np->n_flink) 238 smopts_core(np->n_name, argv); 239 240 return 0; 241 } 242 243 static void 244 free_name(struct name *np) 245 { 246 struct name *next_np; 247 for (/*EMPTY*/; np; np = next_np) { 248 next_np = np->n_flink; 249 free(next_np); 250 } 251 } 252 253 static void 254 delsmopts(char *name) 255 { 256 struct smopts_s *sp; 257 struct smopts_s **last_link; 258 259 last_link = &smoptstbl[hashcase(name)]; 260 for (sp = *last_link; sp; sp = sp->s_link) { 261 if (strcasecmp(sp->s_name, name) == 0) { 262 *last_link = sp->s_link; 263 free_name(sp->s_smopts); 264 free(sp); 265 } 266 } 267 } 268 269 int 270 unsmopts(void *v) 271 { 272 struct name *np; 273 char **argv, **ap; 274 275 argv = v; 276 for (ap = argv; *ap != NULL; ap++) 277 for (np = name_expand(*ap, GTO); np; np = np->n_flink) 278 delsmopts(np->n_name); 279 return 0; 280 } 281 #endif /* SMOPTS_CMD */ 282