/src/ntp-dev/sntp/libopts/pgusage.c
Line | Count | Source (jump to first uncovered line) |
1 | | |
2 | | /** |
3 | | * \file pgusage.c |
4 | | * |
5 | | * Automated Options Paged Usage module. |
6 | | * |
7 | | * @addtogroup autoopts |
8 | | * @{ |
9 | | */ |
10 | | /* |
11 | | * This routine will run run-on options through a pager so the |
12 | | * user may examine, print or edit them at their leisure. |
13 | | * |
14 | | * This file is part of AutoOpts, a companion to AutoGen. |
15 | | * AutoOpts is free software. |
16 | | * AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved |
17 | | * |
18 | | * AutoOpts is available under any one of two licenses. The license |
19 | | * in use must be one of these two and the choice is under the control |
20 | | * of the user of the license. |
21 | | * |
22 | | * The GNU Lesser General Public License, version 3 or later |
23 | | * See the files "COPYING.lgplv3" and "COPYING.gplv3" |
24 | | * |
25 | | * The Modified Berkeley Software Distribution License |
26 | | * See the file "COPYING.mbsd" |
27 | | * |
28 | | * These files have the following sha256 sums: |
29 | | * |
30 | | * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 |
31 | | * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 |
32 | | * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd |
33 | | */ |
34 | | |
35 | | #if defined(HAVE_WORKING_FORK) |
36 | | static inline FILE * |
37 | | open_tmp_usage(char ** buf) |
38 | 0 | { |
39 | 0 | char * bf; |
40 | 0 | size_t bfsz; |
41 | |
|
42 | 0 | { |
43 | 0 | unsigned int my_pid = (unsigned int)getpid(); |
44 | 0 | char const * tmpdir = getenv(TMPDIR); |
45 | 0 | if (tmpdir == NULL) |
46 | 0 | tmpdir = tmp_dir; |
47 | 0 | bfsz = TMP_FILE_FMT_LEN + strlen(tmpdir) + 10; |
48 | 0 | bf = AGALOC(bfsz, "tmp fil"); |
49 | 0 | snprintf(bf, bfsz, TMP_FILE_FMT, tmpdir, my_pid); |
50 | 0 | } |
51 | |
|
52 | 0 | { |
53 | 0 | static mode_t const cmask = S_IRWXO | S_IRWXG; |
54 | 0 | mode_t svmsk = umask(cmask); |
55 | 0 | int fd = mkstemp(bf); |
56 | 0 | (void)umask(svmsk); |
57 | |
|
58 | 0 | if (fd < 0) { |
59 | 0 | AGFREE(bf); |
60 | 0 | return NULL; |
61 | 0 | } |
62 | 0 | *buf = bf; |
63 | 0 | return fdopen(fd, "w"); |
64 | 0 | } |
65 | 0 | } |
66 | | |
67 | | static inline char * |
68 | | mk_pager_cmd(char const * fname) |
69 | 0 | { |
70 | | /* |
71 | | * Page the file and remove it when done. For shell script processing, |
72 | | * we must redirect the output to the current stderr, otherwise stdout. |
73 | | */ |
74 | 0 | fclose(option_usage_fp); |
75 | 0 | option_usage_fp = NULL; |
76 | |
|
77 | 0 | { |
78 | 0 | char const * pager = (char const *)getenv(PAGER_NAME); |
79 | 0 | size_t bfsz; |
80 | 0 | char * res; |
81 | | |
82 | | /* |
83 | | * Use the "more(1)" program if "PAGER" has not been defined |
84 | | */ |
85 | 0 | if (pager == NULL) |
86 | 0 | pager = MORE_STR; |
87 | |
|
88 | 0 | bfsz = 2 * strlen(fname) + strlen(pager) + PAGE_USAGE_FMT_LEN; |
89 | 0 | res = AGALOC(bfsz, "more cmd"); |
90 | 0 | snprintf(res, bfsz, PAGE_USAGE_FMT, pager, fname); |
91 | 0 | AGFREE(fname); |
92 | 0 | return res; |
93 | 0 | } |
94 | 0 | } |
95 | | #endif |
96 | | |
97 | | /*=export_func optionPagedUsage |
98 | | * private: |
99 | | * |
100 | | * what: emit help text and pass through a pager program. |
101 | | * arg: + tOptions * + opts + program options descriptor + |
102 | | * arg: + tOptDesc * + od + the descriptor for this arg + |
103 | | * |
104 | | * doc: |
105 | | * Run the usage output through a pager. |
106 | | * This is very handy if it is very long. |
107 | | * This is disabled on platforms without a working fork() function. |
108 | | =*/ |
109 | | void |
110 | | optionPagedUsage(tOptions * opts, tOptDesc * od) |
111 | 0 | { |
112 | | #if ! defined(HAVE_WORKING_FORK) |
113 | | if ((od->fOptState & OPTST_RESET) != 0) |
114 | | return; |
115 | | |
116 | | (*opts->pUsageProc)(opts, EXIT_SUCCESS); |
117 | | #else |
118 | 0 | static bool sv_print_exit = false; |
119 | 0 | static char * fil_name = NULL; |
120 | | |
121 | | /* |
122 | | * IF we are being called after the usage proc is done |
123 | | * (and thus has called "exit(2)") |
124 | | * THEN invoke the pager to page through the usage file we created. |
125 | | */ |
126 | 0 | switch (pagerState) { |
127 | 0 | case PAGER_STATE_INITIAL: |
128 | 0 | { |
129 | 0 | if ((od->fOptState & OPTST_RESET) != 0) |
130 | 0 | return; |
131 | 0 | option_usage_fp = open_tmp_usage(&fil_name); |
132 | 0 | if (option_usage_fp == NULL) |
133 | 0 | (*opts->pUsageProc)(opts, EXIT_SUCCESS); |
134 | |
|
135 | 0 | pagerState = PAGER_STATE_READY; |
136 | 0 | sv_print_exit = print_exit; |
137 | | |
138 | | /* |
139 | | * Set up so this routine gets called during the exit logic |
140 | | */ |
141 | 0 | atexit((void(*)(void))optionPagedUsage); |
142 | | |
143 | | /* |
144 | | * The usage procedure will now put the usage information into |
145 | | * the temporary file we created above. Keep any shell commands |
146 | | * out of the result. |
147 | | */ |
148 | 0 | print_exit = false; |
149 | 0 | (*opts->pUsageProc)(opts, EXIT_SUCCESS); |
150 | | |
151 | | /* NOTREACHED */ |
152 | 0 | _exit(EXIT_FAILURE); |
153 | 0 | } |
154 | | |
155 | 0 | case PAGER_STATE_READY: |
156 | 0 | fil_name = mk_pager_cmd(fil_name); |
157 | |
|
158 | 0 | if (sv_print_exit) { |
159 | 0 | fputs("\nexit 0\n", stdout); |
160 | 0 | fclose(stdout); |
161 | 0 | dup2(STDERR_FILENO, STDOUT_FILENO); |
162 | |
|
163 | 0 | } else { |
164 | 0 | fclose(stderr); |
165 | 0 | dup2(STDOUT_FILENO, STDERR_FILENO); |
166 | 0 | } |
167 | |
|
168 | 0 | ignore_val( system( fil_name)); |
169 | 0 | AGFREE(fil_name); |
170 | |
|
171 | 0 | case PAGER_STATE_CHILD: |
172 | | /* |
173 | | * This is a child process used in creating shell script usage. |
174 | | */ |
175 | 0 | break; |
176 | 0 | } |
177 | 0 | #endif |
178 | 0 | } |
179 | | |
180 | | /** @} |
181 | | * |
182 | | * Local Variables: |
183 | | * mode: C |
184 | | * c-file-style: "stroustrup" |
185 | | * indent-tabs-mode: nil |
186 | | * End: |
187 | | * end of autoopts/pgusage.c */ |