40 #include <sys/select.h>
41 #include <sys/socket.h>
46 #include <sys/types.h>
52 #include <readline/readline.h>
53 #include <readline/history.h>
59 #include "clientpipe.h"
61 static const char* PROMPT =
"cmd> ";
62 static const char* cli_str =
"client";
69 usage(
char* argv0, FILE* out)
71 fprintf(out,
"Usage: %s [<cmd>]\n", argv0);
72 fprintf(out,
"Simple command line interface to control the signer "
73 "engine daemon.\nIf no cmd is given, the tool is going "
74 "into interactive mode.\n");
76 fprintf(out,
"\nSupported options:\n");
77 fprintf(out,
" -h | --help Show this help and exit.\n");
78 fprintf(out,
" -V | --version Show version and exit.\n");
79 fprintf(out,
" -s | --socket <file> Daemon socketfile \n"
80 " | (default %s).\n", ODS_SE_SOCKFILE);
82 fprintf(out,
"\nBSD licensed, see LICENSE in source package for "
84 fprintf(out,
"Version %s. Report bugs to <%s>.\n",
85 PACKAGE_VERSION, PACKAGE_BUGREPORT);
95 fprintf(out,
"%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
118 extract_msg(
char* buf,
int *pos,
int buflen,
int *exitcode,
int sockfd)
120 char data[ODS_SE_MAXLINE+1], opc;
126 assert(*pos <= buflen);
127 assert(ODS_SE_MAXLINE >= buflen);
131 if (*pos < 3)
return 0;
133 datalen = (buf[1]<<8) | (buf[2]&0xFF);
135 if (datalen+3 <= *pos) {
137 memset(data, 0, ODS_SE_MAXLINE+1);
138 memcpy(data, buf+3, datalen);
140 memmove(buf, buf+datalen+3, *pos);
142 if (opc == CLIENT_OPC_EXIT) {
144 if (datalen != 1)
return -1;
145 *exitcode = (int)buf[3];
149 case CLIENT_OPC_STDOUT:
150 fprintf(stdout,
"%s", data);
152 case CLIENT_OPC_STDERR:
153 fprintf(stdout,
"%s", data);
155 case CLIENT_OPC_PROMPT:
156 fprintf(stdout,
"%s", data);
159 if (!client_handleprompt(sockfd)) {
160 fprintf(stdout,
"\n");
168 }
else if (datalen+3 > buflen) {
171 fprintf(stderr,
"Daemon message to big, truncating.\n");
173 buf[1] = datalen >> 8;
174 buf[2] = datalen & 0xFF;
191 interface_start(
const char* cmd,
const char* servsock_filename)
193 struct sockaddr_un servaddr;
195 int sockfd, flags, exitcode = 0;
196 int ret, n, r, error = 0, inbuf_pos = 0;
197 char userbuf[ODS_SE_MAXLINE], inbuf[ODS_SE_MAXLINE];
199 assert(servsock_filename);
202 if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
203 fprintf(stderr,
"Socket creation failed: %s\n", strerror(errno));
206 bzero(&servaddr,
sizeof(servaddr));
207 servaddr.sun_family = AF_UNIX;
208 strncpy(servaddr.sun_path, servsock_filename,
sizeof(servaddr.sun_path) - 1);
210 if (connect(sockfd, (
const struct sockaddr*) &servaddr,
sizeof(servaddr)) == -1) {
212 if (strncmp(cmd,
"start", 5) == 0) {
213 exitcode = system(ODS_SE_ENGINE);
218 fprintf(stderr,
"Failed to start signer engine\n");
221 }
else if (strcmp(cmd,
"running\n") == 0) {
222 fprintf(stdout,
"Engine not running.\n");
228 "Unable to connect to engine. connect() failed: "
229 "%s (\"%s\")\n", strerror(errno), servsock_filename);
234 if ((flags = fcntl(sockfd, F_GETFL, 0)) == -1) {
235 ods_log_error(
"[%s] unable to start interface, fcntl(F_GETFL) "
236 "failed: %s", cli_str, strerror(errno));
239 }
else if (fcntl(sockfd, F_SETFL, flags|O_NONBLOCK) == -1) {
240 ods_log_error(
"[%s] unable to start interface, fcntl(F_SETFL) "
241 "failed: %s", cli_str, strerror(errno));
248 if (cmd) client_stdin(sockfd, cmd, strlen(cmd)+1);
255 if ((icmd_ptr = readline(PROMPT)) == NULL) {
259 if (snprintf(userbuf, ODS_SE_MAXLINE,
"%s", icmd_ptr) >= ODS_SE_MAXLINE) {
263 ods_str_trim(userbuf,0);
264 if (strlen(userbuf) > 0) add_history(userbuf);
266 fprintf(stdout,
"%s", PROMPT);
268 n = read(fileno(stdin), userbuf, ODS_SE_MAXLINE);
272 }
else if (n == -1) {
277 ods_str_trim(userbuf,0);
280 if (strcmp(userbuf,
"exit") == 0 || strcmp(userbuf,
"quit") == 0)
283 if (!client_stdin(sockfd, userbuf, strlen(userbuf))) {
285 if (strcmp(userbuf,
"start") == 0) {
286 if (system(ODS_EN_ENGINE) != 0) {
287 fprintf(stderr,
"Error: Daemon reported a failure starting. "
288 "Please consult the logfiles.\n");
299 FD_SET(sockfd, &rset);
301 ret = select(sockfd+1, &rset, NULL, NULL, NULL);
304 if (errno == EINTR)
continue;
311 if (FD_ISSET(sockfd, &rset)) {
312 n = read(sockfd, inbuf+inbuf_pos, ODS_SE_MAXLINE-inbuf_pos);
314 fprintf(stderr,
"[Remote closed connection]\n");
317 }
else if (n == -1) {
318 if (errno == EAGAIN || errno == EWOULDBLOCK)
continue;
324 r = extract_msg(inbuf, &inbuf_pos, ODS_SE_MAXLINE, &exitcode, sockfd);
326 fprintf(stderr,
"Error handling message from daemon\n");
332 else if (strlen(userbuf) != 0)
335 fprintf(stderr,
"Daemon exit code: %d\n", exitcode);
340 if (strlen(userbuf) != 0 && !strncmp(userbuf,
"stop", 4))
342 }
while (error == 0 && !cmd);
345 if ((cmd && !strncmp(cmd,
"stop", 4)) ||
346 (strlen(userbuf) != 0 && !strncmp(userbuf,
"stop", 4))) {
348 FILE *cmd2 = popen(
"pgrep ods-signerd",
"r");
349 fgets(line, 80, cmd2);
351 pid_t pid = strtoul(line, NULL, 10);
352 fprintf(stdout,
"pid %d\n", pid);
356 if(kill(pid, 0) == 0){
360 printf(
"signer needs more time to stop...\n");
381 char const *socketfile = ODS_SE_SOCKFILE;
382 int error, c, options_index = 0;
383 static struct option long_options[] = {
384 {
"help", no_argument, 0,
'h'},
385 {
"socket", required_argument, 0,
's'},
386 {
"version", no_argument, 0,
'V'},
390 ods_log_init(
"ods-signerd", 0, NULL, 0);
393 if((argv0 = strrchr(argv[0],
'/')) == NULL)
399 fprintf(stderr,
"error, too many arguments (%d)\n", argc);
407 while ((c=getopt_long(argc, argv,
"+hVs:",
408 long_options, &options_index)) != -1) {
411 usage(argv0, stdout);
415 printf(
"sock set to %s\n", socketfile);
423 fprintf(stderr,
"use --help for usage information\n");
430 fprintf(stderr,
"Enforcer socket file not set.\n");
434 cmd = ods_strcat_delim(argc, argv,
' ');
435 error = interface_start(cmd, socketfile);
int main(int argc, char *argv[])