Deleted Added
full compact
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 ---