-
-
Notifications
You must be signed in to change notification settings - Fork 395
INSTCMD and SET VAR status tracking implementation #659
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
Changes from all commits
72241ad
b7c0a9a
97c51c9
bf46107
a348995
2a171dd
f802054
0f3a01b
f67ab8d
3104343
f3ac852
fe6c478
d30e0cb
6cdbe93
823e968
4d36b83
aef9ea7
25eca74
2e9c27c
f91255d
1473496
f91c893
b7d278d
9989123
7fda5a7
deb2279
f688d2c
5da7391
8d5a035
87f59e7
a619455
69b66e6
57de34f
e14c739
5a5c8c8
7c7bc13
0fdc984
496d2c6
de0deb3
787d584
a31e5e4
663dd9f
c0c478b
3948f09
155e795
9a40084
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
/* upscmd - simple "client" to test instant commands via upsd | ||
|
||
Copyright (C) 2000 Russell Kroll <[email protected]> | ||
Copyright (C) | ||
2000 Russell Kroll <[email protected]> | ||
2019 EATON (author: Arnaud Quette <[email protected]>) | ||
|
||
This program is free software; you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
|
@@ -28,8 +30,10 @@ | |
|
||
#include "upsclient.h" | ||
|
||
static char *upsname = NULL, *hostname = NULL; | ||
static char *upsname = NULL, *hostname = NULL; | ||
static UPSCONN_t *ups = NULL; | ||
static int tracking_enabled = 0; | ||
static unsigned int timeout = DEFAULT_TRACKING_TIMEOUT; | ||
|
||
struct list_t { | ||
char *name; | ||
|
@@ -41,13 +45,16 @@ static void usage(const char *prog) | |
printf("Network UPS Tools upscmd %s\n\n", UPS_VERSION); | ||
printf("usage: %s [-h]\n", prog); | ||
printf(" %s [-l <ups>]\n", prog); | ||
printf(" %s [-u <username>] [-p <password>] <ups> <command> [<value>]\n\n", prog); | ||
printf(" %s [-u <username>] [-p <password>] [-w] [-t <timeout>] <ups> <command> [<value>]\n\n", prog); | ||
printf("Administration program to initiate instant commands on UPS hardware.\n"); | ||
printf("\n"); | ||
printf(" -h display this help text\n"); | ||
printf(" -l <ups> show available commands on UPS <ups>\n"); | ||
printf(" -u <username> set username for command authentication\n"); | ||
printf(" -p <password> set password for command authentication\n"); | ||
printf(" -w wait for the completion of command by the driver\n"); | ||
printf(" and return its actual result from the device\n"); | ||
printf(" -t <timeout> set a timeout when using -w (in seconds, default: %u)\n", DEFAULT_TRACKING_TIMEOUT); | ||
printf("\n"); | ||
printf(" <ups> UPS identifier - <upsname>[@<hostname>[:<port>]]\n"); | ||
printf(" <command> Valid instant command - test.panel.start, etc.\n"); | ||
|
@@ -138,7 +145,10 @@ static void listcmds(void) | |
|
||
static void do_cmd(char **argv, const int argc) | ||
{ | ||
int cmd_complete = 0; | ||
char buf[SMALLBUF]; | ||
char tracking_id[UUID4_LEN]; | ||
time_t start, now; | ||
|
||
if (argc > 1) { | ||
snprintf(buf, sizeof(buf), "INSTCMD %s %s %s\n", upsname, argv[0], argv[1]); | ||
|
@@ -154,11 +164,49 @@ static void do_cmd(char **argv, const int argc) | |
fatalx(EXIT_FAILURE, "Instant command failed: %s", upscli_strerror(ups)); | ||
} | ||
|
||
/* FUTURE: status cookies will tie in here */ | ||
/* verify answer */ | ||
if (strncmp(buf, "OK", 2) != 0) { | ||
fatalx(EXIT_FAILURE, "Unexpected response from upsd: %s", buf); | ||
} | ||
|
||
/* check for status tracking id */ | ||
if ( | ||
!tracking_enabled || | ||
/* sanity check on the size: "OK TRACKING " + UUID4_LEN */ | ||
strlen(buf) != (UUID4_LEN - 1 + strlen("OK TRACKING ")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From my reading of standards and docs in UUID-related codebases, at least two correct spellings of an UUID value are possible: the hexadecimal string broken by dashes in correct positions, or just the all-hex string (shorter). Our updated header defines What if the user passes a valid non-dashed version (so At the very least, I think we should avoid surprises by documenting that the current code requires the particular spelling of UUID string. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure it's worth: the intent is not to have real UUID v4, but more something (a key) unique enough to avoid collisions. Whatever the user passes has to be valid, and was supposed to have been provided before. If he passes random string, or non dashed ID or whatever, this will be truncated and discarded. |
||
) { | ||
/* reply as usual */ | ||
fprintf(stderr, "%s\n", buf); | ||
return; | ||
} | ||
|
||
snprintf(tracking_id, sizeof(tracking_id), "%s", buf + strlen("OK TRACKING ")); | ||
time(&start); | ||
|
||
/* send status tracking request, looping if status is PENDING */ | ||
while (!cmd_complete) { | ||
|
||
/* check for timeout */ | ||
time(&now); | ||
if (difftime(now, start) >= timeout) | ||
fatalx(EXIT_FAILURE, "Can't receive status tracking information: timeout"); | ||
|
||
snprintf(buf, sizeof(buf), "GET TRACKING %s\n", tracking_id); | ||
|
||
if (upscli_sendline(ups, buf, strlen(buf)) < 0) | ||
fatalx(EXIT_FAILURE, "Can't send status tracking request: %s", upscli_strerror(ups)); | ||
|
||
/* and get status tracking reply */ | ||
if (upscli_readline_timeout(ups, buf, sizeof(buf), timeout) < 0) | ||
fatalx(EXIT_FAILURE, "Can't receive status tracking information: %s", upscli_strerror(ups)); | ||
|
||
if (strncmp(buf, "PENDING", 7)) | ||
cmd_complete = 1; | ||
else | ||
/* wait a second before retrying */ | ||
sleep(1); | ||
} | ||
|
||
fprintf(stderr, "%s\n", buf); | ||
} | ||
|
||
|
@@ -180,7 +228,7 @@ int main(int argc, char **argv) | |
char buf[SMALLBUF], username[SMALLBUF], password[SMALLBUF]; | ||
const char *prog = xbasename(argv[0]); | ||
|
||
while ((i = getopt(argc, argv, "+lhu:p:V")) != -1) { | ||
while ((i = getopt(argc, argv, "+lhu:p:t:wV")) != -1) { | ||
|
||
switch (i) | ||
{ | ||
|
@@ -198,6 +246,15 @@ int main(int argc, char **argv) | |
have_pw = 1; | ||
break; | ||
|
||
case 't': | ||
if (!str_to_uint(optarg, &timeout, 10)) | ||
fatal_with_errno(EXIT_FAILURE, "Could not convert the provided value for timeout ('-t' option) to unsigned int"); | ||
break; | ||
|
||
case 'w': | ||
tracking_enabled = 1; | ||
break; | ||
|
||
case 'V': | ||
fatalx(EXIT_SUCCESS, "Network UPS Tools upscmd %s", UPS_VERSION); | ||
|
||
|
@@ -313,6 +370,25 @@ int main(int argc, char **argv) | |
fatalx(EXIT_FAILURE, "Set password failed: %s", upscli_strerror(ups)); | ||
} | ||
|
||
/* enable status tracking ID */ | ||
if (tracking_enabled) { | ||
|
||
snprintf(buf, sizeof(buf), "SET TRACKING ON\n"); | ||
|
||
if (upscli_sendline(ups, buf, strlen(buf)) < 0) { | ||
fatalx(EXIT_FAILURE, "Can't enable command status tracking: %s", upscli_strerror(ups)); | ||
} | ||
|
||
if (upscli_readline(ups, buf, sizeof(buf)) < 0) { | ||
fatalx(EXIT_FAILURE, "Enabling command status tracking failed: %s", upscli_strerror(ups)); | ||
} | ||
|
||
/* Verify the result */ | ||
if (strncmp(buf, "OK", 2) != 0) { | ||
fatalx(EXIT_FAILURE, "Enabling command status tracking failed. upsd answered: %s", buf); | ||
} | ||
} | ||
|
||
do_cmd(&argv[1], argc - 1); | ||
|
||
exit(EXIT_SUCCESS); | ||
|
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.
Note to self (and others): this impacts library filename and packaging/dependencies.