helper: skip including sys/sysctl.h on Linux
[openocd.git] / src / helper / options.c
1 /***************************************************************************
2 * Copyright (C) 2004, 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2007-2010 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
20 ***************************************************************************/
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "configuration.h"
27 #include "log.h"
28 #include "command.h"
29
30 #include <getopt.h>
31
32 #include <limits.h>
33 #include <stdlib.h>
34 #if IS_DARWIN
35 #include <libproc.h>
36 #endif
37 /* sys/sysctl.h is deprecated on Linux from glibc 2.30 */
38 #ifndef __linux__
39 #ifdef HAVE_SYS_SYSCTL_H
40 #include <sys/sysctl.h>
41 #endif
42 #endif
43 #if IS_WIN32 && !IS_CYGWIN
44 #include <windows.h>
45 #endif
46
47 static int help_flag, version_flag;
48
49 static const struct option long_options[] = {
50 {"help", no_argument, &help_flag, 1},
51 {"version", no_argument, &version_flag, 1},
52 {"debug", optional_argument, 0, 'd'},
53 {"file", required_argument, 0, 'f'},
54 {"search", required_argument, 0, 's'},
55 {"log_output", required_argument, 0, 'l'},
56 {"command", required_argument, 0, 'c'},
57 {"pipe", no_argument, 0, 'p'},
58 {0, 0, 0, 0}
59 };
60
61 int configuration_output_handler(struct command_context *context, const char *line)
62 {
63 LOG_USER_N("%s", line);
64
65 return ERROR_OK;
66 }
67
68 /* Return the canonical path to the directory the openocd executable is in.
69 * The path should be absolute, use / as path separator and have all symlinks
70 * resolved. The returned string is malloc'd. */
71 static char *find_exe_path(void)
72 {
73 char *exepath = NULL;
74
75 do {
76 #if IS_WIN32 && !IS_CYGWIN
77 exepath = malloc(MAX_PATH);
78 if (exepath == NULL)
79 break;
80 GetModuleFileName(NULL, exepath, MAX_PATH);
81
82 /* Convert path separators to UNIX style, should work on Windows also. */
83 for (char *p = exepath; *p; p++) {
84 if (*p == '\\')
85 *p = '/';
86 }
87
88 #elif IS_DARWIN
89 exepath = malloc(PROC_PIDPATHINFO_MAXSIZE);
90 if (exepath == NULL)
91 break;
92 if (proc_pidpath(getpid(), exepath, PROC_PIDPATHINFO_MAXSIZE) <= 0) {
93 free(exepath);
94 exepath = NULL;
95 }
96
97 #elif defined(CTL_KERN) && defined(KERN_PROC) && defined(KERN_PROC_PATHNAME) /* *BSD */
98 #ifndef PATH_MAX
99 #define PATH_MAX 1024
100 #endif
101 char *path = malloc(PATH_MAX);
102 if (path == NULL)
103 break;
104 int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
105 size_t size = PATH_MAX;
106
107 if (sysctl(mib, (u_int)ARRAY_SIZE(mib), path, &size, NULL, 0) != 0)
108 break;
109
110 #ifdef HAVE_REALPATH
111 exepath = realpath(path, NULL);
112 free(path);
113 #else
114 exepath = path;
115 #endif
116
117 #elif defined(HAVE_REALPATH) /* Assume POSIX.1-2008 */
118 /* Try Unices in order of likelihood. */
119 exepath = realpath("/proc/self/exe", NULL); /* Linux/Cygwin */
120 if (exepath == NULL)
121 exepath = realpath("/proc/self/path/a.out", NULL); /* Solaris */
122 if (exepath == NULL)
123 exepath = realpath("/proc/curproc/file", NULL); /* FreeBSD (Should be covered above) */
124 #endif
125 } while (0);
126
127 if (exepath != NULL) {
128 /* Strip executable file name, leaving path */
129 *strrchr(exepath, '/') = '\0';
130 } else {
131 LOG_WARNING("Could not determine executable path, using configured BINDIR.");
132 LOG_DEBUG("BINDIR = %s", BINDIR);
133 #ifdef HAVE_REALPATH
134 exepath = realpath(BINDIR, NULL);
135 #else
136 exepath = strdup(BINDIR);
137 #endif
138 }
139
140 return exepath;
141 }
142
143 static char *find_relative_path(const char *from, const char *to)
144 {
145 size_t i;
146
147 /* Skip common /-separated parts of from and to */
148 i = 0;
149 for (size_t n = 0; from[n] == to[n]; n++) {
150 if (from[n] == '\0') {
151 i = n;
152 break;
153 }
154 if (from[n] == '/')
155 i = n + 1;
156 }
157 from += i;
158 to += i;
159
160 /* Count number of /-separated non-empty parts of from */
161 i = 0;
162 while (from[0] != '\0') {
163 if (from[0] != '/')
164 i++;
165 char *next = strchr(from, '/');
166 if (next == NULL)
167 break;
168 from = next + 1;
169 }
170
171 /* Prepend that number of ../ in front of to */
172 char *relpath = malloc(i * 3 + strlen(to) + 1);
173 relpath[0] = '\0';
174 for (size_t n = 0; n < i; n++)
175 strcat(relpath, "../");
176 strcat(relpath, to);
177
178 return relpath;
179 }
180
181 static void add_default_dirs(void)
182 {
183 char *path;
184 char *exepath = find_exe_path();
185 char *bin2data = find_relative_path(BINDIR, PKGDATADIR);
186
187 LOG_DEBUG("bindir=%s", BINDIR);
188 LOG_DEBUG("pkgdatadir=%s", PKGDATADIR);
189 LOG_DEBUG("exepath=%s", exepath);
190 LOG_DEBUG("bin2data=%s", bin2data);
191
192 /*
193 * The directory containing OpenOCD-supplied scripts should be
194 * listed last in the built-in search order, so the user can
195 * override these scripts with site-specific customizations.
196 */
197 const char *home = getenv("HOME");
198
199 if (home) {
200 path = alloc_printf("%s/.openocd", home);
201 if (path) {
202 add_script_search_dir(path);
203 free(path);
204 }
205 }
206
207 path = getenv("OPENOCD_SCRIPTS");
208
209 if (path)
210 add_script_search_dir(path);
211
212 #ifdef _WIN32
213 const char *appdata = getenv("APPDATA");
214
215 if (appdata) {
216 path = alloc_printf("%s/OpenOCD", appdata);
217 if (path) {
218 add_script_search_dir(path);
219 free(path);
220 }
221 }
222 #endif
223
224 path = alloc_printf("%s/%s/%s", exepath, bin2data, "site");
225 if (path) {
226 add_script_search_dir(path);
227 free(path);
228 }
229
230 path = alloc_printf("%s/%s/%s", exepath, bin2data, "scripts");
231 if (path) {
232 add_script_search_dir(path);
233 free(path);
234 }
235
236 free(exepath);
237 free(bin2data);
238 }
239
240 int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
241 {
242 int c;
243
244 while (1) {
245 /* getopt_long stores the option index here. */
246 int option_index = 0;
247
248 c = getopt_long(argc, argv, "hvd::l:f:s:c:p", long_options, &option_index);
249
250 /* Detect the end of the options. */
251 if (c == -1)
252 break;
253
254 switch (c) {
255 case 0:
256 break;
257 case 'h': /* --help | -h */
258 help_flag = 1;
259 break;
260 case 'v': /* --version | -v */
261 version_flag = 1;
262 break;
263 case 'f': /* --file | -f */
264 {
265 char *command = alloc_printf("script {%s}", optarg);
266 add_config_command(command);
267 free(command);
268 break;
269 }
270 case 's': /* --search | -s */
271 add_script_search_dir(optarg);
272 break;
273 case 'd': /* --debug | -d */
274 {
275 int retval = command_run_linef(cmd_ctx, "debug_level %s", optarg ? optarg : "3");
276 if (retval != ERROR_OK)
277 return retval;
278 break;
279 }
280 case 'l': /* --log_output | -l */
281 if (optarg)
282 command_run_linef(cmd_ctx, "log_output %s", optarg);
283 break;
284 case 'c': /* --command | -c */
285 if (optarg)
286 add_config_command(optarg);
287 break;
288 case 'p':
289 /* to replicate the old syntax this needs to be synchronous
290 * otherwise the gdb stdin will overflow with the warning message */
291 command_run_line(cmd_ctx, "gdb_port pipe; log_output openocd.log");
292 LOG_WARNING("deprecated option: -p/--pipe. Use '-c \"gdb_port pipe; "
293 "log_output openocd.log\"' instead.");
294 break;
295 default: /* '?' */
296 /* getopt will emit an error message, all we have to do is bail. */
297 return ERROR_FAIL;
298 }
299 }
300
301 if (optind < argc) {
302 /* Catch extra arguments on the command line. */
303 LOG_OUTPUT("Unexpected command line argument: %s\n", argv[optind]);
304 return ERROR_FAIL;
305 }
306
307 if (help_flag) {
308 LOG_OUTPUT("Open On-Chip Debugger\nLicensed under GNU GPL v2\n");
309 LOG_OUTPUT("--help | -h\tdisplay this help\n");
310 LOG_OUTPUT("--version | -v\tdisplay OpenOCD version\n");
311 LOG_OUTPUT("--file | -f\tuse configuration file <name>\n");
312 LOG_OUTPUT("--search | -s\tdir to search for config files and scripts\n");
313 LOG_OUTPUT("--debug | -d\tset debug level to 3\n");
314 LOG_OUTPUT(" | -d<n>\tset debug level to <level>\n");
315 LOG_OUTPUT("--log_output | -l\tredirect log output to file <name>\n");
316 LOG_OUTPUT("--command | -c\trun <command>\n");
317 exit(-1);
318 }
319
320 if (version_flag) {
321 /* Nothing to do, version gets printed automatically. */
322 /* It is not an error to request the VERSION number. */
323 exit(0);
324 }
325
326 /* paths specified on the command line take precedence over these
327 * built-in paths
328 */
329 add_default_dirs();
330
331 return ERROR_OK;
332 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)