00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00034 #include "config.h"
00035 #include "shared/allocator.h"
00036 #include "shared/file.h"
00037 #include "shared/log.h"
00038
00039 #include <errno.h>
00040 #include <fcntl.h>
00041 #include <stdio.h>
00042 #include <string.h>
00043 #include <strings.h>
00044 #include <sys/select.h>
00045 #include <sys/socket.h>
00046 #include <sys/un.h>
00047 #include <unistd.h>
00048
00049
00050 #include <sys/types.h>
00051 #include <sys/time.h>
00052
00053 #define SE_CLI_CMDLEN 6
00054
00055 static const char* cli_str = "client";
00056
00061 static void
00062 usage(FILE* out)
00063 {
00064 fprintf(out, "Usage: %s [<cmd>]\n", "ods-signer");
00065 fprintf(out, "Simple command line interface to control the signer "
00066 "engine daemon.\nIf no cmd is given, the tool is going "
00067 "to interactive mode.\n");
00068 fprintf(out, "\nBSD licensed, see LICENSE in source package for "
00069 "details.\n");
00070 fprintf(out, "Version %s. Report bugs to <%s>.\n",
00071 PACKAGE_VERSION, PACKAGE_BUGREPORT);
00072 }
00073
00074
00079 static int
00080 max(int a, int b)
00081 {
00082 return a<b ? b : a;
00083 }
00084
00085
00090 static void
00091 interface_run(FILE* fp, int sockfd, char* cmd)
00092 {
00093 int maxfdp1 = 0;
00094 int stdineof = 0;
00095 int i = 0;
00096 int n = 0;
00097 int ret = 0;
00098 int cmd_written = 0;
00099 int cmd_response = 0;
00100 int written = 0;
00101 fd_set rset;
00102 char buf[ODS_SE_MAXLINE];
00103
00104 stdineof = 0;
00105 FD_ZERO(&rset);
00106 for(;;) {
00107
00108 if (stdineof == 0) {
00109 FD_SET(fileno(fp), &rset);
00110 }
00111 FD_SET(sockfd, &rset);
00112 maxfdp1 = max(fileno(fp), sockfd) + 1;
00113
00114 if (!cmd || cmd_written) {
00115
00116 ret = select(maxfdp1, &rset, NULL, NULL, NULL);
00117 if (ret < 0) {
00118 if (errno != EINTR && errno != EWOULDBLOCK) {
00119 ods_log_warning("[%s] interface select error: %s",
00120 cli_str, strerror(errno));
00121 }
00122 continue;
00123 }
00124 } else if (cmd) {
00125
00126 ods_writen(sockfd, cmd, strlen(cmd));
00127 cmd_written = 1;
00128 stdineof = 1;
00129 continue;
00130 }
00131
00132 if (cmd && cmd_written && cmd_response) {
00133
00134 return;
00135 }
00136
00137 if (FD_ISSET(sockfd, &rset)) {
00138
00139 for (i=0; i < ODS_SE_MAXLINE; i++) {
00140 buf[i] = 0;
00141 }
00142 buf[ODS_SE_MAXLINE-1] = '\0';
00143
00144
00145 if ((n = read(sockfd, buf, ODS_SE_MAXLINE)) <= 0) {
00146 if (n < 0) {
00147
00148 fprintf(stderr, "error: %s\n", strerror(errno));
00149 exit(1);
00150 } else {
00151
00152 if (stdineof == 1) {
00153
00154 return;
00155 } else {
00156
00157 fprintf(stderr, "signer engine terminated "
00158 "prematurely\n");
00159 exit(1);
00160 }
00161 }
00162 }
00163
00164 if (cmd) {
00165 if (n < SE_CLI_CMDLEN) {
00166
00167 fprintf(stderr, "not enough response data received "
00168 "from daemon.\n");
00169 exit(1);
00170 }
00171
00172
00173
00174 if (strncmp(buf+n-SE_CLI_CMDLEN,"\ncmd> ",SE_CLI_CMDLEN) == 0) {
00175
00176
00177 n -= SE_CLI_CMDLEN;
00178 buf[n] = '\0';
00179 cmd_response = 1;
00180 }
00181 }
00182
00183
00184 for (written=0; written < n; written += ret) {
00185
00186 ret = (int) write(fileno(stdout), &buf[written], n-written);
00187
00188 if (ret == 0) {
00189 fprintf(stderr, "no write\n");
00190 break;
00191 }
00192 if (ret < 0) {
00193 if (errno == EINTR || errno == EWOULDBLOCK) {
00194 ret = 0;
00195 continue;
00196 }
00197 fprintf(stderr, "\n\nwrite error: %s\n", strerror(errno));
00198 break;
00199 }
00200
00201 if (written+ret > n) {
00202 fprintf(stderr, "\n\nwrite error: more bytes (%d) written than required (%d)\n",
00203 written+ret, n);
00204 break;
00205 }
00206
00207 }
00208 if (ods_strcmp(buf, ODS_SE_STOP_RESPONSE) == 0 || cmd_response) {
00209 fprintf(stderr, "\n");
00210 return;
00211 }
00212 }
00213
00214 if (FD_ISSET(fileno(fp), &rset)) {
00215
00216
00217 if (cmd && cmd_written) {
00218
00219 stdineof = 1;
00220 ret = shutdown(sockfd, SHUT_WR);
00221 if (ret != 0) {
00222 fprintf(stderr, "shutdown failed: %s\n",
00223 strerror(errno));
00224 exit(1);
00225 }
00226 FD_CLR(fileno(fp), &rset);
00227 continue;
00228 }
00229
00230
00231 for (i=0; i< ODS_SE_MAXLINE; i++) {
00232 buf[i] = 0;
00233 }
00234
00235
00236 if ((n = read(fileno(fp), buf, ODS_SE_MAXLINE)) == 0) {
00237 stdineof = 1;
00238 ret = shutdown(sockfd, SHUT_WR);
00239 if (ret != 0) {
00240 fprintf(stderr, "shutdown failed: %s\n",
00241 strerror(errno));
00242 exit(1);
00243 }
00244 FD_CLR(fileno(fp), &rset);
00245 continue;
00246 }
00247
00248 buf[ODS_SE_MAXLINE-1] = '\0';
00249 if (strncmp(buf, "exit", 4) == 0 ||
00250 strncmp(buf, "quit", 4) == 0) {
00251 return;
00252 }
00253 ods_str_trim(buf);
00254 n = strlen(buf);
00255 ods_writen(sockfd, buf, n);
00256 }
00257 }
00258 }
00259
00260
00265 static void
00266 interface_start(char* cmd)
00267 {
00268 int sockfd, ret, flags;
00269 struct sockaddr_un servaddr;
00270 const char* servsock_filename = ODS_SE_SOCKFILE;
00271
00272
00273 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
00274 if (sockfd <= 0) {
00275 fprintf(stderr, "Unable to connect to engine. "
00276 "socket() failed: %s\n", strerror(errno));
00277 exit(1);
00278 }
00279
00280
00281 bzero(&servaddr, sizeof(servaddr));
00282 servaddr.sun_family = AF_UNIX;
00283 strncpy(servaddr.sun_path, servsock_filename,
00284 sizeof(servaddr.sun_path) - 1);
00285
00286
00287 ret = connect(sockfd, (const struct sockaddr*) &servaddr,
00288 sizeof(servaddr));
00289 if (ret != 0) {
00290 if (cmd && ods_strcmp(cmd, "start\n") == 0) {
00291 ret = system(ODS_SE_ENGINE);
00292 return;
00293 }
00294
00295 if (cmd && ods_strcmp(cmd, "running\n") == 0) {
00296 fprintf(stderr, "Engine not running.\n");
00297 } else {
00298 fprintf(stderr, "Unable to connect to engine: "
00299 "connect() failed: %s\n", strerror(errno));
00300 }
00301
00302 close(sockfd);
00303 exit(1);
00304 }
00305
00306
00307 flags = fcntl(sockfd, F_GETFL, 0);
00308 if (flags < 0) {
00309 ods_log_error("[%s] unable to start interface, fcntl(F_GETFL) "
00310 "failed: %s", cli_str, strerror(errno));
00311 close(sockfd);
00312 return;
00313 }
00314 flags |= O_NONBLOCK;
00315 if (fcntl(sockfd, F_SETFL, flags) < 0) {
00316 ods_log_error("[%s] unable to start interface, fcntl(F_SETFL) "
00317 "failed: %s", cli_str, strerror(errno));
00318 close(sockfd);
00319 return;
00320 }
00321
00322
00323 flags = fcntl(fileno(stdin), F_GETFL, 0);
00324 if (flags < 0) {
00325 ods_log_error("[%s] unable to start interface, fcntl(F_GETFL) "
00326 "failed: %s", cli_str, strerror(errno));
00327 close(sockfd);
00328 return;
00329 }
00330 flags |= O_NONBLOCK;
00331 if (fcntl(fileno(stdin), F_SETFL, flags) < 0) {
00332 ods_log_error("[%s] unable to start interface, fcntl(F_SETFL) "
00333 "failed: %s", cli_str, strerror(errno));
00334 close(sockfd);
00335 return;
00336 }
00337
00338
00339 if (!cmd) {
00340 fprintf(stderr, "cmd> ");
00341 }
00342
00343
00344 ods_log_init(NULL, 0, 0);
00345 interface_run(stdin, sockfd, cmd);
00346 close(sockfd);
00347 return;
00348 }
00349
00350
00355 int
00356 main(int argc, char* argv[])
00357 {
00358 int c;
00359 int options_size = 0;
00360 const char* options[4];
00361 char* cmd = NULL;
00362 allocator_type* clialloc = allocator_create(malloc, free);
00363 if (!clialloc) {
00364 fprintf(stderr,"error, malloc failed for client\n");
00365 exit(1);
00366 }
00367
00368 if (argc > 3) {
00369 fprintf(stderr,"error, too many arguments\n");
00370 exit(1);
00371 }
00372
00373
00374 for (c = 0; c < argc; c++) {
00375 options[c] = argv[c];
00376 if (c > 0) {
00377 options_size += strlen(argv[c]) + 1;
00378 }
00379 }
00380 if (argc > 1) {
00381 cmd = (char*) allocator_alloc(clialloc, (options_size+2)*sizeof(char));
00382 if (!cmd) {
00383 fprintf(stderr, "memory allocation failed\n");
00384 exit(1);
00385 }
00386 (void)strncpy(cmd, "", 1);
00387 for (c = 1; c < argc; c++) {
00388 (void)strncat(cmd, options[c], strlen(options[c]));
00389 (void)strncat(cmd, " ", 1);
00390 }
00391 cmd[options_size-1] = '\n';
00392 }
00393
00394
00395 if (cmd && ods_strcmp(cmd, "-h\n") == 0) {
00396 usage(stdout);
00397 } else if (cmd && ods_strcmp(cmd, "--help\n") == 0) {
00398 usage(stdout);
00399 } else {
00400 interface_start(cmd);
00401 }
00402
00403
00404 allocator_deallocate(clialloc, (void*) cmd);
00405 allocator_cleanup(clialloc);
00406 return 0;
00407 }