Cleanup of config/includes.
[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 #include <string.h>
35 #if IS_DARWIN
36 #include <libproc.h>
37 #endif
38 /* sys/sysctl.h is deprecated on Linux from glibc 2.30 */
39 #ifndef __linux__
40 #ifdef HAVE_SYS_SYSCTL_H
41 #include <sys/sysctl.h>
42 #endif
43 #endif
44 #if IS_WIN32 && !IS_CYGWIN
45 #include <windows.h>
46 #endif
47
48 static int help_flag, version_flag;
49
50 static const struct option long_options[] = {
51 {"help", no_argument, &help_flag, 1},
52 {"version", no_argument, &version_flag, 1},
53 {"debug", optional_argument, 0, 'd'},
54 {"file", required_argument, 0, 'f'},
55 {"search", required_argument, 0, 's'},
56 {"log_output", required_argument, 0, 'l'},
57 {"command", required_argument, 0, 'c'},
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_user_dirs(void)
182 {
183 char *path;
184
185 #if IS_WIN32
186 const char *appdata = getenv("APPDATA");
187
188 if (appdata) {
189 path = alloc_printf("%s/OpenOCD", appdata);
190 if (path) {
191 /* Convert path separators to UNIX style, should work on Windows also. */
192 for (char *p = path; *p; p++) {
193 if (*p == '\\')
194 *p = '/';
195 }
196 add_script_search_dir(path);
197 free(path);
198 }
199 }
200 /* WIN32 may also have HOME defined, particularly under Cygwin, so add those paths below too */
201 #endif
202
203 const char *home = getenv("HOME");
204 #if IS_DARWIN
205 if (home) {
206 path = alloc_printf("%s/Library/Preferences/org.openocd", home);
207 if (path) {
208 add_script_search_dir(path);
209 free(path);
210 }
211 }
212 #endif
213 const char *xdg_config = getenv("XDG_CONFIG_HOME");
214
215 if (xdg_config) {
216 path = alloc_printf("%s/openocd", xdg_config);
217 if (path) {
218 add_script_search_dir(path);
219 free(path);
220 }
221 } else if (home) {
222 path = alloc_printf("%s/.config/openocd", home);
223 if (path) {
224 add_script_search_dir(path);
225 free(path);
226 }
227 }
228
229 if (home) {
230 path = alloc_printf("%s/.openocd", home);
231 if (path) {
232 add_script_search_dir(path);
233 free(path);
234 }
235 }
236 }
237
238 static void add_default_dirs(void)
239 {
240 char *path;
241 char *exepath = find_exe_path();
242 char *bin2data = find_relative_path(BINDIR, PKGDATADIR);
243
244 LOG_DEBUG("bindir=%s", BINDIR);
245 LOG_DEBUG("pkgdatadir=%s", PKGDATADIR);
246 LOG_DEBUG("exepath=%s", exepath);
247 LOG_DEBUG("bin2data=%s", bin2data);
248
249 /*
250 * The directory containing OpenOCD-supplied scripts should be
251 * listed last in the built-in search order, so the user can
252 * override these scripts with site-specific customizations.
253 */
254 path = getenv("OPENOCD_SCRIPTS");
255 if (path)
256 add_script_search_dir(path);
257
258 add_user_dirs();
259
260 path = alloc_printf("%s/%s/%s", exepath, bin2data, "site");
261 if (path) {
262 add_script_search_dir(path);
263 free(path);
264 }
265
266 path = alloc_printf("%s/%s/%s", exepath, bin2data, "scripts");
267 if (path) {
268 add_script_search_dir(path);
269 free(path);
270 }
271
272 free(exepath);
273 free(bin2data);
274 }
275
276 int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
277 {
278 int c;
279
280 while (1) {
281 /* getopt_long stores the option index here. */
282 int option_index = 0;
283
284 c = getopt_long(argc, argv, "hvd::l:f:s:c:", long_options, &option_index);
285
286 /* Detect the end of the options. */
287 if (c == -1)
288 break;
289
290 switch (c) {
291 case 0:
292 break;
293 case 'h': /* --help | -h */
294 help_flag = 1;
295 break;
296 case 'v': /* --version | -v */
297 version_flag = 1;
298 break;
299 case 'f': /* --file | -f */
300 {
301 char *command = alloc_printf("script {%s}", optarg);
302 add_config_command(command);
303 free(command);
304 break;
305 }
306 case 's': /* --search | -s */
307 add_script_search_dir(optarg);
308 break;
309 case 'd': /* --debug | -d */
310 {
311 int retval = command_run_linef(cmd_ctx, "debug_level %s", optarg ? optarg : "3");
312 if (retval != ERROR_OK)
313 return retval;
314 break;
315 }
316 case 'l': /* --log_output | -l */
317 if (optarg)
318 command_run_linef(cmd_ctx, "log_output %s", optarg);
319 break;
320 case 'c': /* --command | -c */
321 if (optarg)
322 add_config_command(optarg);
323 break;
324 default: /* '?' */
325 /* getopt will emit an error message, all we have to do is bail. */
326 return ERROR_FAIL;
327 }
328 }
329
330 if (optind < argc) {
331 /* Catch extra arguments on the command line. */
332 LOG_OUTPUT("Unexpected command line argument: %s\n", argv[optind]);
333 return ERROR_FAIL;
334 }
335
336 if (help_flag) {
337 LOG_OUTPUT("Open On-Chip Debugger\nLicensed under GNU GPL v2\n");
338 LOG_OUTPUT("--help | -h\tdisplay this help\n");
339 LOG_OUTPUT("--version | -v\tdisplay OpenOCD version\n");
340 LOG_OUTPUT("--file | -f\tuse configuration file <name>\n");
341 LOG_OUTPUT("--search | -s\tdir to search for config files and scripts\n");
342 LOG_OUTPUT("--debug | -d\tset debug level to 3\n");
343 LOG_OUTPUT(" | -d<n>\tset debug level to <level>\n");
344 LOG_OUTPUT("--log_output | -l\tredirect log output to file <name>\n");
345 LOG_OUTPUT("--command | -c\trun <command>\n");
346 exit(-1);
347 }
348
349 if (version_flag) {
350 /* Nothing to do, version gets printed automatically. */
351 /* It is not an error to request the VERSION number. */
352 exit(0);
353 }
354
355 /* paths specified on the command line take precedence over these
356 * built-in paths
357 */
358 add_default_dirs();
359
360 return ERROR_OK;
361 }

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)