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

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)