-
Notifications
You must be signed in to change notification settings - Fork 60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dtls-client.c: accept options after arguments. #221
Merged
boaks
merged 1 commit into
eclipse-tinydtls:main
from
boaks:support_cli_options_behind_arguments
Aug 28, 2024
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -359,7 +359,7 @@ usage( const char *program, const char *version) { | |
program = ++p; | ||
|
||
fprintf(stderr, "%s v%s -- DTLS client implementation\n" | ||
"(c) 2011-2014 Olaf Bergmann <[email protected]>\n\n" | ||
"(c) 2011-2024 Olaf Bergmann <[email protected]>\n\n" | ||
#ifdef DTLS_PSK | ||
"usage: %s [-c cipher suites] [-e] [-i file] [-k file] [-o file]\n" | ||
" %*s [-p port] [-r] [-v num] addr [port]\n", | ||
|
@@ -411,6 +411,7 @@ int | |
main(int argc, char **argv) { | ||
fd_set rfds, wfds; | ||
struct timeval timeout; | ||
unsigned short dst_port = 0; | ||
unsigned short port = DEFAULT_PORT; | ||
char port_str[NI_MAXSERV] = "0"; | ||
log_t log_level = DTLS_LOG_WARN; | ||
|
@@ -423,7 +424,7 @@ main(int argc, char **argv) { | |
size_t len = 0; | ||
int buf_ready = 0; | ||
|
||
|
||
memset(&dst, 0, sizeof(session_t)); | ||
dtls_init(); | ||
snprintf(port_str, sizeof(port_str), "%d", port); | ||
|
||
|
@@ -434,7 +435,8 @@ main(int argc, char **argv) { | |
memcpy(psk_key, PSK_DEFAULT_KEY, psk_key_length); | ||
#endif /* DTLS_PSK */ | ||
|
||
while ((opt = getopt(argc, argv, "c:eo:p:rv:" PSK_OPTIONS)) != -1) { | ||
while (optind < argc) { | ||
opt = getopt(argc, argv, "c:eo:p:rv:z" PSK_OPTIONS); | ||
switch (opt) { | ||
#ifdef DTLS_PSK | ||
case 'i' : | ||
|
@@ -482,31 +484,48 @@ main(int argc, char **argv) { | |
case 'v' : | ||
log_level = strtol(optarg, NULL, 10); | ||
break; | ||
case -1 : | ||
/* handle arguments */ | ||
if (!dst.size) { | ||
/* first argument: destination address */ | ||
/* resolve destination address of server where data should be sent */ | ||
res = resolve_address(argv[optind++], &dst.addr.sa); | ||
if (res < 0) { | ||
dtls_emerg("failed to resolve address\n"); | ||
exit(-1); | ||
} | ||
dst.size = res; | ||
} else if (!dst_port) { | ||
/* second argument: destination port (optional) */ | ||
dst_port = atoi(argv[optind++]); | ||
} else { | ||
dtls_warn("too many arguments!\n"); | ||
usage(argv[0], dtls_package_version()); | ||
exit(1); | ||
} | ||
break; | ||
default: | ||
usage(argv[0], dtls_package_version()); | ||
exit(1); | ||
} | ||
} | ||
|
||
dtls_set_log_level(log_level); | ||
|
||
if (argc <= optind) { | ||
if (!dst.size) { | ||
dtls_warn("missing destination address!\n"); | ||
usage(argv[0], dtls_package_version()); | ||
exit(1); | ||
} | ||
|
||
memset(&dst, 0, sizeof(session_t)); | ||
/* resolve destination address where server should be sent */ | ||
res = resolve_address(argv[optind++], &dst.addr.sa); | ||
if (res < 0) { | ||
dtls_emerg("failed to resolve address\n"); | ||
exit(-1); | ||
if (!dst_port) { | ||
/* destination port not provided, use default */ | ||
dst_port = DEFAULT_PORT; | ||
} | ||
if (dst.addr.sa.sa_family == AF_INET6) { | ||
dst.addr.sin6.sin6_port = htons(dst_port); | ||
} else { | ||
dst.addr.sin.sin_port = htons(dst_port); | ||
} | ||
dst.size = res; | ||
|
||
/* use port number from command line when specified or the listen | ||
port, otherwise */ | ||
dst.addr.sin.sin_port = htons(atoi(optind < argc ? argv[optind++] : port_str)); | ||
dtls_set_log_level(log_level); | ||
|
||
/* init socket and set it to non-blocking */ | ||
fd = socket(dst.addr.sa.sa_family, SOCK_DGRAM, 0); | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From PR #222 (@mrdeep1 )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure, if "very unusual" really applies.
What I found:
The dtls-client silently ignores options after the arguments. We can either stick to that or process arguments (opt == -1) while incrementing
optind
to over come that. If someone wants options to be treated as arguments, using "--" works well.Assuming the support for options after arguments should be supported, the '-1' may be processed either within the switch or ahead by checking for -1. I decided for this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a side note, Windows
getopt()
general implementation does not support having options after arguments as this is not in the POSIX standard, but is supported by GNU.See https://stackoverflow.com/questions/58429368/getopt-does-not-order-arguments-in-windows
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively would be to fail on additional arguments/options after the port. The code before just silently ignored that. The check
if (argc <= optind) {
doesn't work forThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It appears (for GNU), that
gets argv{} populated as
as per
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I run in this issue with Ubuntu 20.04 and 22.04 and the default toolchains that comes with them. AFAIK, that's GNU.
If "getopt()" stops the return options after first ".1", the code of this PR would then print an error and the usage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's what I get with gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah - I was running this on an older environment. If (for Ubuntu) you add in
#define _GNU_SOURCE
at the start ofdtls-client.c
, then my debug output of the above is true.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:-).
My sum-up:
There are different implementations of
getopt
. And there are also some compiler specific options, which sorts the CLI arguments. If it's sorted, a simpler PR would also do it, but this one also doesn't harm.If "getopt" doesn't support options after the arguments, this PR can't change that, but doesn't harm. In difference to the implementation before, it would report options after arguments as error.
If the arguments are not sorted before, and "getopt" still works after the arguments, this PR enables to use options after the arguments.
Therefore for me this PR helps to get the "best" out of the plenty implementations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.