summaryrefslogtreecommitdiff
path: root/p11-kit
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2017-10-06 10:58:50 +0200
committerDaiki Ueno <ueno@gnu.org>2017-10-06 16:56:58 +0200
commit96a3d3e6371785f846bc72c2a701a1eb67c89b77 (patch)
tree3697ec61b8ec9fc8aa17da4f248ef7417887f634 /p11-kit
parent031912fa844c4f3da327c8b2578d9d9ce2a6473e (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.am5
-rw-r--r--p11-kit/server.c122
-rwxr-xr-xp11-kit/test-server.sh39
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