diff options
author | Daiki Ueno <dueno@redhat.com> | 2017-10-06 10:58:50 +0200 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2017-10-06 16:56:58 +0200 |
commit | 96a3d3e6371785f846bc72c2a701a1eb67c89b77 (patch) | |
tree | 3697ec61b8ec9fc8aa17da4f248ef7417887f634 /p11-kit | |
parent | 031912fa844c4f3da327c8b2578d9d9ce2a6473e (diff) |
server: Better shell integration
This adds -k, -c, and -s options to the "p11-kit server" command,
which allows you to terminate the server process, select which C-shell
or Bourne shell command line is printed on startup, respectively.
Diffstat (limited to 'p11-kit')
-rw-r--r-- | p11-kit/Makefile.am | 5 | ||||
-rw-r--r-- | p11-kit/server.c | 122 | ||||
-rwxr-xr-x | p11-kit/test-server.sh | 39 |
3 files changed, 147 insertions, 19 deletions
diff --git a/p11-kit/Makefile.am b/p11-kit/Makefile.am index f2571d2..955719a 100644 --- a/p11-kit/Makefile.am +++ b/p11-kit/Makefile.am @@ -208,6 +208,10 @@ check_PROGRAMS += \ test-rpc \ $(NULL) +if !OS_WIN32 +check_SCRIPTS += p11-kit/test-server.sh +endif + test_conf_SOURCES = p11-kit/test-conf.c test_conf_LDADD = $(p11_kit_LIBS) @@ -306,4 +310,5 @@ mock_five_la_LIBADD = $(mock_one_la_LIBADD) EXTRA_DIST += \ p11-kit/fixtures \ p11-kit/test-mock.c \ + $(check_SCRIPTS) \ $(NULL) diff --git a/p11-kit/server.c b/p11-kit/server.c index 96c77ec..b86d424 100644 --- a/p11-kit/server.c +++ b/p11-kit/server.c @@ -45,6 +45,7 @@ #include <assert.h> #include <errno.h> #include <fcntl.h> +#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -161,6 +162,10 @@ static bool need_children_cleanup = false; static bool terminate = false; static unsigned children_avail = 0; static bool quiet = false; +static bool csh = false; + +#define P11_KIT_SERVER_ADDRESS_ENV "P11_KIT_SERVER_ADDRESS" +#define P11_KIT_SERVER_PID_ENV "P11_KIT_SERVER_PID" static SIGHANDLER_T ocsignal (int signum, SIGHANDLER_T handler) @@ -346,28 +351,42 @@ server_loop (Server *server, if (server->socket == -1) return 1; - if (!quiet) { - char *path; - - path = p11_path_encode (server->socket_name); - printf ("P11_KIT_SERVER_ADDRESS=unix:path=%s\n", path); - free (path); - printf ("P11_KIT_SERVER_PID=%d\n", getpid ()); - fflush (stdout); - close (STDOUT_FILENO); - } - /* run as daemon */ if (!foreground) { pid = fork (); - switch (pid) { - case -1: + if (pid == -1) { p11_message_err (errno, "could not fork() to daemonize"); return 1; - case 0: - break; - default: - _exit (0); + } + if (pid == 0) { + close (STDIN_FILENO); + close (STDOUT_FILENO); + } + if (pid != 0) { + char *path, *address; + + path = p11_path_encode (server->socket_name); + rc = asprintf (&address, "unix:path=%s", path); + free (path); + if (rc < 0) + return 1; + if (csh) { + printf ("setenv %s %s;\n", + P11_KIT_SERVER_ADDRESS_ENV, + address); + printf ("setenv %s %d;\n", + P11_KIT_SERVER_PID_ENV, + pid); + } else { + printf ("%s=%s; export %s;\n", + P11_KIT_SERVER_ADDRESS_ENV, address, + P11_KIT_SERVER_ADDRESS_ENV); + printf ("%s=%d; export %s;\n", + P11_KIT_SERVER_PID_ENV, pid, + P11_KIT_SERVER_PID_ENV); + } + free (address); + exit (0); } if (setsid () == -1) { p11_message_err (errno, "could not create a new session"); @@ -487,6 +506,8 @@ main (int argc, const struct passwd *pwd; const struct group *grp; bool foreground = false; + bool csh_opt = false; + bool kill_opt = false; struct timespec *timeout = NULL, ts; char *name = NULL; char *provider = NULL; @@ -504,7 +525,10 @@ main (int argc, opt_foreground = 'f', opt_timeout = 't', opt_name = 'n', - opt_provider = 'p' + opt_provider = 'p', + opt_kill = 'k', + opt_csh = 'c', + opt_sh = 's' }; struct option options[] = { @@ -519,6 +543,9 @@ main (int argc, { "timeout", required_argument, NULL, opt_timeout }, { "name", required_argument, NULL, opt_name }, { "provider", required_argument, NULL, opt_provider }, + { "kill", no_argument, NULL, opt_kill }, + { "csh", no_argument, NULL, opt_csh }, + { "sh", no_argument, NULL, opt_sh }, { 0 }, }; @@ -532,6 +559,9 @@ main (int argc, { opt_timeout, "exit if no connection until the given timeout" }, { opt_name, "specify name of the socket (default: pkcs11-<pid>)" }, { opt_provider, "specify the module to use" }, + { opt_kill, "terminate the running server" }, + { opt_csh, "generate C-shell commands on stdout" }, + { opt_sh, "generate Bourne shell commands on stdout" }, { 0 }, }; @@ -589,6 +619,17 @@ main (int argc, case opt_provider: provider = optarg; break; + case opt_kill: + kill_opt = true; + break; + case opt_csh: + csh = true; + csh_opt = true; + break; + case opt_sh: + csh = false; + csh_opt = true; + break; case opt_help: case '?': p11_tool_usage (usages, options); @@ -602,11 +643,54 @@ main (int argc, argc -= optind; argv += optind; - if (argc < 1) { + if (argc < 1 && !kill_opt) { p11_tool_usage (usages, options); return 2; } + if (!csh_opt) { + const char *shell = secure_getenv ("SHELL"); + size_t len; + if (shell != NULL && (len = strlen (shell)) > 2 && + strncmp (shell + len - 3, "csh", 3) == 0) + csh = true; + } + + if (kill_opt) { + const char *pidstr = secure_getenv (P11_KIT_SERVER_PID_ENV); + char *endptr; + long pidval; + + if (pidstr == NULL) { + fprintf (stderr, "%s not set, cannot kill server", + P11_KIT_SERVER_PID_ENV); + exit (1); + } + pidval = strtol (pidstr, &endptr, 10); + if (errno == ERANGE && + (pidval == LONG_MAX || pidval == LONG_MIN)) { + perror ("strtol"); + exit (1); + } + if (kill ((pid_t) pidval, SIGTERM) == -1) { + perror ("kill"); + exit (1); + } + + if (csh) { + printf ("unsetenv %s;\n", + P11_KIT_SERVER_ADDRESS_ENV); + printf ("unsetenv %s;\n", + P11_KIT_SERVER_PID_ENV); + } else { + printf ("unset %s;\n", + P11_KIT_SERVER_ADDRESS_ENV); + printf ("unset %s;\n", + P11_KIT_SERVER_PID_ENV); + } + exit (0); + } + if (run_as_gid != -1) { if (setgid (run_as_gid) == -1) { p11_message_err (errno, "cannot set gid to %u", (unsigned)run_as_gid); diff --git a/p11-kit/test-server.sh b/p11-kit/test-server.sh new file mode 100755 index 0000000..225127c --- /dev/null +++ b/p11-kit/test-server.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +testdir=$PWD/test-server-$$ +test -d "$testdir" || mkdir "$testdir" + +cleanup () { + rm -rf "$testdir" +} +trap cleanup 0 + +cd "$testdir" + +unset P11_KIT_SERVER_ADDRESS +unset P11_KIT_SERVER_PID + +XDG_RUNTIME_DIR="$testdir" +export XDG_RUNTIME_DIR + +"$abs_top_builddir"/p11-kit-server -s --provider "$abs_top_builddir"/.libs/mock-one.so pkcs11: > start.env 2> start.err +if test $? -ne 0; then + cat start.err + exit 1 +fi + +. ./start.env + +test "${P11_KIT_SERVER_ADDRESS+set}" == set || exit 1 +test "${P11_KIT_SERVER_PID+set}" == set || exit 1 + +"$abs_top_builddir"/p11-kit-server -s -k > stop.env 2> stop.err +if test $? -ne 0; then + cat stop.err + exit 1 +fi + +. ./stop.env + +test "${P11_KIT_SERVER_ADDRESS-unset}" == unset || exit 1 +test "${P11_KIT_SERVER_PID-unset}" == unset || exit 1 |