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

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)