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

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)