main.c (119172) | main.c (132493) |
---|---|
1/* 2 * Copyright (c) 2001-2003 3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 13 unchanged lines hidden (view full) --- 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * Author: Hartmut Brandt <harti@freebsd.org> 28 */ 29#include <sys/cdefs.h> | 1/* 2 * Copyright (c) 2001-2003 3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 13 unchanged lines hidden (view full) --- 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * Author: Hartmut Brandt <harti@freebsd.org> 28 */ 29#include <sys/cdefs.h> |
30__FBSDID("$FreeBSD: head/sbin/atm/atmconfig/main.c 119172 2003-08-20 08:25:36Z harti $"); | 30__FBSDID("$FreeBSD: head/sbin/atm/atmconfig/main.c 132493 2004-07-21 09:42:56Z harti $"); |
31 32#include <sys/types.h> 33#include <sys/sysctl.h> 34#include <netdb.h> 35#include <stdarg.h> 36#include <ctype.h> 37#include <limits.h> | 31 32#include <sys/types.h> 33#include <sys/sysctl.h> 34#include <netdb.h> 35#include <stdarg.h> 36#include <ctype.h> 37#include <limits.h> |
38#include <inttypes.h> | 38#include <stdint.h> 39#include <fnmatch.h> 40#include <dirent.h> |
39#include "atmconfig.h" 40#include "private.h" 41 42/* verbosity level */ 43int verbose; 44 45/* notitle option */ 46static int notitle; --- 17 unchanged lines hidden (view full) --- 64 65static int 66substr(const char *s1, const char *s2) 67{ 68 return (strlen(s1) <= strlen(s2) && strncmp(s1, s2, strlen(s1)) == 0); 69} 70 71/* | 41#include "atmconfig.h" 42#include "private.h" 43 44/* verbosity level */ 45int verbose; 46 47/* notitle option */ 48static int notitle; --- 17 unchanged lines hidden (view full) --- 66 67static int 68substr(const char *s1, const char *s2) 69{ 70 return (strlen(s1) <= strlen(s2) && strncmp(s1, s2, strlen(s1)) == 0); 71} 72 73/* |
74 * Current help file state 75 */ 76struct help_file { 77 int file_state; /* 0:looking for main file, 1:found, 2:other */ 78 const char *p_start; /* current path pointer */ 79 const char *p_end; /* end of current path in path */ 80 char *dirname; /* directory name */ 81 DIR *dir; /* open directory */ 82 char *fname; /* current filename */ 83 FILE *fp; /* open file */ 84 char line[LINE_MAX]; /* current line */ 85 u_int fcnt; /* count of files found */ 86}; 87 88struct help_pos { 89 off_t pos; /* file position */ 90 u_int fcnt; /* number of file */ 91 char *fname; /* name of file */ 92 const char *p_start; /* current path pointer */ 93 const char *p_end; /* end of current path in path */ 94}; 95 96static int 97help_next_file(struct help_file *hp) 98{ 99 const char *fpat; 100 struct dirent *ent; 101 102 if (hp->file_state == 3) 103 return (-1); 104 105 if (hp->file_state == 0) 106 fpat = FILE_HELP; 107 else 108 fpat = FILE_HELP_OTHERS; 109 110 if (hp->file_state == 0 || hp->file_state == 1) { 111 /* start from beginning */ 112 hp->p_start = PATH_HELP; 113 hp->file_state++; 114 } 115 116 try_file: 117 if (hp->dir != NULL) { 118 /* directory open (must be state 2) */ 119 while ((ent = readdir(hp->dir)) != NULL) { 120 if (fnmatch(fpat, ent->d_name, FNM_NOESCAPE) != 0) 121 continue; 122 if (asprintf(&hp->fname, "%s/%s", hp->dirname, 123 ent->d_name) == -1) 124 err(1, NULL); 125 if ((hp->fp = fopen(hp->fname, "r")) != NULL) { 126 hp->fcnt++; 127 return (0); 128 } 129 free(hp->fname); 130 } 131 /* end of directory */ 132 closedir(hp->dir); 133 hp->dir = NULL; 134 free(hp->dirname); 135 goto next_path; 136 } 137 138 /* nothing open - advanc to new path element */ 139 try_path: 140 for (hp->p_end = hp->p_start; *hp->p_end != '\0' && 141 *hp->p_end != ':'; hp->p_end++) 142 ; 143 144 if (asprintf(&hp->dirname, "%.*s", (int)(hp->p_end - hp->p_start), 145 hp->p_start) == -1) 146 err(1, NULL); 147 148 if (hp->file_state == 1) { 149 /* just try to open */ 150 if (asprintf(&hp->fname, "%s/%s", hp->dirname, fpat) == -1) 151 err(1, NULL); 152 if ((hp->fp = fopen(hp->fname, "r")) != NULL) { 153 hp->fcnt++; 154 return (0); 155 } 156 free(hp->fname); 157 158 goto next_path; 159 } 160 161 /* open directory */ 162 if ((hp->dir = opendir(hp->dirname)) != NULL) 163 goto try_file; 164 165 free(hp->dirname); 166 167 next_path: 168 hp->p_start = hp->p_end; 169 if (*hp->p_start == '\0') { 170 /* end of path */ 171 if (hp->file_state == 1) 172 errx(1, "help file not found"); 173 return (-1); 174 } 175 hp->p_start++; 176 goto try_path; 177 178} 179 180/* 181 * Save current file position 182 */ 183static void 184help_file_tell(struct help_file *hp, struct help_pos *pos) 185{ 186 if (pos->fname != NULL) 187 free(pos->fname); 188 if ((pos->fname = strdup(hp->fname)) == NULL) 189 err(1, NULL); 190 pos->fcnt = hp->fcnt; 191 pos->p_start = hp->p_start; 192 pos->p_end = hp->p_end; 193 if ((pos->pos = ftello(hp->fp)) == -1) 194 err(1, "%s", pos->fname); 195} 196 197/* 198 * Go to that position 199 * 200 * We can go either to the original help file or back in the current file. 201 */ 202static void 203help_file_seek(struct help_file *hp, struct help_pos *pos) 204{ 205 hp->p_start = pos->p_start; 206 hp->p_end = pos->p_end; 207 hp->fcnt = pos->fcnt; 208 209 if (hp->dir != NULL) { 210 free(hp->dirname); 211 closedir(hp->dir); 212 hp->dir = NULL; 213 } 214 215 if (hp->fp != NULL &&strcmp(hp->fname, pos->fname) != 0) { 216 free(hp->fname); 217 fclose(hp->fp); 218 hp->fp = NULL; 219 } 220 if (hp->fp == NULL) { 221 if ((hp->fname = strdup(pos->fname)) == NULL) 222 err(1, NULL); 223 if ((hp->fp = fopen(hp->fname, "r")) == NULL) 224 err(1, "reopen %s", hp->fname); 225 } 226 if (fseeko(hp->fp, pos->pos, SEEK_SET) == -1) 227 err(1, "seek %s", hp->fname); 228 229 if (pos->fcnt == 1) 230 /* go back to state 1 */ 231 hp->file_state = 1; 232 else 233 /* lock */ 234 hp->file_state = 3; 235} 236 237/* 238 * Rewind to position 0 239 */ 240static void 241help_file_rewind(struct help_file *hp) 242{ 243 244 if (hp->file_state == 1) { 245 if (fseeko(hp->fp, (off_t)0, SEEK_SET) == -1) 246 err(1, "rewind help file"); 247 return; 248 } 249 250 if (hp->dir != NULL) { 251 free(hp->dirname); 252 closedir(hp->dir); 253 hp->dir = NULL; 254 } 255 256 if (hp->fp != NULL) { 257 free(hp->fname); 258 fclose(hp->fp); 259 hp->fp = NULL; 260 } 261 memset(hp, 0, sizeof(*hp)); 262} 263 264/* 265 * Get next line from a help file 266 */ 267static const char * 268help_next_line(struct help_file *hp) 269{ 270 for (;;) { 271 if (hp->fp != NULL) { 272 if (fgets(hp->line, sizeof(hp->line), hp->fp) != NULL) 273 return (hp->line); 274 if (ferror(hp->fp)) 275 err(1, "%s", hp->fname); 276 free(hp->fname); 277 278 fclose(hp->fp); 279 hp->fp = NULL; 280 } 281 if (help_next_file(hp) == -1) 282 return (NULL); 283 } 284 285} 286 287/* 288 * This function prints the available 0-level help topics from all 289 * other help files by scanning the files. It assumes, that this is called 290 * only from the main help file. 291 */ 292static void 293help_get_0topics(struct help_file *hp) 294{ 295 struct help_pos save; 296 const char *line; 297 298 memset(&save, 0, sizeof(save)); 299 help_file_tell(hp, &save); 300 301 help_file_rewind(hp); 302 while ((line = help_next_line(hp)) != NULL) { 303 if (line[0] == '^' && line[1] == '^') 304 printf("%s", line + 2); 305 } 306 help_file_seek(hp, &save); 307} 308 309/* |
|
72 * Function to print help. The help argument is in argv[0] here. 73 */ 74static void 75help_func(int argc, char *argv[]) 76{ | 310 * Function to print help. The help argument is in argv[0] here. 311 */ 312static void 313help_func(int argc, char *argv[]) 314{ |
77 FILE *hp; 78 const char *start, *end; 79 char *fname; 80 off_t match, last_match; 81 char line[LINE_MAX]; | 315 struct help_file hfile; 316 struct help_pos match, last_match; 317 const char *line; |
82 char key[100]; | 318 char key[100]; |
83 int level, i; | 319 int level; 320 int i, has_sub_topics; |
84 | 321 |
85 /* 86 * Find the help file 87 */ 88 hp = NULL; 89 for (start = PATH_HELP; *start != '\0'; start = end + 1) { 90 for (end = start; *end != ':' && *end != '\0'; end++) 91 ; 92 if (start == end) { 93 if (asprintf(&fname, "%s", FILE_HELP) == -1) 94 err(1, NULL); 95 } else { 96 if (asprintf(&fname, "%.*s/%s", (int)(end - start), 97 start, FILE_HELP) == -1) 98 err(1, NULL); 99 } 100 if ((hp = fopen(fname, "r")) != NULL) 101 break; 102 free(fname); 103 } 104 if (hp == NULL) 105 errx(1, "help file not found"); | 322 memset(&hfile, 0, sizeof(hfile)); 323 memset(&match, 0, sizeof(match)); 324 memset(&last_match, 0, sizeof(last_match)); |
106 107 if (argc == 0) { | 325 326 if (argc == 0) { |
327 /* only 'help' - show intro */ |
|
108 if ((argv[0] = strdup("intro")) == NULL) 109 err(1, NULL); 110 argc = 1; 111 } 112 113 optind = 0; | 328 if ((argv[0] = strdup("intro")) == NULL) 329 err(1, NULL); 330 argc = 1; 331 } 332 333 optind = 0; |
114 match = -1; 115 last_match = -1; | 334 match.pos = -1; 335 last_match.pos = -1; |
116 for (;;) { 117 /* read next line */ | 336 for (;;) { 337 /* read next line */ |
118 if (fgets(line, sizeof(line), hp) == NULL) { 119 if (ferror(hp)) 120 err(1, fname); | 338 if ((line = help_next_line(&hfile)) == NULL) { |
121 /* EOF */ | 339 /* EOF */ |
122 clearerr(hp); | |
123 level = 999; 124 goto stop; 125 } | 340 level = 999; 341 goto stop; 342 } |
126 if (line[0] != '^') | 343 if (line[0] != '^' || line[1] == '^') |
127 continue; 128 129 if (sscanf(line + 1, "%d%99s", &level, key) != 2) 130 errx(1, "error in help file '%s'", line); 131 132 if (level < optind) { 133 stop: 134 /* next higher level entry - stop this level */ | 344 continue; 345 346 if (sscanf(line + 1, "%d%99s", &level, key) != 2) 347 errx(1, "error in help file '%s'", line); 348 349 if (level < optind) { 350 stop: 351 /* next higher level entry - stop this level */ |
135 if (match == -1) { | 352 if (match.pos == -1) { |
136 /* not found */ 137 goto not_found; 138 } 139 /* go back to the match */ | 353 /* not found */ 354 goto not_found; 355 } 356 /* go back to the match */ |
140 if (fseeko(hp, match, SEEK_SET) == -1) 141 err(1, fname); | 357 help_file_seek(&hfile, &match); |
142 last_match = match; | 358 last_match = match; |
143 match = -1; | 359 memset(&match, 0, sizeof(match)); 360 match.pos = -1; |
144 145 /* go to next key */ 146 if (++optind >= argc) 147 break; 148 } 149 if (level == optind) { 150 if (substr(argv[optind], key)) { | 361 362 /* go to next key */ 363 if (++optind >= argc) 364 break; 365 } 366 if (level == optind) { 367 if (substr(argv[optind], key)) { |
151 if (match != -1) { | 368 if (match.pos != -1) { |
152 printf("Ambiguous topic."); 153 goto list_topics; 154 } | 369 printf("Ambiguous topic."); 370 goto list_topics; 371 } |
155 if ((match = ftello(hp)) == -1) 156 err(1, fname); | 372 help_file_tell(&hfile, &match); |
157 } 158 } 159 } | 373 } 374 } 375 } |
160 if (last_match == -1) { 161 if (fseek(hp, 0L, SEEK_SET) == -1) 162 err(1, fname); 163 } else { 164 if (fseeko(hp, last_match, SEEK_SET) == -1) 165 err(1, fname); 166 } | |
167 | 376 |
377 /* before breaking above we have seeked back to the matching point */ |
|
168 for (;;) { | 378 for (;;) { |
169 if (fgets(line, sizeof(line), hp) == NULL) { 170 if (ferror(hp)) 171 err(1, fname); | 379 if ((line = help_next_line(&hfile)) == NULL) |
172 break; | 380 break; |
173 } | 381 |
174 if (line[0] == '#') 175 continue; | 382 if (line[0] == '#') 383 continue; |
176 if (line[0] == '^') | 384 if (line[0] == '^') { 385 if (line[1] == '^') 386 continue; |
177 break; | 387 break; |
388 } 389 if (strncmp(line, "$MAIN", 5) == 0) { 390 help_get_0topics(&hfile); 391 continue; 392 } |
|
178 printf("%s", line); 179 } 180 181 exit(0); 182 183 not_found: 184 printf("Topic not found."); 185 186 list_topics: | 393 printf("%s", line); 394 } 395 396 exit(0); 397 398 not_found: 399 printf("Topic not found."); 400 401 list_topics: |
187 printf(" Use one of:\natmconfig"); | 402 printf(" Use one of:\natmconfig help"); |
188 for (i = 0; i < optind; i++) 189 printf(" %s", argv[i]); | 403 for (i = 0; i < optind; i++) 404 printf(" %s", argv[i]); |
405 |
|
190 printf(" ["); | 406 printf(" ["); |
407 |
|
191 /* list all the keys at this level */ | 408 /* list all the keys at this level */ |
192 if (last_match == -1) { 193 if (fseek(hp, 0L, SEEK_SET) == -1) 194 err(1, fname); 195 } else { 196 if (fseeko(hp, last_match, SEEK_SET) == -1) 197 err(1, fname); 198 } | 409 if (last_match.pos == -1) 410 /* go back to start of help */ 411 help_file_rewind(&hfile); 412 else 413 help_file_seek(&hfile, &last_match); |
199 | 414 |
200 for (;;) { 201 /* read next line */ 202 if (fgets(line, sizeof(line), hp) == NULL) { 203 if (ferror(hp)) 204 err(1, fname); 205 break; 206 } 207 if (line[0] == '#' || line[0] != '^') | 415 has_sub_topics = 0; 416 while ((line = help_next_line(&hfile)) != NULL) { 417 if (line[0] == '#' || line[0] != '^' || line[1] == '^') |
208 continue; 209 210 if (sscanf(line + 1, "%d%99s", &level, key) != 2) 211 errx(1, "error in help file '%s'", line); 212 213 if (level < optind) 214 break; | 418 continue; 419 420 if (sscanf(line + 1, "%d%99s", &level, key) != 2) 421 errx(1, "error in help file '%s'", line); 422 423 if (level < optind) 424 break; |
215 if (level == optind) | 425 if (level == optind) { 426 has_sub_topics = 1; |
216 printf(" %s", key); | 427 printf(" %s", key); |
428 } |
|
217 } | 429 } |
218 printf(" ]\n"); | 430 printf(" ]."); 431 if (!has_sub_topics) 432 printf(" No sub-topics found."); 433 printf("\n"); |
219 exit(1); 220} 221 222int 223main(int argc, char *argv[]) 224{ 225 int opt, i; 226 const struct cmdtab *match, *cc, *tab; --- 294 unchanged lines hidden --- | 434 exit(1); 435} 436 437int 438main(int argc, char *argv[]) 439{ 440 int opt, i; 441 const struct cmdtab *match, *cc, *tab; --- 294 unchanged lines hidden --- |