[svn] GnuPG - r4246 - in trunk: . agent common doc doc/examples scd
svn author wk
cvs at cvs.gnupg.org
Thu Sep 7 17:13:35 CEST 2006
Author: wk
Date: 2006-09-07 17:13:33 +0200 (Thu, 07 Sep 2006)
New Revision: 4246
Added:
trunk/doc/examples/
trunk/doc/examples/scd-event
Modified:
trunk/NEWS
trunk/TODO
trunk/agent/call-scd.c
trunk/common/ChangeLog
trunk/common/exechelp.c
trunk/common/exechelp.h
trunk/doc/ChangeLog
trunk/doc/Makefile.am
trunk/doc/scdaemon.texi
trunk/scd/ChangeLog
trunk/scd/command.c
Log:
Let scdaemon call a script on status changes
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2006-09-07 06:42:55 UTC (rev 4245)
+++ trunk/NEWS 2006-09-07 15:13:33 UTC (rev 4246)
@@ -12,7 +12,9 @@
* API change in gpg-agent's pkdecrypt command. Thus an older gpgsm
may not be used with the current gpg-agent.
+ * The scdaemon will now call a script on reader status changes.
+
Noteworthy changes in version 1.9.22 (2006-07-27)
-------------------------------------------------
Modified: trunk/TODO
===================================================================
--- trunk/TODO 2006-09-07 06:42:55 UTC (rev 4245)
+++ trunk/TODO 2006-09-07 15:13:33 UTC (rev 4246)
@@ -80,10 +80,7 @@
* doc/
** Explain how to setup a root CA key as trusted
** Explain how trustlist.txt might be managed.
-** Write a script to generate man pages from texi.
- In progress (yatm)
-
* Windows port
** gpgsm's LISTKEYS does not yet work
Fix is to change everything to libestream
@@ -91,8 +88,6 @@
This means we can't reread a configuration
** No card status notifications.
-
-
* sm/
** check that we issue NO_SECKEY xxx if a -u key was not found
We don't. The messages retruned are also wrong (recipient vs. signer).
Modified: trunk/agent/call-scd.c
===================================================================
--- trunk/agent/call-scd.c 2006-09-07 06:42:55 UTC (rev 4245)
+++ trunk/agent/call-scd.c 2006-09-07 15:13:33 UTC (rev 4246)
@@ -193,7 +193,7 @@
/* Fork off the SCdaemon if this has not already been done. Lock the
daemon and make sure that a proper context has been setup in CTRL.
- Thsi fucntion might also lock the daemon, which means that the
+ This function might also lock the daemon, which means that the
caller must call unlock_scd after this fucntion has returned
success and the actual Assuan transaction been done. */
static int
Modified: trunk/common/ChangeLog
===================================================================
--- trunk/common/ChangeLog 2006-09-07 06:42:55 UTC (rev 4245)
+++ trunk/common/ChangeLog 2006-09-07 15:13:33 UTC (rev 4246)
@@ -1,3 +1,10 @@
+2006-09-07 Werner Koch <wk at g10code.com>
+
+ * exechelp.c (gnupg_spawn_process): Factor out post fork code to ..
+ (do_exec): .. new function. Allow passing of -1 for the fds.
+ (gnupg_spawn_process): Terminate gcrypt's secure memory in the child.
+ (gnupg_spawn_process_detached): New.
+
2006-09-06 Werner Koch <wk at g10code.com>
* maperror.c: Removed.
Modified: trunk/common/exechelp.c
===================================================================
--- trunk/common/exechelp.c 2006-09-07 06:42:55 UTC (rev 4245)
+++ trunk/common/exechelp.c 2006-09-07 15:13:33 UTC (rev 4246)
@@ -28,6 +28,7 @@
#include <assert.h>
#include <signal.h>
#include <unistd.h>
+#include <fcntl.h>
#ifdef USE_GNU_PTH
#include <pth.h>
#endif
@@ -159,7 +160,68 @@
#endif /*HAVE_W32_SYSTEM*/
+#ifndef HAVE_W32_SYSTEM
+/* The exec core used right after the fork. This will never return. */
+static void
+do_exec (const char *pgmname, const char *argv[],
+ int fd_in, int fd_out, int fd_err,
+ void (*preexec)(void) )
+{
+ char **arg_list;
+ int n, i, j;
+ int fds[3];
+ fds[0] = fd_in;
+ fds[1] = fd_out;
+ fds[2] = fd_err;
+
+ /* Create the command line argument array. */
+ i = 0;
+ if (argv)
+ while (argv[i])
+ i++;
+ arg_list = xcalloc (i+2, sizeof *arg_list);
+ arg_list[0] = strrchr (pgmname, '/');
+ if (arg_list[0])
+ arg_list[0]++;
+ else
+ arg_list[0] = xstrdup (pgmname);
+ if (argv)
+ for (i=0,j=1; argv[i]; i++, j++)
+ arg_list[j] = (char*)argv[i];
+
+ /* Connect the standard files. */
+ for (i=0; i <= 2; i++)
+ {
+ if (fds[i] == -1 )
+ {
+ fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY);
+ if (fds[i] == -1)
+ log_fatal ("failed to open `%s': %s\n",
+ "/dev/null", strerror (errno));
+ }
+ else if (fds[i] != i && dup2 (fds[i], i) == -1)
+ log_fatal ("dup2 std%s failed: %s\n",
+ i==0?"in":i==1?"out":"err", strerror (errno));
+ }
+
+ /* Close all other files. */
+ n = sysconf (_SC_OPEN_MAX);
+ if (n < 0)
+ n = MAX_OPEN_FDS;
+ for (i=3; i < n; i++)
+ close(i);
+ errno = 0;
+
+ if (preexec)
+ preexec ();
+ execv (pgmname, arg_list);
+ /* No way to print anything, as we have closed all streams. */
+ _exit (127);
+}
+#endif /*!HAVE_W32_SYSTEM*/
+
+
/* Fork and exec the PGMNAME, connect the file descriptor of INFILE to
stdin, write the output to OUTFILE, return a new stream in
STATUSFILE for stderr and the pid of the process in PID. The
@@ -325,47 +387,10 @@
if (!*pid)
{
- /* Child. */
- char **arg_list;
- int n, i, j;
-
- /* Create the command line argument array. */
- for (i=0; argv[i]; i++)
- ;
- arg_list = xcalloc (i+2, sizeof *arg_list);
- arg_list[0] = strrchr (pgmname, '/');
- if (arg_list[0])
- arg_list[0]++;
- else
- arg_list[0] = xstrdup (pgmname);
- for (i=0,j=1; argv[i]; i++, j++)
- arg_list[j] = (char*)argv[i];
-
- /* Connect the infile to stdin. */
- if (fd != 0 && dup2 (fd, 0) == -1)
- log_fatal ("dup2 stdin failed: %s\n", strerror (errno));
-
- /* Connect the outfile to stdout. */
- if (fdout != 1 && dup2 (fdout, 1) == -1)
- log_fatal ("dup2 stdout failed: %s\n", strerror (errno));
-
- /* Connect stderr to our pipe. */
- if (rp[1] != 2 && dup2 (rp[1], 2) == -1)
- log_fatal ("dup2 stderr failed: %s\n", strerror (errno));
-
- /* Close all other files. */
- n = sysconf (_SC_OPEN_MAX);
- if (n < 0)
- n = MAX_OPEN_FDS;
- for (i=3; i < n; i++)
- close(i);
- errno = 0;
-
- if (preexec)
- preexec ();
- execv (pgmname, arg_list);
- /* No way to print anything, as we have closed all streams. */
- _exit (127);
+ gcry_control (GCRYCTL_TERM_SECMEM);
+ /* Run child. */
+ do_exec (pgmname, argv, fd, fdout, rp[1], preexec);
+ /*NOTREACHED*/
}
/* Parent. */
@@ -481,3 +506,64 @@
}
+
+/* Spawn a new process and immediatley detach from it. The name of
+ the program to exec is PGMNAME and its arguments are in ARGV (the
+ programname is automatically passed as first argument).
+ Environment strings in ENVP are set. An error is returned if
+ pgmname is not executable; to make this work it is necessary to
+ provide an absolute file name. All standard file descriptors are
+ connected to /dev/null. */
+gpg_error_t
+gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
+ const char *envp[] )
+{
+#ifdef HAVE_W32_SYSTEM
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+#else
+ pid_t pid;
+ int i;
+
+ if (getuid() != geteuid())
+ return gpg_error (GPG_ERR_BUG);
+
+ if (access (pgmname, X_OK))
+ return gpg_error_from_errno (errno);
+
+#ifdef USE_GNU_PTH
+ pid = pth_fork? pth_fork () : fork ();
+#else
+ pid = fork ();
+#endif
+ if (pid == (pid_t)(-1))
+ {
+ log_error (_("error forking process: %s\n"), strerror (errno));
+ return gpg_error_from_errno (errno);
+ }
+ if (!pid)
+ {
+ gcry_control (GCRYCTL_TERM_SECMEM);
+ if (setsid() == -1 || chdir ("/"))
+ _exit (1);
+ pid = fork (); /* Double fork to let init takes over the new child. */
+ if (pid == (pid_t)(-1))
+ _exit (1);
+ if (pid)
+ _exit (0); /* Let the parent exit immediately. */
+
+ if (envp)
+ for (i=0; envp[i]; i++)
+ putenv (xstrdup (envp[i]));
+
+ do_exec (pgmname, argv, -1, -1, -1, NULL);
+
+ /*NOTREACHED*/
+ }
+
+ if (waitpid (pid, NULL, 0) == -1)
+ log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
+ strerror (errno));
+
+ return 0;
+#endif /* !HAVE_W32_SYSTEM*/
+}
Modified: trunk/common/exechelp.h
===================================================================
--- trunk/common/exechelp.h 2006-09-07 06:42:55 UTC (rev 4245)
+++ trunk/common/exechelp.h 2006-09-07 15:13:33 UTC (rev 4246)
@@ -43,4 +43,16 @@
gpg_error_t gnupg_wait_process (const char *pgmname, pid_t pid);
+/* Spawn a new process and immediatley detach from it. The name of
+ the program to exec is PGMNAME and its arguments are in ARGV (the
+ programname is automatically passed as first argument).
+ Environment strings in ENVP are set. An error is returned if
+ pgmname is not executable; to make this work it is necessary to
+ provide an absolute file name. */
+gpg_error_t gnupg_spawn_process_detached (const char *pgmname,
+ const char *argv[],
+ const char *envp[] );
+
+
+
#endif /*GNUPG_COMMON_EXECHELP_H*/
Modified: trunk/doc/ChangeLog
===================================================================
--- trunk/doc/ChangeLog 2006-09-07 06:42:55 UTC (rev 4245)
+++ trunk/doc/ChangeLog 2006-09-07 15:13:33 UTC (rev 4246)
@@ -1,3 +1,10 @@
+2006-09-07 Werner Koch <wk at g10code.com>
+
+ * scdaemon.texi (Scdaemon Configuration): New.
+
+ * examples/scd-event: Event handler for sdaemon.
+ * examples/: New directory
+
2006-08-22 Werner Koch <wk at g10code.com>
* yat2m.c (parse_file): Added code to skip a line after @mansect.
Modified: trunk/doc/Makefile.am
===================================================================
--- trunk/doc/Makefile.am 2006-09-07 06:42:55 UTC (rev 4245)
+++ trunk/doc/Makefile.am 2006-09-07 15:13:33 UTC (rev 4246)
@@ -19,13 +19,16 @@
## Process this file with automake to produce Makefile.in
+examples=examples/scd-event
+
EXTRA_DIST = DETAILS HACKING TRANSLATE OpenPGP KEYSERVER samplekeys.asc \
gnupg-badge-openpgp.eps gnupg-badge-openpgp.jpg \
gnupg-badge-openpgp.pdf \
gnupg-card-architecture.eps gnupg-card-architecture.png \
gnupg-card-architecture.pdf \
faq.raw FAQ faq.html gnupg7.texi \
- opt-homedir.texi see-also-note.texi
+ opt-homedir.texi see-also-note.texi \
+ $(examples)
BUILT_SOURCES = gnupg-card-architecture.eps gnupg-card-architecture.png \
gnupg-card-architecture.pdf FAQ faq.html
Added: trunk/doc/examples/scd-event
===================================================================
--- trunk/doc/examples/scd-event 2006-09-07 06:42:55 UTC (rev 4245)
+++ trunk/doc/examples/scd-event 2006-09-07 15:13:33 UTC (rev 4246)
@@ -0,0 +1,102 @@
+#!/bin/sh
+# Sample script for scdaemon event mechanism.
+
+#exec >>/tmp/scd-event.log
+
+PGM=scd-event
+
+reader_port=
+old_code=0x0000
+new_code=0x0000
+status=
+
+tick='`'
+prev=
+while [ $# -gt 0 ]; do
+ arg="$1"
+ case $arg in
+ -*=*) optarg=$(echo "X$arg" | sed -e '1s/^X//' -e 's/[-_a-zA-Z0-9]*=//')
+ ;;
+ *) optarg=
+ ;;
+ esac
+ if [ -n "$prev" ]; then
+ eval "$prev=\$arg"
+ prev=
+ shift
+ continue
+ fi
+ case $arg in
+ --help|-h)
+ cat <<EOF
+Usage: $PGM [options]
+$PGM is called by scdaemon on card reader status changes
+
+Options:
+ --reader-port N Reports change for port N
+ --old-code 0xNNNN Previous status code
+ --old-code 0xNNNN Current status code
+ --status USABLE|ACTIVE|PRESENT}NOCARD
+ Human readable status code
+
+Environment:
+
+GNUPGHOME=DIR Set to the active hmedir
+
+EOF
+ exit 0
+ ;;
+
+ --reader-port)
+ prev=reader_port
+ ;;
+ --reader-port=*)
+ reader_port="$optarg"
+ ;;
+ --old-code)
+ prev=old_code
+ ;;
+ --old-code=*)
+ old_code="$optarg"
+ ;;
+ --new-code)
+ prev=new_code
+ ;;
+ --new-code=*)
+ new_code="$optarg"
+ ;;
+ --status)
+ prev=status
+ ;;
+ --new-code=*)
+ status="$optarg"
+ ;;
+
+ -*)
+ echo "$PGM: invalid option $tick$arg'" >&2
+ exit 1
+ ;;
+
+ *)
+ break
+ ;;
+ esac
+ shift
+done
+if [ -n "$prev" ]; then
+ echo "$PGM: argument missing for option $tick$prev'" >&2
+ exit 1
+fi
+
+cat <<EOF
+========================
+port: $reader_port
+old-code: $old_code
+new-code: $new_code
+status: $status
+EOF
+
+if [ x$status = xUSABLE ]; then
+ gpg --batch --card-status 2>&1
+fi
+
Property changes on: trunk/doc/examples/scd-event
___________________________________________________________________
Name: svn:executable
+ *
Modified: trunk/doc/scdaemon.texi
===================================================================
--- trunk/doc/scdaemon.texi 2006-09-07 06:42:55 UTC (rev 4245)
+++ trunk/doc/scdaemon.texi 2006-09-07 15:13:33 UTC (rev 4246)
@@ -48,6 +48,7 @@
* Scdaemon Commands:: List of all commands.
* Scdaemon Options:: List of all options.
* Card applications:: Description of card applications.
+* Scdaemon Configuration:: Configuration files.
* Scdaemon Examples:: Some usage examples.
* Scdaemon Protocol:: The protocol the daemon uses.
@end menu
@@ -320,7 +321,42 @@
@command{gpgsm}.
+ at c *******************************************
+ at c *************** ****************
+ at c *************** FILES ****************
+ at c *************** ****************
+ at c *******************************************
+ at mansect files
+ at node Scdaemon Configuration
+ at section Configuration files
+There are a few configuration files to control certain aspects of
+ at command{scdaemons}'s operation. Unless noted, they are expected in the
+current home directory (@pxref{option --homedir}).
+
+ at table @file
+
+ at item scdaemon.conf
+ at cindex scdaemon.conf
+This is the standard configuration file read by @command{scdaemon} on
+startup. It may contain any valid long option; the leading two dashes
+may not be entered and the option may not be abbreviated. This default
+name may be changed on the command line (@pxref{option --options}).
+
+ at item scd-event
+ at cindex scd-event
+If this file is present and executable, it will be called on veyer card
+reader's status changed. An example of this script is provided with the
+distribution
+
+ at item reader_ at var{n}.status
+This file is created by @command{sdaemon} to let other applications now
+about reader status changes. Its use is now deprecated in favor of
+ at file{scd-event}.
+
+ at end table
+
+
@c
@c Examples
@c
@@ -339,7 +375,7 @@
@c
@c Assuan Protocol
@c
- at mansect assuan
+ at manpause
@node Scdaemon Protocol
@section Scdaemon's Assuan Protocol
@@ -621,3 +657,11 @@
+ at mansect see also
+ at ifset isman
+ at command{gpg-agent}(1),
+ at command{gpgsm}(1),
+ at command{gpg2}(1)
+ at end ifset
+ at include see-also-note.texi
+
Modified: trunk/scd/ChangeLog
===================================================================
--- trunk/scd/ChangeLog 2006-09-07 06:42:55 UTC (rev 4245)
+++ trunk/scd/ChangeLog 2006-09-07 15:13:33 UTC (rev 4246)
@@ -1,3 +1,8 @@
+2006-09-07 Werner Koch <wk at g10code.com>
+
+ * command.c (update_reader_status_file): Execute an event handler
+ if available.
+
2006-09-06 Werner Koch <wk at g10code.com>
* apdu.c (pcsc_end_transaction):
Modified: trunk/scd/command.c
===================================================================
--- trunk/scd/command.c 2006-09-07 06:42:55 UTC (rev 4245)
+++ trunk/scd/command.c 2006-09-07 15:13:33 UTC (rev 4246)
@@ -37,6 +37,7 @@
#include <ksba.h>
#include "app-common.h"
#include "apdu.h" /* Required for apdu_*_reader (). */
+#include "exechelp.h"
/* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */
#define MAXLEN_PIN 100
@@ -1778,6 +1779,47 @@
}
xfree (fname);
+ /* If a status script is executable, run it. */
+ {
+ const char *args[9], *envs[2];
+ char numbuf1[30], numbuf2[3], numbuf3[30];
+ char *homestr, *envstr;
+ gpg_error_t err;
+
+ homestr = make_filename (opt.homedir, NULL);
+ if (asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
+ log_error ("out of core while building environment\n");
+ else
+ {
+ envs[0] = envstr;
+ envs[1] = NULL;
+
+ sprintf (numbuf1, "%d", ss->slot);
+ sprintf (numbuf2, "0x%04X", ss->status);
+ sprintf (numbuf3, "0x%04X", status);
+ args[0] = "--reader-port";
+ args[1] = numbuf1;
+ args[2] = "--old-code";
+ args[3] = numbuf2;
+ args[4] = "--new-code";
+ args[5] = numbuf3;
+ args[6] = "--status";
+ args[7] = ((status & 1)? "USABLE":
+ (status & 4)? "ACTIVE":
+ (status & 2)? "PRESENT": "NOCARD");
+ args[8] = NULL;
+
+ fname = make_filename (opt.homedir, "scd-event", NULL);
+ err = gnupg_spawn_process_detached (fname, args, envs);
+ if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
+ log_error ("failed to run event handler `%s': %s\n",
+ fname, gpg_strerror (err));
+ xfree (fname);
+ free (envstr);
+ }
+ xfree (homestr);
+ }
+
/* Set the card removed flag for all current sessions. We
will set this on any card change because a reset or
SERIALNO request must be done in any case. */
@@ -1802,6 +1844,7 @@
kill (pid, signo);
#endif
}
+
}
}
}
More information about the Gnupg-commits
mailing list