2005-02-24 18:36:11 +01:00
|
|
|
|
/* gpg-connect-agent.c - Tool to connect to the agent.
|
2010-03-29 14:57:11 +02:00
|
|
|
|
* Copyright (C) 2005, 2007, 2008, 2010 Free Software Foundation, Inc.
|
2014-03-14 19:25:58 +01:00
|
|
|
|
* Copyright (C) 2014 Werner Koch
|
2005-02-24 18:36:11 +01:00
|
|
|
|
*
|
|
|
|
|
* This file is part of GnuPG.
|
|
|
|
|
*
|
|
|
|
|
* GnuPG is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
2007-07-04 21:49:40 +02:00
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2005-02-24 18:36:11 +01:00
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* GnuPG is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2016-11-05 12:02:19 +01:00
|
|
|
|
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
2005-02-24 18:36:11 +01:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <errno.h>
|
2005-02-25 17:14:55 +01:00
|
|
|
|
#include <ctype.h>
|
2005-02-24 18:36:11 +01:00
|
|
|
|
#include <assuan.h>
|
2007-10-19 16:51:39 +02:00
|
|
|
|
#include <unistd.h>
|
2007-10-24 17:34:23 +02:00
|
|
|
|
#include <assert.h>
|
2005-02-24 18:36:11 +01:00
|
|
|
|
|
2017-03-07 12:21:23 +01:00
|
|
|
|
#include "../common/i18n.h"
|
2005-02-24 18:36:11 +01:00
|
|
|
|
#include "../common/util.h"
|
|
|
|
|
#include "../common/asshelp.h"
|
2007-10-01 16:48:39 +02:00
|
|
|
|
#include "../common/sysutils.h"
|
2007-10-02 18:30:58 +02:00
|
|
|
|
#include "../common/membuf.h"
|
2007-10-19 16:51:39 +02:00
|
|
|
|
#include "../common/ttyio.h"
|
2008-12-05 13:01:01 +01:00
|
|
|
|
#ifdef HAVE_W32_SYSTEM
|
|
|
|
|
# include "../common/exechelp.h"
|
|
|
|
|
#endif
|
2012-02-06 20:50:47 +01:00
|
|
|
|
#include "../common/init.h"
|
2008-12-05 13:01:01 +01:00
|
|
|
|
|
2007-10-19 16:51:39 +02:00
|
|
|
|
|
|
|
|
|
#define CONTROL_D ('D' - 'A' + 1)
|
|
|
|
|
#define octdigitp(p) (*(p) >= '0' && *(p) <= '7')
|
2005-02-24 18:36:11 +01:00
|
|
|
|
|
|
|
|
|
/* Constants to identify the commands and options. */
|
|
|
|
|
enum cmd_and_opt_values
|
|
|
|
|
{
|
|
|
|
|
aNull = 0,
|
|
|
|
|
oQuiet = 'q',
|
|
|
|
|
oVerbose = 'v',
|
2005-05-18 12:48:06 +02:00
|
|
|
|
oRawSocket = 'S',
|
2010-02-26 11:52:05 +01:00
|
|
|
|
oTcpSocket = 'T',
|
2006-09-13 17:57:30 +02:00
|
|
|
|
oExec = 'E',
|
2007-10-02 23:46:29 +02:00
|
|
|
|
oRun = 'r',
|
2007-10-19 16:51:39 +02:00
|
|
|
|
oSubst = 's',
|
2005-02-24 18:36:11 +01:00
|
|
|
|
|
|
|
|
|
oNoVerbose = 500,
|
2005-02-25 17:14:55 +01:00
|
|
|
|
oHomedir,
|
2010-10-14 18:34:31 +02:00
|
|
|
|
oAgentProgram,
|
2014-03-14 19:25:58 +01:00
|
|
|
|
oDirmngrProgram,
|
2006-09-13 17:57:30 +02:00
|
|
|
|
oHex,
|
2007-04-03 18:57:37 +02:00
|
|
|
|
oDecode,
|
2014-03-14 19:25:58 +01:00
|
|
|
|
oNoExtConnect,
|
2014-11-19 10:31:34 +01:00
|
|
|
|
oDirmngr,
|
2014-11-19 10:34:32 +01:00
|
|
|
|
oUIServer,
|
2014-11-19 10:31:34 +01:00
|
|
|
|
oNoAutostart,
|
2005-02-24 18:36:11 +01:00
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* The list of commands and options. */
|
2008-12-05 13:01:01 +01:00
|
|
|
|
static ARGPARSE_OPTS opts[] = {
|
|
|
|
|
ARGPARSE_group (301, N_("@\nOptions:\n ")),
|
2011-12-14 15:42:28 +01:00
|
|
|
|
|
2008-12-05 13:01:01 +01:00
|
|
|
|
ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
|
|
|
|
|
ARGPARSE_s_n (oQuiet, "quiet", N_("quiet")),
|
|
|
|
|
ARGPARSE_s_n (oHex, "hex", N_("print data out hex encoded")),
|
|
|
|
|
ARGPARSE_s_n (oDecode,"decode", N_("decode received data lines")),
|
2014-03-14 19:25:58 +01:00
|
|
|
|
ARGPARSE_s_n (oDirmngr,"dirmngr", N_("connect to the dirmngr")),
|
2014-11-19 10:34:32 +01:00
|
|
|
|
ARGPARSE_s_n (oUIServer, "uiserver", "@"),
|
2011-12-14 15:42:28 +01:00
|
|
|
|
ARGPARSE_s_s (oRawSocket, "raw-socket",
|
2008-12-05 13:01:01 +01:00
|
|
|
|
N_("|NAME|connect to Assuan socket NAME")),
|
2011-12-14 15:42:28 +01:00
|
|
|
|
ARGPARSE_s_s (oTcpSocket, "tcp-socket",
|
2010-02-26 11:52:05 +01:00
|
|
|
|
N_("|ADDR|connect to Assuan server at ADDR")),
|
2011-12-14 15:42:28 +01:00
|
|
|
|
ARGPARSE_s_n (oExec, "exec",
|
2008-12-05 13:01:01 +01:00
|
|
|
|
N_("run the Assuan server given on the command line")),
|
|
|
|
|
ARGPARSE_s_n (oNoExtConnect, "no-ext-connect",
|
|
|
|
|
N_("do not use extended connect mode")),
|
2011-12-14 15:42:28 +01:00
|
|
|
|
ARGPARSE_s_s (oRun, "run",
|
2008-12-05 13:01:01 +01:00
|
|
|
|
N_("|FILE|run commands from FILE on startup")),
|
2011-12-14 15:42:28 +01:00
|
|
|
|
ARGPARSE_s_n (oSubst, "subst", N_("run /subst on startup")),
|
2008-12-05 13:01:01 +01:00
|
|
|
|
|
2014-11-19 10:31:34 +01:00
|
|
|
|
ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
|
2008-12-05 13:01:01 +01:00
|
|
|
|
ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"),
|
2011-12-14 15:42:28 +01:00
|
|
|
|
ARGPARSE_s_s (oHomedir, "homedir", "@" ),
|
2010-10-14 18:34:31 +02:00
|
|
|
|
ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
|
2014-03-14 19:25:58 +01:00
|
|
|
|
ARGPARSE_s_s (oDirmngrProgram, "dirmngr-program", "@"),
|
2008-12-05 13:01:01 +01:00
|
|
|
|
|
|
|
|
|
ARGPARSE_end ()
|
|
|
|
|
};
|
2005-02-24 18:36:11 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* We keep all global options in the structure OPT. */
|
|
|
|
|
struct
|
|
|
|
|
{
|
|
|
|
|
int verbose; /* Verbosity level. */
|
|
|
|
|
int quiet; /* Be extra quiet. */
|
2014-11-19 10:31:34 +01:00
|
|
|
|
int autostart; /* Start the server if not running. */
|
2005-02-24 18:36:11 +01:00
|
|
|
|
const char *homedir; /* Configuration directory name */
|
2010-10-14 18:34:31 +02:00
|
|
|
|
const char *agent_program; /* Value of --agent-program. */
|
2014-03-14 19:25:58 +01:00
|
|
|
|
const char *dirmngr_program; /* Value of --dirmngr-program. */
|
2005-02-25 17:14:55 +01:00
|
|
|
|
int hex; /* Print data lines in hex format. */
|
2007-04-03 18:57:37 +02:00
|
|
|
|
int decode; /* Decode received data lines. */
|
2014-03-14 19:25:58 +01:00
|
|
|
|
int use_dirmngr; /* Use the dirmngr and not gpg-agent. */
|
2014-11-19 10:34:32 +01:00
|
|
|
|
int use_uiserver; /* Use the standard UI server. */
|
2005-05-18 12:48:06 +02:00
|
|
|
|
const char *raw_socket; /* Name of socket to connect in raw mode. */
|
2010-02-26 11:52:05 +01:00
|
|
|
|
const char *tcp_socket; /* Name of server to connect in tcp mode. */
|
2006-09-13 17:57:30 +02:00
|
|
|
|
int exec; /* Run the pgm given on the command line. */
|
|
|
|
|
unsigned int connect_flags; /* Flags used for connecting. */
|
2007-10-02 18:30:58 +02:00
|
|
|
|
int enable_varsubst; /* Set if variable substitution is enabled. */
|
2007-10-24 17:34:23 +02:00
|
|
|
|
int trim_leading_spaces;
|
2005-02-24 18:36:11 +01:00
|
|
|
|
} opt;
|
|
|
|
|
|
|
|
|
|
|
2005-05-20 22:39:36 +02:00
|
|
|
|
|
|
|
|
|
/* Definitions for /definq commands and a global linked list with all
|
|
|
|
|
the definitions. */
|
|
|
|
|
struct definq_s
|
|
|
|
|
{
|
|
|
|
|
struct definq_s *next;
|
|
|
|
|
char *name; /* Name of inquiry or NULL for any name. */
|
2007-10-19 16:51:39 +02:00
|
|
|
|
int is_var; /* True if FILE is a variable name. */
|
|
|
|
|
int is_prog; /* True if FILE is a program to run. */
|
2005-05-20 22:39:36 +02:00
|
|
|
|
char file[1]; /* Name of file or program. */
|
|
|
|
|
};
|
|
|
|
|
typedef struct definq_s *definq_t;
|
|
|
|
|
|
|
|
|
|
static definq_t definq_list;
|
|
|
|
|
static definq_t *definq_list_tail = &definq_list;
|
|
|
|
|
|
|
|
|
|
|
2007-10-02 18:30:58 +02:00
|
|
|
|
/* Variable definitions and glovbal table. */
|
|
|
|
|
struct variable_s
|
|
|
|
|
{
|
|
|
|
|
struct variable_s *next;
|
|
|
|
|
char *value; /* Malloced value - always a string. */
|
|
|
|
|
char name[1]; /* Name of the variable. */
|
|
|
|
|
};
|
|
|
|
|
typedef struct variable_s *variable_t;
|
|
|
|
|
|
|
|
|
|
static variable_t variable_table;
|
|
|
|
|
|
2007-10-24 17:34:23 +02:00
|
|
|
|
|
|
|
|
|
/* To implement loops we store entire lines in a linked list. */
|
|
|
|
|
struct loopline_s
|
|
|
|
|
{
|
|
|
|
|
struct loopline_s *next;
|
|
|
|
|
char line[1];
|
|
|
|
|
};
|
|
|
|
|
typedef struct loopline_s *loopline_t;
|
|
|
|
|
|
|
|
|
|
|
2007-10-02 18:30:58 +02:00
|
|
|
|
/* This is used to store the pid of the server. */
|
|
|
|
|
static pid_t server_pid = (pid_t)(-1);
|
|
|
|
|
|
2008-10-01 18:17:39 +02:00
|
|
|
|
/* The current datasink file or NULL. */
|
|
|
|
|
static FILE *current_datasink;
|
2007-10-02 18:30:58 +02:00
|
|
|
|
|
|
|
|
|
/* A list of open file descriptors. */
|
|
|
|
|
static struct
|
|
|
|
|
{
|
|
|
|
|
int inuse;
|
|
|
|
|
#ifdef HAVE_W32_SYSTEM
|
|
|
|
|
HANDLE handle;
|
|
|
|
|
#endif
|
|
|
|
|
} open_fd_table[256];
|
|
|
|
|
|
2005-05-20 22:39:36 +02:00
|
|
|
|
|
2005-02-24 18:36:11 +01:00
|
|
|
|
/*-- local prototypes --*/
|
2007-10-19 16:51:39 +02:00
|
|
|
|
static char *substitute_line_copy (const char *buffer);
|
2009-11-04 11:59:11 +01:00
|
|
|
|
static int read_and_print_response (assuan_context_t ctx, int withhash,
|
|
|
|
|
int *r_goterr);
|
2005-02-24 18:36:11 +01:00
|
|
|
|
static assuan_context_t start_agent (void);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-02-20 22:19:50 +01:00
|
|
|
|
/* Print usage information and provide strings for help. */
|
2005-02-24 18:36:11 +01:00
|
|
|
|
static const char *
|
|
|
|
|
my_strusage( int level )
|
|
|
|
|
{
|
|
|
|
|
const char *p;
|
|
|
|
|
|
|
|
|
|
switch (level)
|
|
|
|
|
{
|
2013-11-18 14:09:47 +01:00
|
|
|
|
case 11: p = "@GPG@-connect-agent (@GNUPG@)";
|
2005-02-24 18:36:11 +01:00
|
|
|
|
break;
|
|
|
|
|
case 13: p = VERSION; break;
|
|
|
|
|
case 17: p = PRINTABLE_OS_NAME; break;
|
2009-07-21 16:21:05 +02:00
|
|
|
|
case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
|
|
|
|
|
|
2005-02-24 18:36:11 +01:00
|
|
|
|
case 1:
|
2013-11-18 14:09:47 +01:00
|
|
|
|
case 40: p = _("Usage: @GPG@-connect-agent [options] (-h for help)");
|
2005-02-24 18:36:11 +01:00
|
|
|
|
break;
|
|
|
|
|
case 41:
|
2013-11-18 14:09:47 +01:00
|
|
|
|
p = _("Syntax: @GPG@-connect-agent [options]\n"
|
2005-02-24 18:36:11 +01:00
|
|
|
|
"Connect to a running agent and send commands\n");
|
|
|
|
|
break;
|
|
|
|
|
case 31: p = "\nHome: "; break;
|
2016-06-07 10:59:46 +02:00
|
|
|
|
case 32: p = gnupg_homedir (); break;
|
2005-02-24 18:36:11 +01:00
|
|
|
|
case 33: p = "\n"; break;
|
|
|
|
|
|
|
|
|
|
default: p = NULL; break;
|
|
|
|
|
}
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-11 20:18:24 +02:00
|
|
|
|
|
2009-04-01 12:51:53 +02:00
|
|
|
|
/* Unescape STRING and returned the malloced result. The surrounding
|
2007-10-19 16:51:39 +02:00
|
|
|
|
quotes must already be removed from STRING. */
|
|
|
|
|
static char *
|
|
|
|
|
unescape_string (const char *string)
|
|
|
|
|
{
|
|
|
|
|
const unsigned char *s;
|
|
|
|
|
int esc;
|
|
|
|
|
size_t n;
|
|
|
|
|
char *buffer;
|
|
|
|
|
unsigned char *d;
|
|
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
|
for (s = (const unsigned char*)string, esc=0; *s; s++)
|
|
|
|
|
{
|
|
|
|
|
if (esc)
|
|
|
|
|
{
|
|
|
|
|
switch (*s)
|
|
|
|
|
{
|
2011-12-14 15:42:28 +01:00
|
|
|
|
case 'b':
|
|
|
|
|
case 't':
|
|
|
|
|
case 'v':
|
|
|
|
|
case 'n':
|
|
|
|
|
case 'f':
|
|
|
|
|
case 'r':
|
|
|
|
|
case '"':
|
|
|
|
|
case '\'':
|
2007-10-19 16:51:39 +02:00
|
|
|
|
case '\\': n++; break;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
case 'x':
|
2007-10-19 16:51:39 +02:00
|
|
|
|
if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
|
|
|
|
|
n++;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2011-12-14 15:42:28 +01:00
|
|
|
|
if (s[1] && s[2]
|
2007-10-19 16:51:39 +02:00
|
|
|
|
&& octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
|
|
|
|
|
n++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
esc = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (*s == '\\')
|
|
|
|
|
esc = 1;
|
|
|
|
|
else
|
|
|
|
|
n++;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
}
|
2007-10-19 16:51:39 +02:00
|
|
|
|
|
|
|
|
|
buffer = xmalloc (n+1);
|
|
|
|
|
d = (unsigned char*)buffer;
|
|
|
|
|
for (s = (const unsigned char*)string, esc=0; *s; s++)
|
|
|
|
|
{
|
|
|
|
|
if (esc)
|
|
|
|
|
{
|
|
|
|
|
switch (*s)
|
|
|
|
|
{
|
|
|
|
|
case 'b': *d++ = '\b'; break;
|
|
|
|
|
case 't': *d++ = '\t'; break;
|
|
|
|
|
case 'v': *d++ = '\v'; break;
|
|
|
|
|
case 'n': *d++ = '\n'; break;
|
|
|
|
|
case 'f': *d++ = '\f'; break;
|
|
|
|
|
case 'r': *d++ = '\r'; break;
|
|
|
|
|
case '"': *d++ = '\"'; break;
|
|
|
|
|
case '\'': *d++ = '\''; break;
|
|
|
|
|
case '\\': *d++ = '\\'; break;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
case 'x':
|
2007-10-19 16:51:39 +02:00
|
|
|
|
if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
|
|
|
|
|
{
|
|
|
|
|
s++;
|
|
|
|
|
*d++ = xtoi_2 (s);
|
|
|
|
|
s++;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2011-12-14 15:42:28 +01:00
|
|
|
|
if (s[1] && s[2]
|
2007-10-19 16:51:39 +02:00
|
|
|
|
&& octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
|
|
|
|
|
{
|
|
|
|
|
*d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2);
|
|
|
|
|
s += 2;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
esc = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (*s == '\\')
|
|
|
|
|
esc = 1;
|
|
|
|
|
else
|
|
|
|
|
*d++ = *s;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
}
|
2007-10-19 16:51:39 +02:00
|
|
|
|
*d = 0;
|
|
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Do the percent unescaping and return a newly malloced string.
|
|
|
|
|
If WITH_PLUS is set '+' characters will be changed to space. */
|
|
|
|
|
static char *
|
|
|
|
|
unpercent_string (const char *string, int with_plus)
|
|
|
|
|
{
|
|
|
|
|
const unsigned char *s;
|
|
|
|
|
unsigned char *buffer, *p;
|
|
|
|
|
size_t n;
|
|
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
|
for (s=(const unsigned char *)string; *s; s++)
|
|
|
|
|
{
|
|
|
|
|
if (*s == '%' && s[1] && s[2])
|
2011-12-14 15:42:28 +01:00
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
s++;
|
|
|
|
|
n++;
|
|
|
|
|
s++;
|
|
|
|
|
}
|
|
|
|
|
else if (with_plus && *s == '+')
|
|
|
|
|
n++;
|
|
|
|
|
else
|
|
|
|
|
n++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buffer = xmalloc (n+1);
|
|
|
|
|
p = buffer;
|
|
|
|
|
for (s=(const unsigned char *)string; *s; s++)
|
|
|
|
|
{
|
|
|
|
|
if (*s == '%' && s[1] && s[2])
|
2011-12-14 15:42:28 +01:00
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
s++;
|
|
|
|
|
*p++ = xtoi_2 (s);
|
|
|
|
|
s++;
|
|
|
|
|
}
|
|
|
|
|
else if (with_plus && *s == '+')
|
|
|
|
|
*p++ = ' ';
|
|
|
|
|
else
|
|
|
|
|
*p++ = *s;
|
|
|
|
|
}
|
|
|
|
|
*p = 0;
|
|
|
|
|
return (char*)buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-10-02 18:30:58 +02:00
|
|
|
|
|
2007-10-11 19:35:31 +02:00
|
|
|
|
static const char *
|
2007-10-02 18:30:58 +02:00
|
|
|
|
set_var (const char *name, const char *value)
|
|
|
|
|
{
|
|
|
|
|
variable_t var;
|
|
|
|
|
|
|
|
|
|
for (var = variable_table; var; var = var->next)
|
|
|
|
|
if (!strcmp (var->name, name))
|
|
|
|
|
break;
|
|
|
|
|
if (!var)
|
|
|
|
|
{
|
|
|
|
|
var = xmalloc (sizeof *var + strlen (name));
|
|
|
|
|
var->value = NULL;
|
|
|
|
|
strcpy (var->name, name);
|
|
|
|
|
var->next = variable_table;
|
|
|
|
|
variable_table = var;
|
|
|
|
|
}
|
|
|
|
|
xfree (var->value);
|
|
|
|
|
var->value = value? xstrdup (value) : NULL;
|
2007-10-11 19:35:31 +02:00
|
|
|
|
return var->value;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
}
|
2007-10-02 18:30:58 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
set_int_var (const char *name, int value)
|
|
|
|
|
{
|
|
|
|
|
char numbuf[35];
|
|
|
|
|
|
|
|
|
|
snprintf (numbuf, sizeof numbuf, "%d", value);
|
|
|
|
|
set_var (name, numbuf);
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-11 19:35:31 +02:00
|
|
|
|
|
2007-10-02 18:30:58 +02:00
|
|
|
|
/* Return the value of a variable. That value is valid until a
|
2007-10-11 19:35:31 +02:00
|
|
|
|
variable of the name is changed. Return NULL if not found. Note
|
|
|
|
|
that envvars are copied to our variable list at the first access
|
|
|
|
|
and not at oprogram start. */
|
2007-10-02 18:30:58 +02:00
|
|
|
|
static const char *
|
|
|
|
|
get_var (const char *name)
|
|
|
|
|
{
|
|
|
|
|
variable_t var;
|
2007-10-11 19:35:31 +02:00
|
|
|
|
const char *s;
|
2007-10-02 18:30:58 +02:00
|
|
|
|
|
2007-10-12 18:05:14 +02:00
|
|
|
|
if (!*name)
|
|
|
|
|
return "";
|
2007-10-02 18:30:58 +02:00
|
|
|
|
for (var = variable_table; var; var = var->next)
|
|
|
|
|
if (!strcmp (var->name, name))
|
|
|
|
|
break;
|
2007-10-11 19:35:31 +02:00
|
|
|
|
if (!var && (s = getenv (name)))
|
|
|
|
|
return set_var (name, s);
|
2007-10-02 18:30:58 +02:00
|
|
|
|
if (!var || !var->value)
|
|
|
|
|
return NULL;
|
|
|
|
|
return var->value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
Fix more spelling
* NEWS, acinclude.m4, agent/command-ssh.c, agent/command.c,
agent/gpg-agent.c, agent/keyformat.txt, agent/protect-tool.c,
common/asshelp.c, common/b64enc.c, common/recsel.c, doc/DETAILS,
doc/HACKING, doc/Notes, doc/TRANSLATE, doc/dirmngr.texi,
doc/faq.org, doc/gpg-agent.texi, doc/gpg.texi, doc/gpgsm.texi,
doc/instguide.texi, g10/armor.c, g10/gpg.c, g10/keyedit.c,
g10/mainproc.c, g10/pkclist.c, g10/tofu.c, g13/sh-cmd.c,
g13/sh-dmcrypt.c, kbx/keybox-init.c, m4/pkg.m4, sm/call-dirmngr.c,
sm/gpgsm.c, tests/Makefile.am, tests/gpgscm/Manual.txt,
tests/gpgscm/scheme.c, tests/openpgp/gpgv-forged-keyring.scm,
tests/openpgp/multisig.test, tests/openpgp/verify.scm,
tests/pkits/README, tools/applygnupgdefaults,
tools/gpg-connect-agent.c, tools/mime-maker.c, tools/mime-parser.c:
minor spelling cleanup.
Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
2016-09-15 20:21:15 +02:00
|
|
|
|
/* Perform some simple arithmetic operations. Caller must release
|
2007-10-24 17:34:23 +02:00
|
|
|
|
the return value. On error the return value is NULL. */
|
|
|
|
|
static char *
|
|
|
|
|
arithmetic_op (int operator, const char *operands)
|
|
|
|
|
{
|
|
|
|
|
long result, value;
|
|
|
|
|
char numbuf[35];
|
|
|
|
|
|
|
|
|
|
while ( spacep (operands) )
|
|
|
|
|
operands++;
|
|
|
|
|
if (!*operands)
|
|
|
|
|
return NULL;
|
|
|
|
|
result = strtol (operands, NULL, 0);
|
|
|
|
|
while (*operands && !spacep (operands) )
|
|
|
|
|
operands++;
|
2008-03-05 11:08:10 +01:00
|
|
|
|
if (operator == '!')
|
|
|
|
|
result = !result;
|
|
|
|
|
|
2007-10-24 17:34:23 +02:00
|
|
|
|
while (*operands)
|
|
|
|
|
{
|
|
|
|
|
while ( spacep (operands) )
|
|
|
|
|
operands++;
|
|
|
|
|
if (!*operands)
|
|
|
|
|
break;
|
|
|
|
|
value = strtol (operands, NULL, 0);
|
|
|
|
|
while (*operands && !spacep (operands) )
|
|
|
|
|
operands++;
|
|
|
|
|
switch (operator)
|
|
|
|
|
{
|
|
|
|
|
case '+': result += value; break;
|
|
|
|
|
case '-': result -= value; break;
|
|
|
|
|
case '*': result *= value; break;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
case '/':
|
2007-10-24 17:34:23 +02:00
|
|
|
|
if (!value)
|
|
|
|
|
return NULL;
|
|
|
|
|
result /= value;
|
|
|
|
|
break;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
case '%':
|
2007-10-24 17:34:23 +02:00
|
|
|
|
if (!value)
|
|
|
|
|
return NULL;
|
|
|
|
|
result %= value;
|
|
|
|
|
break;
|
2008-03-05 11:08:10 +01:00
|
|
|
|
case '!': result = !value; break;
|
|
|
|
|
case '|': result = result || value; break;
|
|
|
|
|
case '&': result = result && value; break;
|
2007-10-24 17:34:23 +02:00
|
|
|
|
default:
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("unknown arithmetic operator '%c'\n", operator);
|
2007-10-24 17:34:23 +02:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
snprintf (numbuf, sizeof numbuf, "%ld", result);
|
|
|
|
|
return xstrdup (numbuf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-10-19 16:51:39 +02:00
|
|
|
|
/* Extended version of get_var. This returns a malloced string and
|
2011-12-14 15:42:28 +01:00
|
|
|
|
understand the function syntax: "func args".
|
2007-10-19 16:51:39 +02:00
|
|
|
|
|
|
|
|
|
Defined functions are
|
2011-12-14 15:42:28 +01:00
|
|
|
|
|
2007-10-19 16:51:39 +02:00
|
|
|
|
get - Return a value described by the next argument:
|
|
|
|
|
cwd - The current working directory.
|
|
|
|
|
homedir - The gnupg homedir.
|
|
|
|
|
sysconfdir - GnuPG's system configuration directory.
|
|
|
|
|
bindir - GnuPG's binary directory.
|
|
|
|
|
libdir - GnuPG's library directory.
|
|
|
|
|
libexecdir - GnuPG's library directory for executable files.
|
|
|
|
|
datadir - GnuPG's data directory.
|
|
|
|
|
serverpid - The PID of the current server.
|
|
|
|
|
|
|
|
|
|
unescape ARGS
|
|
|
|
|
Remove C-style escapes from string. Note that "\0" and
|
|
|
|
|
"\x00" terminate the string implictly. Use "\x7d" to
|
|
|
|
|
represent the closing brace. The args start right after
|
|
|
|
|
the first space after the function name.
|
|
|
|
|
|
|
|
|
|
unpercent ARGS
|
|
|
|
|
unpercent+ ARGS
|
2007-10-24 17:34:23 +02:00
|
|
|
|
Remove percent style ecaping from string. Note that "%00
|
2007-10-19 16:51:39 +02:00
|
|
|
|
terminates the string implicitly. Use "%7d" to represetn
|
|
|
|
|
the closing brace. The args start right after the first
|
|
|
|
|
space after the function name. "unpercent+" also maps '+'
|
|
|
|
|
to space.
|
|
|
|
|
|
|
|
|
|
percent ARGS
|
|
|
|
|
percent+ ARGS
|
|
|
|
|
Escape the args using the percent style. Tabs, formfeeds,
|
2015-05-11 19:38:07 +02:00
|
|
|
|
linefeeds, carriage return, and the plus sign are also
|
|
|
|
|
escaped. "percent+" also maps spaces to plus characters.
|
2007-10-19 16:51:39 +02:00
|
|
|
|
|
2008-03-05 11:08:10 +01:00
|
|
|
|
errcode ARG
|
|
|
|
|
Assuming ARG is an integer, return the gpg-error code.
|
|
|
|
|
|
|
|
|
|
errsource ARG
|
|
|
|
|
Assuming ARG is an integer, return the gpg-error source.
|
|
|
|
|
|
|
|
|
|
errstring ARG
|
|
|
|
|
Assuming ARG is an integer return a formatted fpf error string.
|
|
|
|
|
|
|
|
|
|
|
2007-10-19 16:51:39 +02:00
|
|
|
|
Example: get_var_ext ("get sysconfdir") -> "/etc/gnupg"
|
2011-12-14 15:42:28 +01:00
|
|
|
|
|
2007-10-19 16:51:39 +02:00
|
|
|
|
*/
|
|
|
|
|
static char *
|
|
|
|
|
get_var_ext (const char *name)
|
|
|
|
|
{
|
|
|
|
|
static int recursion_count;
|
|
|
|
|
const char *s;
|
|
|
|
|
char *result;
|
|
|
|
|
char *p;
|
|
|
|
|
char *free_me = NULL;
|
2008-03-05 11:08:10 +01:00
|
|
|
|
int intvalue;
|
2007-10-19 16:51:39 +02:00
|
|
|
|
|
|
|
|
|
if (recursion_count > 50)
|
|
|
|
|
{
|
|
|
|
|
log_error ("variables nested too deeply\n");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
recursion_count++;
|
|
|
|
|
free_me = opt.enable_varsubst? substitute_line_copy (name) : NULL;
|
|
|
|
|
if (free_me)
|
|
|
|
|
name = free_me;
|
|
|
|
|
for (s=name; *s && !spacep (s); s++)
|
|
|
|
|
;
|
|
|
|
|
if (!*s)
|
|
|
|
|
{
|
|
|
|
|
s = get_var (name);
|
|
|
|
|
result = s? xstrdup (s): NULL;
|
|
|
|
|
}
|
|
|
|
|
else if ( (s - name) == 3 && !strncmp (name, "get", 3))
|
|
|
|
|
{
|
|
|
|
|
while ( spacep (s) )
|
|
|
|
|
s++;
|
|
|
|
|
if (!strcmp (s, "cwd"))
|
|
|
|
|
{
|
2014-04-15 16:40:48 +02:00
|
|
|
|
result = gnupg_getcwd ();
|
2007-10-19 16:51:39 +02:00
|
|
|
|
if (!result)
|
|
|
|
|
log_error ("getcwd failed: %s\n", strerror (errno));
|
|
|
|
|
}
|
|
|
|
|
else if (!strcmp (s, "homedir"))
|
2016-06-08 10:12:32 +02:00
|
|
|
|
result = xstrdup (gnupg_homedir ());
|
2007-10-19 16:51:39 +02:00
|
|
|
|
else if (!strcmp (s, "sysconfdir"))
|
|
|
|
|
result = xstrdup (gnupg_sysconfdir ());
|
|
|
|
|
else if (!strcmp (s, "bindir"))
|
|
|
|
|
result = xstrdup (gnupg_bindir ());
|
|
|
|
|
else if (!strcmp (s, "libdir"))
|
|
|
|
|
result = xstrdup (gnupg_libdir ());
|
|
|
|
|
else if (!strcmp (s, "libexecdir"))
|
|
|
|
|
result = xstrdup (gnupg_libexecdir ());
|
|
|
|
|
else if (!strcmp (s, "datadir"))
|
|
|
|
|
result = xstrdup (gnupg_datadir ());
|
|
|
|
|
else if (!strcmp (s, "serverpid"))
|
2008-03-05 11:08:10 +01:00
|
|
|
|
result = xasprintf ("%d", (int)server_pid);
|
2007-10-19 16:51:39 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("invalid argument '%s' for variable function 'get'\n", s);
|
2007-10-19 16:51:39 +02:00
|
|
|
|
log_info ("valid are: cwd, "
|
|
|
|
|
"{home,bin,lib,libexec,data}dir, serverpid\n");
|
|
|
|
|
result = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ( (s - name) == 8 && !strncmp (name, "unescape", 8))
|
|
|
|
|
{
|
|
|
|
|
s++;
|
|
|
|
|
result = unescape_string (s);
|
|
|
|
|
}
|
|
|
|
|
else if ( (s - name) == 9 && !strncmp (name, "unpercent", 9))
|
|
|
|
|
{
|
|
|
|
|
s++;
|
|
|
|
|
result = unpercent_string (s, 0);
|
|
|
|
|
}
|
|
|
|
|
else if ( (s - name) == 10 && !strncmp (name, "unpercent+", 10))
|
|
|
|
|
{
|
|
|
|
|
s++;
|
|
|
|
|
result = unpercent_string (s, 1);
|
|
|
|
|
}
|
|
|
|
|
else if ( (s - name) == 7 && !strncmp (name, "percent", 7))
|
|
|
|
|
{
|
|
|
|
|
s++;
|
2015-05-11 19:38:07 +02:00
|
|
|
|
result = percent_escape (s, "+\t\r\n\f\v");
|
2007-10-19 16:51:39 +02:00
|
|
|
|
}
|
|
|
|
|
else if ( (s - name) == 8 && !strncmp (name, "percent+", 8))
|
|
|
|
|
{
|
|
|
|
|
s++;
|
2015-05-11 19:38:07 +02:00
|
|
|
|
result = percent_escape (s, "+\t\r\n\f\v");
|
2007-10-19 16:51:39 +02:00
|
|
|
|
for (p=result; *p; p++)
|
|
|
|
|
if (*p == ' ')
|
|
|
|
|
*p = '+';
|
|
|
|
|
}
|
2008-03-05 11:08:10 +01:00
|
|
|
|
else if ( (s - name) == 7 && !strncmp (name, "errcode", 7))
|
|
|
|
|
{
|
|
|
|
|
s++;
|
|
|
|
|
intvalue = (int)strtol (s, NULL, 0);
|
|
|
|
|
result = xasprintf ("%d", gpg_err_code (intvalue));
|
|
|
|
|
}
|
|
|
|
|
else if ( (s - name) == 9 && !strncmp (name, "errsource", 9))
|
|
|
|
|
{
|
|
|
|
|
s++;
|
|
|
|
|
intvalue = (int)strtol (s, NULL, 0);
|
|
|
|
|
result = xasprintf ("%d", gpg_err_source (intvalue));
|
|
|
|
|
}
|
|
|
|
|
else if ( (s - name) == 9 && !strncmp (name, "errstring", 9))
|
|
|
|
|
{
|
|
|
|
|
s++;
|
|
|
|
|
intvalue = (int)strtol (s, NULL, 0);
|
2011-12-14 15:42:28 +01:00
|
|
|
|
result = xasprintf ("%s <%s>",
|
2008-03-05 11:08:10 +01:00
|
|
|
|
gpg_strerror (intvalue), gpg_strsource (intvalue));
|
|
|
|
|
}
|
|
|
|
|
else if ( (s - name) == 1 && strchr ("+-*/%!|&", *name))
|
2007-10-24 17:34:23 +02:00
|
|
|
|
{
|
|
|
|
|
result = arithmetic_op (*name, s+1);
|
|
|
|
|
}
|
2007-10-19 16:51:39 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("unknown variable function '%.*s'\n", (int)(s-name), name);
|
2007-10-19 16:51:39 +02:00
|
|
|
|
result = NULL;
|
|
|
|
|
}
|
2011-12-14 15:42:28 +01:00
|
|
|
|
|
2007-10-19 16:51:39 +02:00
|
|
|
|
xfree (free_me);
|
|
|
|
|
recursion_count--;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-02 18:30:58 +02:00
|
|
|
|
|
|
|
|
|
/* Substitute variables in LINE and return a new allocated buffer if
|
|
|
|
|
required. The function might modify LINE if the expanded version
|
|
|
|
|
fits into it. */
|
|
|
|
|
static char *
|
|
|
|
|
substitute_line (char *buffer)
|
|
|
|
|
{
|
|
|
|
|
char *line = buffer;
|
|
|
|
|
char *p, *pend;
|
|
|
|
|
const char *value;
|
|
|
|
|
size_t valuelen, n;
|
|
|
|
|
char *result = NULL;
|
2007-10-19 16:51:39 +02:00
|
|
|
|
char *freeme = NULL;
|
2007-10-02 18:30:58 +02:00
|
|
|
|
|
|
|
|
|
while (*line)
|
|
|
|
|
{
|
|
|
|
|
p = strchr (line, '$');
|
|
|
|
|
if (!p)
|
|
|
|
|
return result; /* No more variables. */
|
2011-12-14 15:42:28 +01:00
|
|
|
|
|
2007-10-02 18:30:58 +02:00
|
|
|
|
if (p[1] == '$') /* Escaped dollar sign. */
|
|
|
|
|
{
|
|
|
|
|
memmove (p, p+1, strlen (p+1)+1);
|
|
|
|
|
line = p + 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2007-10-12 18:05:14 +02:00
|
|
|
|
if (p[1] == '{')
|
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
|
|
for (pend=p+2; *pend; pend++)
|
|
|
|
|
{
|
|
|
|
|
if (*pend == '{')
|
|
|
|
|
count++;
|
|
|
|
|
else if (*pend == '}')
|
|
|
|
|
{
|
|
|
|
|
if (--count < 0)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-10-12 18:05:14 +02:00
|
|
|
|
if (!*pend)
|
|
|
|
|
return result; /* Unclosed - don't substitute. */
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (pend=p+1; *pend && !spacep (pend) && *pend != '$' ; pend++)
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
if (p[1] == '{' && *pend == '}')
|
|
|
|
|
{
|
2007-10-24 10:06:16 +02:00
|
|
|
|
int save = *pend;
|
|
|
|
|
*pend = 0;
|
2007-10-19 16:51:39 +02:00
|
|
|
|
freeme = get_var_ext (p+2);
|
|
|
|
|
value = freeme;
|
2007-10-24 10:06:16 +02:00
|
|
|
|
*pend++ = save;
|
2007-10-12 18:05:14 +02:00
|
|
|
|
}
|
|
|
|
|
else if (*pend)
|
2007-10-02 18:30:58 +02:00
|
|
|
|
{
|
|
|
|
|
int save = *pend;
|
|
|
|
|
*pend = 0;
|
|
|
|
|
value = get_var (p+1);
|
|
|
|
|
*pend = save;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
value = get_var (p+1);
|
|
|
|
|
if (!value)
|
|
|
|
|
value = "";
|
|
|
|
|
valuelen = strlen (value);
|
|
|
|
|
if (valuelen <= pend - p)
|
|
|
|
|
{
|
|
|
|
|
memcpy (p, value, valuelen);
|
|
|
|
|
p += valuelen;
|
|
|
|
|
n = pend - p;
|
|
|
|
|
if (n)
|
|
|
|
|
memmove (p, p+n, strlen (p+n)+1);
|
|
|
|
|
line = p;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char *src = result? result : buffer;
|
|
|
|
|
char *dst;
|
|
|
|
|
|
|
|
|
|
dst = xmalloc (strlen (src) + valuelen + 1);
|
|
|
|
|
n = p - src;
|
|
|
|
|
memcpy (dst, src, n);
|
|
|
|
|
memcpy (dst + n, value, valuelen);
|
|
|
|
|
n += valuelen;
|
|
|
|
|
strcpy (dst + n, pend);
|
|
|
|
|
line = dst + n;
|
2007-10-24 10:06:16 +02:00
|
|
|
|
xfree (result);
|
2007-10-02 18:30:58 +02:00
|
|
|
|
result = dst;
|
|
|
|
|
}
|
2007-10-19 16:51:39 +02:00
|
|
|
|
xfree (freeme);
|
|
|
|
|
freeme = NULL;
|
2007-10-02 18:30:58 +02:00
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 16:51:39 +02:00
|
|
|
|
/* Same as substitute_line but do not modify BUFFER. */
|
|
|
|
|
static char *
|
|
|
|
|
substitute_line_copy (const char *buffer)
|
|
|
|
|
{
|
|
|
|
|
char *result, *p;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
|
2007-10-19 16:51:39 +02:00
|
|
|
|
p = xstrdup (buffer?buffer:"");
|
|
|
|
|
result = substitute_line (p);
|
|
|
|
|
if (!result)
|
|
|
|
|
result = p;
|
|
|
|
|
else
|
|
|
|
|
xfree (p);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2007-10-02 18:30:58 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2007-10-11 19:35:31 +02:00
|
|
|
|
assign_variable (char *line, int syslet)
|
2007-10-02 18:30:58 +02:00
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
char *name, *p, *tmp, *free_me, *buffer;
|
2007-10-02 18:30:58 +02:00
|
|
|
|
|
|
|
|
|
/* Get the name. */
|
|
|
|
|
name = line;
|
|
|
|
|
for (p=name; *p && !spacep (p); p++)
|
|
|
|
|
;
|
|
|
|
|
if (*p)
|
|
|
|
|
*p++ = 0;
|
|
|
|
|
while (spacep (p))
|
|
|
|
|
p++;
|
|
|
|
|
|
|
|
|
|
if (!*p)
|
2011-12-14 15:42:28 +01:00
|
|
|
|
set_var (name, NULL); /* Remove variable. */
|
2007-10-11 19:35:31 +02:00
|
|
|
|
else if (syslet)
|
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
free_me = opt.enable_varsubst? substitute_line_copy (p) : NULL;
|
2007-10-11 20:18:24 +02:00
|
|
|
|
if (free_me)
|
|
|
|
|
p = free_me;
|
2007-10-19 16:51:39 +02:00
|
|
|
|
buffer = xmalloc (4 + strlen (p) + 1);
|
|
|
|
|
strcpy (stpcpy (buffer, "get "), p);
|
|
|
|
|
tmp = get_var_ext (buffer);
|
|
|
|
|
xfree (buffer);
|
|
|
|
|
set_var (name, tmp);
|
|
|
|
|
xfree (tmp);
|
2007-10-11 20:18:24 +02:00
|
|
|
|
xfree (free_me);
|
2007-10-11 19:35:31 +02:00
|
|
|
|
}
|
2011-12-14 15:42:28 +01:00
|
|
|
|
else
|
2007-10-02 18:30:58 +02:00
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
tmp = opt.enable_varsubst? substitute_line_copy (p) : NULL;
|
2007-10-02 18:30:58 +02:00
|
|
|
|
if (tmp)
|
|
|
|
|
{
|
|
|
|
|
set_var (name, tmp);
|
|
|
|
|
xfree (tmp);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
set_var (name, p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
show_variables (void)
|
|
|
|
|
{
|
|
|
|
|
variable_t var;
|
|
|
|
|
|
|
|
|
|
for (var = variable_table; var; var = var->next)
|
|
|
|
|
if (var->value)
|
|
|
|
|
printf ("%-20s %s\n", var->name, var->value);
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-24 18:36:11 +01:00
|
|
|
|
|
2005-05-20 22:39:36 +02:00
|
|
|
|
/* Store an inquire response pattern. Note, that this function may
|
|
|
|
|
change the content of LINE. We assume that leading white spaces
|
|
|
|
|
are already removed. */
|
|
|
|
|
static void
|
2007-10-19 16:51:39 +02:00
|
|
|
|
add_definq (char *line, int is_var, int is_prog)
|
2005-05-20 22:39:36 +02:00
|
|
|
|
{
|
|
|
|
|
definq_t d;
|
|
|
|
|
char *name, *p;
|
|
|
|
|
|
|
|
|
|
/* Get name. */
|
|
|
|
|
name = line;
|
|
|
|
|
for (p=name; *p && !spacep (p); p++)
|
|
|
|
|
;
|
|
|
|
|
if (*p)
|
|
|
|
|
*p++ = 0;
|
|
|
|
|
while (spacep (p))
|
|
|
|
|
p++;
|
|
|
|
|
|
|
|
|
|
d = xmalloc (sizeof *d + strlen (p) );
|
|
|
|
|
strcpy (d->file, p);
|
2007-10-19 16:51:39 +02:00
|
|
|
|
d->is_var = is_var;
|
2005-05-20 22:39:36 +02:00
|
|
|
|
d->is_prog = is_prog;
|
|
|
|
|
if ( !strcmp (name, "*"))
|
|
|
|
|
d->name = NULL;
|
|
|
|
|
else
|
|
|
|
|
d->name = xstrdup (name);
|
|
|
|
|
|
|
|
|
|
d->next = NULL;
|
|
|
|
|
*definq_list_tail = d;
|
|
|
|
|
definq_list_tail = &d->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-04-28 03:06:33 +02:00
|
|
|
|
/* Show all inquiry definitions. */
|
2005-05-20 22:39:36 +02:00
|
|
|
|
static void
|
|
|
|
|
show_definq (void)
|
|
|
|
|
{
|
|
|
|
|
definq_t d;
|
|
|
|
|
|
|
|
|
|
for (d=definq_list; d; d = d->next)
|
|
|
|
|
if (d->name)
|
2011-12-14 15:42:28 +01:00
|
|
|
|
printf ("%-20s %c %s\n",
|
2007-10-19 16:51:39 +02:00
|
|
|
|
d->name, d->is_var? 'v' : d->is_prog? 'p':'f', d->file);
|
2005-05-20 22:39:36 +02:00
|
|
|
|
for (d=definq_list; d; d = d->next)
|
|
|
|
|
if (!d->name)
|
2011-12-14 15:42:28 +01:00
|
|
|
|
printf ("%-20s %c %s\n", "*",
|
2007-10-19 16:51:39 +02:00
|
|
|
|
d->is_var? 'v': d->is_prog? 'p':'f', d->file);
|
2005-05-20 22:39:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Clear all inquiry definitions. */
|
|
|
|
|
static void
|
|
|
|
|
clear_definq (void)
|
|
|
|
|
{
|
|
|
|
|
while (definq_list)
|
2011-12-14 15:42:28 +01:00
|
|
|
|
{
|
2005-05-20 22:39:36 +02:00
|
|
|
|
definq_t tmp = definq_list->next;
|
|
|
|
|
xfree (definq_list->name);
|
|
|
|
|
xfree (definq_list);
|
|
|
|
|
definq_list = tmp;
|
|
|
|
|
}
|
|
|
|
|
definq_list_tail = &definq_list;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
}
|
2005-05-20 22:39:36 +02:00
|
|
|
|
|
|
|
|
|
|
2006-09-13 17:57:30 +02:00
|
|
|
|
static void
|
|
|
|
|
do_sendfd (assuan_context_t ctx, char *line)
|
|
|
|
|
{
|
|
|
|
|
FILE *fp;
|
|
|
|
|
char *name, *mode, *p;
|
|
|
|
|
int rc, fd;
|
|
|
|
|
|
|
|
|
|
/* Get file name. */
|
|
|
|
|
name = line;
|
|
|
|
|
for (p=name; *p && !spacep (p); p++)
|
|
|
|
|
;
|
|
|
|
|
if (*p)
|
|
|
|
|
*p++ = 0;
|
|
|
|
|
while (spacep (p))
|
|
|
|
|
p++;
|
|
|
|
|
|
|
|
|
|
/* Get mode. */
|
|
|
|
|
mode = p;
|
|
|
|
|
if (!*mode)
|
|
|
|
|
mode = "r";
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (p=mode; *p && !spacep (p); p++)
|
|
|
|
|
;
|
|
|
|
|
if (*p)
|
|
|
|
|
*p++ = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Open and send. */
|
|
|
|
|
fp = fopen (name, mode);
|
|
|
|
|
if (!fp)
|
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("can't open '%s' in \"%s\" mode: %s\n",
|
2006-09-13 17:57:30 +02:00
|
|
|
|
name, mode, strerror (errno));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
fd = fileno (fp);
|
|
|
|
|
|
|
|
|
|
if (opt.verbose)
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("file '%s' opened in \"%s\" mode, fd=%d\n",
|
2006-09-13 17:57:30 +02:00
|
|
|
|
name, mode, fd);
|
|
|
|
|
|
2007-10-01 16:48:39 +02:00
|
|
|
|
rc = assuan_sendfd (ctx, INT2FD (fd) );
|
2006-09-13 17:57:30 +02:00
|
|
|
|
if (rc)
|
2007-10-02 18:30:58 +02:00
|
|
|
|
log_error ("sending descriptor %d failed: %s\n", fd, gpg_strerror (rc));
|
2006-09-13 17:57:30 +02:00
|
|
|
|
fclose (fp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
do_recvfd (assuan_context_t ctx, char *line)
|
|
|
|
|
{
|
2008-10-20 15:53:23 +02:00
|
|
|
|
(void)ctx;
|
|
|
|
|
(void)line;
|
2006-09-13 17:57:30 +02:00
|
|
|
|
log_info ("This command has not yet been implemented\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-10-02 18:30:58 +02:00
|
|
|
|
static void
|
|
|
|
|
do_open (char *line)
|
|
|
|
|
{
|
|
|
|
|
FILE *fp;
|
|
|
|
|
char *varname, *name, *mode, *p;
|
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_W32_SYSTEM
|
|
|
|
|
if (server_pid == (pid_t)(-1))
|
|
|
|
|
{
|
|
|
|
|
log_error ("the pid of the server is unknown\n");
|
|
|
|
|
log_info ("use command \"/serverpid\" first\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Get variable name. */
|
|
|
|
|
varname = line;
|
|
|
|
|
for (p=varname; *p && !spacep (p); p++)
|
|
|
|
|
;
|
|
|
|
|
if (*p)
|
|
|
|
|
*p++ = 0;
|
|
|
|
|
while (spacep (p))
|
|
|
|
|
p++;
|
|
|
|
|
|
|
|
|
|
/* Get file name. */
|
|
|
|
|
name = p;
|
|
|
|
|
for (p=name; *p && !spacep (p); p++)
|
|
|
|
|
;
|
|
|
|
|
if (*p)
|
|
|
|
|
*p++ = 0;
|
|
|
|
|
while (spacep (p))
|
|
|
|
|
p++;
|
|
|
|
|
|
|
|
|
|
/* Get mode. */
|
|
|
|
|
mode = p;
|
|
|
|
|
if (!*mode)
|
|
|
|
|
mode = "r";
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (p=mode; *p && !spacep (p); p++)
|
|
|
|
|
;
|
|
|
|
|
if (*p)
|
|
|
|
|
*p++ = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Open and send. */
|
|
|
|
|
fp = fopen (name, mode);
|
|
|
|
|
if (!fp)
|
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("can't open '%s' in \"%s\" mode: %s\n",
|
2007-10-02 18:30:58 +02:00
|
|
|
|
name, mode, strerror (errno));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-10-24 20:04:52 +02:00
|
|
|
|
fd = dup (fileno (fp));
|
2007-10-02 18:30:58 +02:00
|
|
|
|
if (fd >= 0 && fd < DIM (open_fd_table))
|
|
|
|
|
{
|
|
|
|
|
open_fd_table[fd].inuse = 1;
|
2010-08-18 21:25:15 +02:00
|
|
|
|
#ifdef HAVE_W32CE_SYSTEM
|
|
|
|
|
# warning fixme: implement our pipe emulation.
|
|
|
|
|
#endif
|
2010-04-14 13:24:02 +02:00
|
|
|
|
#if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
|
2007-10-02 18:30:58 +02:00
|
|
|
|
{
|
|
|
|
|
HANDLE prochandle, handle, newhandle;
|
|
|
|
|
|
|
|
|
|
handle = (void*)_get_osfhandle (fd);
|
2011-12-14 15:42:28 +01:00
|
|
|
|
|
2007-10-02 18:30:58 +02:00
|
|
|
|
prochandle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, server_pid);
|
|
|
|
|
if (!prochandle)
|
|
|
|
|
{
|
|
|
|
|
log_error ("failed to open the server process\n");
|
|
|
|
|
close (fd);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!DuplicateHandle (GetCurrentProcess(), handle,
|
|
|
|
|
prochandle, &newhandle, 0,
|
|
|
|
|
TRUE, DUPLICATE_SAME_ACCESS ))
|
|
|
|
|
{
|
|
|
|
|
log_error ("failed to duplicate the handle\n");
|
|
|
|
|
close (fd);
|
|
|
|
|
CloseHandle (prochandle);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
CloseHandle (prochandle);
|
|
|
|
|
open_fd_table[fd].handle = newhandle;
|
|
|
|
|
}
|
|
|
|
|
if (opt.verbose)
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_info ("file '%s' opened in \"%s\" mode, fd=%d (libc=%d)\n",
|
2007-10-02 18:30:58 +02:00
|
|
|
|
name, mode, (int)open_fd_table[fd].handle, fd);
|
|
|
|
|
set_int_var (varname, (int)open_fd_table[fd].handle);
|
2011-12-14 15:42:28 +01:00
|
|
|
|
#else
|
2007-10-02 18:30:58 +02:00
|
|
|
|
if (opt.verbose)
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_info ("file '%s' opened in \"%s\" mode, fd=%d\n",
|
2007-10-02 18:30:58 +02:00
|
|
|
|
name, mode, fd);
|
|
|
|
|
set_int_var (varname, fd);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
log_error ("can't put fd %d into table\n", fd);
|
2018-10-24 20:04:52 +02:00
|
|
|
|
if (fd != -1)
|
|
|
|
|
close (fd); /* Table was full. */
|
2007-10-02 18:30:58 +02:00
|
|
|
|
}
|
2018-10-24 20:04:52 +02:00
|
|
|
|
fclose (fp);
|
2007-10-02 18:30:58 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
do_close (char *line)
|
|
|
|
|
{
|
|
|
|
|
int fd = atoi (line);
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_W32_SYSTEM
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i=0; i < DIM (open_fd_table); i++)
|
|
|
|
|
if ( open_fd_table[i].inuse && open_fd_table[i].handle == (void*)fd)
|
|
|
|
|
break;
|
|
|
|
|
if (i < DIM (open_fd_table))
|
|
|
|
|
fd = i;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
log_error ("given fd (system handle) has not been opened\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (fd < 0 || fd >= DIM (open_fd_table))
|
|
|
|
|
{
|
|
|
|
|
log_error ("invalid fd\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!open_fd_table[fd].inuse)
|
|
|
|
|
{
|
|
|
|
|
log_error ("given fd has not been opened\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#ifdef HAVE_W32_SYSTEM
|
|
|
|
|
CloseHandle (open_fd_table[fd].handle); /* Close duped handle. */
|
|
|
|
|
#endif
|
|
|
|
|
close (fd);
|
|
|
|
|
open_fd_table[fd].inuse = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
do_showopen (void)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i=0; i < DIM (open_fd_table); i++)
|
|
|
|
|
if (open_fd_table[i].inuse)
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_W32_SYSTEM
|
|
|
|
|
printf ("%-15d (libc=%d)\n", (int)open_fd_table[i].handle, i);
|
|
|
|
|
#else
|
|
|
|
|
printf ("%-15d\n", i);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* configure.ac (NEED_LIBASSUAN_API, NEED_LIBASSUAN_VERSION):
Update to new API (2, 1.1.0).
agent/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* gpg-agent.c (parse_rereadable_options): Don't set global assuan
log file (there ain't one anymore).
(main): Update to new API.
(check_own_socket_pid_cb): Return gpg_error_t instead of int.
(check_own_socket_thread, check_for_running_agent): Create assuan
context before connecting to server.
* command.c: Include "scdaemon.h" before <assuan.h> because of
GPG_ERR_SOURCE_DEFAULT check.
(write_and_clear_outbuf): Use gpg_error_t instead of
assuan_error_t.
(cmd_geteventcounter, cmd_istrusted, cmd_listtrusted)
(cmd_marktrusted, cmd_havekey, cmd_sigkey, cmd_setkeydesc)
(cmd_sethash, cmd_pksign, cmd_pkdecrypt, cmd_genkey, cmd_readkey)
(cmd_keyinfo, cmd_get_passphrase, cmd_clear_passphrase)
(cmd_get_confirmation, cmd_learn, cmd_passwd)
(cmd_preset_passphrase, cmd_scd, cmd_getval, cmd_putval)
(cmd_updatestartuptty, cmd_killagent, cmd_reloadagent)
(cmd_getinfo, option_handler): Return gpg_error_t instead of int.
(post_cmd_notify): Change type of ERR to gpg_error_t from int.
(io_monitor): Add hook argument. Use symbols for constants.
(register_commands): Change return type of HANDLER to gpg_error_t.
(start_command_handler): Allocate assuan context before starting
server.
* call-pinentry.c: Include "scdaemon.h" before <assuan.h> because
of GPG_ERR_SOURCE_DEFAULT check.
(unlock_pinentry): Call assuan_release instead of
assuan_disconnect.
(getinfo_pid_cb, getpin_cb): Return gpg_error_t instead of int.
(start_pinentry): Allocate assuan context before connecting to
server.
* call-scd.c (membuf_data_cb, learn_status_cb, get_serialno_cb)
(membuf_data_cb, inq_needpin, card_getattr_cb, pass_status_thru)
(pass_data_thru): Change return type to gpg_error_t.
(start_scd): Allocate assuan context before connecting to server.
common/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* asshelp.c (start_new_gpg_agent): Allocate assuan context before
starting server.
g10/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* call-agent.c: Include "scdaemon.h" before <assuan.h> because of
GPG_ERR_SOURCE_DEFAULT check.
(learn_status_cb, dummy_data_cb, get_serialno_cb, default_inq_cb)
(learn_status_cb, inq_writecert_parms, inq_writekey_parms)
(scd_genkey_cb, membuf_data_cb): Return gpg_error_t instead of
int.
* gpg.c: Include "scdaemon.h" before <assuan.h> because of
GPG_ERR_SOURCE_DEFAULT check.
(main): Update to new Assuan API.
* server.c: Include "scdaemon.h" before <assuan.h> because of
GPG_ERR_SOURCE_DEFAULT check.
(option_handler, cmd_recipient, cmd_signer, cmd_encrypt)
(cmd_decrypt, cmd_verify, cmd_sign, cmd_import, cmd_export)
(cmd_delkeys, cmd_message, do_listkeys, cmd_listkeys)
(cmd_listsecretkeys, cmd_genkey, cmd_getinfo): Return gpg_error_t
instead of int.
(register_commands): Allocate assuan context before starting
server.
(gpg_server): Allocate assuan_context before starting server.
scd/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* command.c: Include "scdaemon.h" before <assuan.h> because of
GPG_ERR_SOURCE_DEFAULT check.
(option_handler, open_card, cmd_serialno, cmd_lean, cmd_readcert)
(cmd_readkey, cmd_setdata, cmd_pksign, cmd_pkauth, cmd_pkdecrypt)
(cmd_getattr, cmd_setattr, cmd_writecert, cmd_writekey)
(cmd_genkey, cmd_random, cmd_passwd, cmd_checkpin, cmd_lock)
(cmd_unlock, cmd_getinfo, cmd_restart, cmd_disconnect, cmd_apdu)
(cmd_killscd): Return gpg_error_t instead of int.
(scd_command_handler): Allocate assuan context before starting server.
* scdaemon.c (main): Update to new Assuan API.
sm/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* gpgsm.c (main): Update to new assuan API.
* server.c: Include "gpgsm.h" before <assuan.h> due to check for
GPG_ERR_SOURCE_DEFAULT and assuan.h now including gpg-error.h.
(option_handler, cmd_recipient, cmd_signer, cmd_encrypt)
(cmd_decrypt, cmd_verify, cmd_sign, cmd_import, cmd_export)
(cmd_delkeys, cmd_message, cmd_listkeys, cmd_dumpkeys)
(cmd_listsecretkeys, cmd_dumpsecretkeys, cmd_genkey)
(cmd_getauditlog, cmd_getinfo): Return gpg_error_t instead of int.
(register_commands): Same for member HANDLER in table.
(gpgsm_server): Allocate assuan context before starting server.
* sm/call-dirmngr.c:
* call-dirmngr.c (prepare_dirmngr): Check for CTX and error before
setting LDAPSERVER.
(start_dirmngr_ext): Allocate assuan context before starting
server.
(inq_certificate, isvalid_status_cb, lookup_cb, lookup_status_cb)
(run_command_cb, run_command_inq_cb, run_command_status_cb):
Return gpg_error_t instead of int.
tools/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* gpg-connect-agent.c (getinfo_pid_cb, read_and_print_response)
(main): Update to new Assuan API.
2009-09-23 02:01:25 +02:00
|
|
|
|
static gpg_error_t
|
2007-10-11 19:35:31 +02:00
|
|
|
|
getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
|
2007-10-02 18:30:58 +02:00
|
|
|
|
{
|
|
|
|
|
membuf_t *mb = opaque;
|
|
|
|
|
put_membuf (mb, buffer, length);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get the pid of the server and store it locally. */
|
|
|
|
|
static void
|
|
|
|
|
do_serverpid (assuan_context_t ctx)
|
|
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
membuf_t mb;
|
|
|
|
|
char *buffer;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
|
2007-10-02 18:30:58 +02:00
|
|
|
|
init_membuf (&mb, 100);
|
2007-10-11 19:35:31 +02:00
|
|
|
|
rc = assuan_transact (ctx, "GETINFO pid", getinfo_pid_cb, &mb,
|
2007-10-02 18:30:58 +02:00
|
|
|
|
NULL, NULL, NULL, NULL);
|
|
|
|
|
put_membuf (&mb, "", 1);
|
|
|
|
|
buffer = get_membuf (&mb, NULL);
|
|
|
|
|
if (rc || !buffer)
|
2011-12-14 15:42:28 +01:00
|
|
|
|
log_error ("command \"%s\" failed: %s\n",
|
2007-10-02 18:30:58 +02:00
|
|
|
|
"GETINFO pid", gpg_strerror (rc));
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
server_pid = (pid_t)strtoul (buffer, NULL, 10);
|
|
|
|
|
if (opt.verbose)
|
|
|
|
|
log_info ("server's PID is %lu\n", (unsigned long)server_pid);
|
|
|
|
|
}
|
|
|
|
|
xfree (buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-12-14 15:42:28 +01:00
|
|
|
|
/* Return true if the command is either "HELP" or "SCD HELP". */
|
|
|
|
|
static int
|
|
|
|
|
help_cmd_p (const char *line)
|
|
|
|
|
{
|
|
|
|
|
if (!ascii_strncasecmp (line, "SCD", 3)
|
|
|
|
|
&& (spacep (line+3) || !line[3]))
|
|
|
|
|
{
|
|
|
|
|
for (line += 3; spacep (line); line++)
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (!ascii_strncasecmp (line, "HELP", 4)
|
|
|
|
|
&& (spacep (line+4) || !line[4]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-02-24 18:36:11 +01:00
|
|
|
|
/* gpg-connect-agent's entry point. */
|
|
|
|
|
int
|
|
|
|
|
main (int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
ARGPARSE_ARGS pargs;
|
|
|
|
|
int no_more_options = 0;
|
|
|
|
|
assuan_context_t ctx;
|
2005-05-20 22:39:36 +02:00
|
|
|
|
char *line, *p;
|
2007-10-02 18:30:58 +02:00
|
|
|
|
char *tmpline;
|
2005-02-24 18:36:11 +01:00
|
|
|
|
size_t linesize;
|
|
|
|
|
int rc;
|
2007-10-02 23:46:29 +02:00
|
|
|
|
int cmderr;
|
|
|
|
|
const char *opt_run = NULL;
|
2017-01-24 15:36:59 +01:00
|
|
|
|
gpgrt_stream_t script_fp = NULL;
|
2007-10-24 17:34:23 +02:00
|
|
|
|
int use_tty, keep_line;
|
|
|
|
|
struct {
|
|
|
|
|
int collecting;
|
|
|
|
|
loopline_t head;
|
|
|
|
|
loopline_t *tail;
|
|
|
|
|
loopline_t current;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
unsigned int nestlevel;
|
2008-03-05 11:08:10 +01:00
|
|
|
|
int oneshot;
|
2007-10-24 17:34:23 +02:00
|
|
|
|
char *condition;
|
|
|
|
|
} loopstack[20];
|
|
|
|
|
int loopidx;
|
2008-05-26 14:00:55 +02:00
|
|
|
|
char **cmdline_commands = NULL;
|
2005-02-24 18:36:11 +01:00
|
|
|
|
|
2015-01-28 19:57:22 +01:00
|
|
|
|
early_system_init ();
|
2007-10-19 16:51:39 +02:00
|
|
|
|
gnupg_rl_initialize ();
|
2005-02-24 18:36:11 +01:00
|
|
|
|
set_strusage (my_strusage);
|
Call log_set_prefix() with human-readable labels.
* agent/preset-passphrase.c, agent/protect-tool.c, dirmngr/dirmngr.c
* dirmngr/t-http.c, g10/gpg.c, g10/gpgv.c, g13/g13-syshelp.c
* g13/g13.c, kbx/kbxutil.c, scd/scdaemon.c, sm/gpgsm.c
* tests/gpgscm/main.c, tools/gpg-check-pattern.c
* tools/gpg-connect-agent.c, tools/gpgconf.c, tools/gpgtar.c
* tools/symcryptrun.c: Invoke log_set_prefix() with
human-readable labels.
--
Some invocations of log_set_prefix() were done with raw numeric values
instead of values that humans can understand. Use symbolic
representations instead of numeric for better readability.
Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
2016-08-12 07:37:57 +02:00
|
|
|
|
log_set_prefix ("gpg-connect-agent", GPGRT_LOG_WITH_PREFIX);
|
2007-06-14 19:05:07 +02:00
|
|
|
|
|
|
|
|
|
/* Make sure that our subsystems are ready. */
|
2008-12-09 09:58:02 +01:00
|
|
|
|
i18n_init();
|
2010-03-22 13:46:05 +01:00
|
|
|
|
init_common_subsystems (&argc, &argv);
|
2007-06-14 19:05:07 +02:00
|
|
|
|
|
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* configure.ac (NEED_LIBASSUAN_API, NEED_LIBASSUAN_VERSION):
Update to new API (2, 1.1.0).
agent/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* gpg-agent.c (parse_rereadable_options): Don't set global assuan
log file (there ain't one anymore).
(main): Update to new API.
(check_own_socket_pid_cb): Return gpg_error_t instead of int.
(check_own_socket_thread, check_for_running_agent): Create assuan
context before connecting to server.
* command.c: Include "scdaemon.h" before <assuan.h> because of
GPG_ERR_SOURCE_DEFAULT check.
(write_and_clear_outbuf): Use gpg_error_t instead of
assuan_error_t.
(cmd_geteventcounter, cmd_istrusted, cmd_listtrusted)
(cmd_marktrusted, cmd_havekey, cmd_sigkey, cmd_setkeydesc)
(cmd_sethash, cmd_pksign, cmd_pkdecrypt, cmd_genkey, cmd_readkey)
(cmd_keyinfo, cmd_get_passphrase, cmd_clear_passphrase)
(cmd_get_confirmation, cmd_learn, cmd_passwd)
(cmd_preset_passphrase, cmd_scd, cmd_getval, cmd_putval)
(cmd_updatestartuptty, cmd_killagent, cmd_reloadagent)
(cmd_getinfo, option_handler): Return gpg_error_t instead of int.
(post_cmd_notify): Change type of ERR to gpg_error_t from int.
(io_monitor): Add hook argument. Use symbols for constants.
(register_commands): Change return type of HANDLER to gpg_error_t.
(start_command_handler): Allocate assuan context before starting
server.
* call-pinentry.c: Include "scdaemon.h" before <assuan.h> because
of GPG_ERR_SOURCE_DEFAULT check.
(unlock_pinentry): Call assuan_release instead of
assuan_disconnect.
(getinfo_pid_cb, getpin_cb): Return gpg_error_t instead of int.
(start_pinentry): Allocate assuan context before connecting to
server.
* call-scd.c (membuf_data_cb, learn_status_cb, get_serialno_cb)
(membuf_data_cb, inq_needpin, card_getattr_cb, pass_status_thru)
(pass_data_thru): Change return type to gpg_error_t.
(start_scd): Allocate assuan context before connecting to server.
common/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* asshelp.c (start_new_gpg_agent): Allocate assuan context before
starting server.
g10/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* call-agent.c: Include "scdaemon.h" before <assuan.h> because of
GPG_ERR_SOURCE_DEFAULT check.
(learn_status_cb, dummy_data_cb, get_serialno_cb, default_inq_cb)
(learn_status_cb, inq_writecert_parms, inq_writekey_parms)
(scd_genkey_cb, membuf_data_cb): Return gpg_error_t instead of
int.
* gpg.c: Include "scdaemon.h" before <assuan.h> because of
GPG_ERR_SOURCE_DEFAULT check.
(main): Update to new Assuan API.
* server.c: Include "scdaemon.h" before <assuan.h> because of
GPG_ERR_SOURCE_DEFAULT check.
(option_handler, cmd_recipient, cmd_signer, cmd_encrypt)
(cmd_decrypt, cmd_verify, cmd_sign, cmd_import, cmd_export)
(cmd_delkeys, cmd_message, do_listkeys, cmd_listkeys)
(cmd_listsecretkeys, cmd_genkey, cmd_getinfo): Return gpg_error_t
instead of int.
(register_commands): Allocate assuan context before starting
server.
(gpg_server): Allocate assuan_context before starting server.
scd/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* command.c: Include "scdaemon.h" before <assuan.h> because of
GPG_ERR_SOURCE_DEFAULT check.
(option_handler, open_card, cmd_serialno, cmd_lean, cmd_readcert)
(cmd_readkey, cmd_setdata, cmd_pksign, cmd_pkauth, cmd_pkdecrypt)
(cmd_getattr, cmd_setattr, cmd_writecert, cmd_writekey)
(cmd_genkey, cmd_random, cmd_passwd, cmd_checkpin, cmd_lock)
(cmd_unlock, cmd_getinfo, cmd_restart, cmd_disconnect, cmd_apdu)
(cmd_killscd): Return gpg_error_t instead of int.
(scd_command_handler): Allocate assuan context before starting server.
* scdaemon.c (main): Update to new Assuan API.
sm/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* gpgsm.c (main): Update to new assuan API.
* server.c: Include "gpgsm.h" before <assuan.h> due to check for
GPG_ERR_SOURCE_DEFAULT and assuan.h now including gpg-error.h.
(option_handler, cmd_recipient, cmd_signer, cmd_encrypt)
(cmd_decrypt, cmd_verify, cmd_sign, cmd_import, cmd_export)
(cmd_delkeys, cmd_message, cmd_listkeys, cmd_dumpkeys)
(cmd_listsecretkeys, cmd_dumpsecretkeys, cmd_genkey)
(cmd_getauditlog, cmd_getinfo): Return gpg_error_t instead of int.
(register_commands): Same for member HANDLER in table.
(gpgsm_server): Allocate assuan context before starting server.
* sm/call-dirmngr.c:
* call-dirmngr.c (prepare_dirmngr): Check for CTX and error before
setting LDAPSERVER.
(start_dirmngr_ext): Allocate assuan context before starting
server.
(inq_certificate, isvalid_status_cb, lookup_cb, lookup_status_cb)
(run_command_cb, run_command_inq_cb, run_command_status_cb):
Return gpg_error_t instead of int.
tools/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* gpg-connect-agent.c (getinfo_pid_cb, read_and_print_response)
(main): Update to new Assuan API.
2009-09-23 02:01:25 +02:00
|
|
|
|
assuan_set_gpg_err_source (0);
|
2005-02-24 18:36:11 +01:00
|
|
|
|
|
|
|
|
|
|
2014-11-19 10:31:34 +01:00
|
|
|
|
opt.autostart = 1;
|
2009-11-05 13:06:45 +01:00
|
|
|
|
opt.connect_flags = 1;
|
2005-02-24 18:36:11 +01:00
|
|
|
|
|
|
|
|
|
/* Parse the command line. */
|
|
|
|
|
pargs.argc = &argc;
|
|
|
|
|
pargs.argv = &argv;
|
|
|
|
|
pargs.flags = 1; /* Do not remove the args. */
|
|
|
|
|
while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
|
|
|
|
|
{
|
|
|
|
|
switch (pargs.r_opt)
|
|
|
|
|
{
|
|
|
|
|
case oQuiet: opt.quiet = 1; break;
|
|
|
|
|
case oVerbose: opt.verbose++; break;
|
|
|
|
|
case oNoVerbose: opt.verbose = 0; break;
|
2016-06-07 10:59:46 +02:00
|
|
|
|
case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
|
2010-10-14 18:34:31 +02:00
|
|
|
|
case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
|
2014-03-14 19:25:58 +01:00
|
|
|
|
case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break;
|
2014-11-19 10:31:34 +01:00
|
|
|
|
case oNoAutostart: opt.autostart = 0; break;
|
2005-02-25 17:14:55 +01:00
|
|
|
|
case oHex: opt.hex = 1; break;
|
2007-04-03 18:57:37 +02:00
|
|
|
|
case oDecode: opt.decode = 1; break;
|
2014-03-14 19:25:58 +01:00
|
|
|
|
case oDirmngr: opt.use_dirmngr = 1; break;
|
2014-11-19 10:34:32 +01:00
|
|
|
|
case oUIServer: opt.use_uiserver = 1; break;
|
2005-05-18 12:48:06 +02:00
|
|
|
|
case oRawSocket: opt.raw_socket = pargs.r.ret_str; break;
|
2010-02-26 11:52:05 +01:00
|
|
|
|
case oTcpSocket: opt.tcp_socket = pargs.r.ret_str; break;
|
2006-09-13 17:57:30 +02:00
|
|
|
|
case oExec: opt.exec = 1; break;
|
|
|
|
|
case oNoExtConnect: opt.connect_flags &= ~(1); break;
|
2007-10-02 23:46:29 +02:00
|
|
|
|
case oRun: opt_run = pargs.r.ret_str; break;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
case oSubst:
|
2007-10-24 17:34:23 +02:00
|
|
|
|
opt.enable_varsubst = 1;
|
|
|
|
|
opt.trim_leading_spaces = 1;
|
|
|
|
|
break;
|
2005-02-24 18:36:11 +01:00
|
|
|
|
|
|
|
|
|
default: pargs.err = 2; break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (log_get_errorcount (0))
|
|
|
|
|
exit (2);
|
|
|
|
|
|
2014-11-19 10:34:32 +01:00
|
|
|
|
/* --uiserver is a shortcut for a specific raw socket. This comes
|
|
|
|
|
in particular handy on Windows. */
|
|
|
|
|
if (opt.use_uiserver)
|
|
|
|
|
{
|
2016-06-07 10:59:46 +02:00
|
|
|
|
opt.raw_socket = make_absfilename (gnupg_homedir (), "S.uiserver", NULL);
|
2014-11-19 10:34:32 +01:00
|
|
|
|
}
|
2012-03-27 12:35:13 +02:00
|
|
|
|
|
|
|
|
|
/* Print a warning if an argument looks like an option. */
|
|
|
|
|
if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i=0; i < argc; i++)
|
|
|
|
|
if (argv[i][0] == '-' && argv[i][1] == '-')
|
2014-10-10 15:29:42 +02:00
|
|
|
|
log_info (_("Note: '%s' is not considered an option\n"), argv[i]);
|
2012-03-27 12:35:13 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-04-14 16:39:16 +02:00
|
|
|
|
use_tty = (gnupg_isatty (fileno (stdin)) && gnupg_isatty (fileno (stdout)));
|
2007-10-19 16:51:39 +02:00
|
|
|
|
|
2006-09-13 17:57:30 +02:00
|
|
|
|
if (opt.exec)
|
|
|
|
|
{
|
|
|
|
|
if (!argc)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("option \"%s\" requires a program "
|
|
|
|
|
"and optional arguments\n"), "--exec" );
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (argc)
|
2008-05-26 14:00:55 +02:00
|
|
|
|
cmdline_commands = argv;
|
2006-09-13 17:57:30 +02:00
|
|
|
|
|
|
|
|
|
if (opt.exec && opt.raw_socket)
|
2010-02-26 11:52:05 +01:00
|
|
|
|
{
|
|
|
|
|
opt.raw_socket = NULL;
|
|
|
|
|
log_info (_("option \"%s\" ignored due to \"%s\"\n"),
|
|
|
|
|
"--raw-socket", "--exec");
|
|
|
|
|
}
|
|
|
|
|
if (opt.exec && opt.tcp_socket)
|
|
|
|
|
{
|
|
|
|
|
opt.tcp_socket = NULL;
|
|
|
|
|
log_info (_("option \"%s\" ignored due to \"%s\"\n"),
|
|
|
|
|
"--tcp-socket", "--exec");
|
|
|
|
|
}
|
|
|
|
|
if (opt.tcp_socket && opt.raw_socket)
|
|
|
|
|
{
|
|
|
|
|
opt.tcp_socket = NULL;
|
|
|
|
|
log_info (_("option \"%s\" ignored due to \"%s\"\n"),
|
|
|
|
|
"--tcp-socket", "--raw-socket");
|
|
|
|
|
}
|
2006-09-13 17:57:30 +02:00
|
|
|
|
|
2017-01-24 15:36:59 +01:00
|
|
|
|
if (opt_run && !(script_fp = gpgrt_fopen (opt_run, "r")))
|
2007-10-02 23:46:29 +02:00
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("cannot open run file '%s': %s\n",
|
2007-10-02 23:46:29 +02:00
|
|
|
|
opt_run, strerror (errno));
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-09-13 17:57:30 +02:00
|
|
|
|
if (opt.exec)
|
2005-05-18 12:48:06 +02:00
|
|
|
|
{
|
2010-08-18 21:25:15 +02:00
|
|
|
|
assuan_fd_t no_close[3];
|
2006-09-13 17:57:30 +02:00
|
|
|
|
|
2010-08-18 21:25:15 +02:00
|
|
|
|
no_close[0] = assuan_fd_from_posix_fd (es_fileno (es_stderr));
|
2009-12-08 05:43:15 +01:00
|
|
|
|
no_close[1] = assuan_fd_from_posix_fd (log_get_fd ());
|
2010-08-18 21:25:15 +02:00
|
|
|
|
no_close[2] = ASSUAN_INVALID_FD;
|
2009-10-16 20:29:01 +02:00
|
|
|
|
|
|
|
|
|
rc = assuan_new (&ctx);
|
|
|
|
|
if (rc)
|
|
|
|
|
{
|
|
|
|
|
log_error ("assuan_new failed: %s\n", gpg_strerror (rc));
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-05 13:06:45 +01:00
|
|
|
|
rc = assuan_pipe_connect
|
|
|
|
|
(ctx, *argv, (const char **)argv, no_close, NULL, NULL,
|
|
|
|
|
(opt.connect_flags & 1) ? ASSUAN_PIPE_CONNECT_FDPASSING : 0);
|
2006-09-13 17:57:30 +02:00
|
|
|
|
if (rc)
|
|
|
|
|
{
|
|
|
|
|
log_error ("assuan_pipe_connect_ext failed: %s\n",
|
|
|
|
|
gpg_strerror (rc));
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (opt.verbose)
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_info ("server '%s' started\n", *argv);
|
2006-09-13 17:57:30 +02:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (opt.raw_socket)
|
|
|
|
|
{
|
2009-10-16 20:29:01 +02:00
|
|
|
|
rc = assuan_new (&ctx);
|
|
|
|
|
if (rc)
|
|
|
|
|
{
|
|
|
|
|
log_error ("assuan_new failed: %s\n", gpg_strerror (rc));
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-05 13:06:45 +01:00
|
|
|
|
rc = assuan_socket_connect
|
|
|
|
|
(ctx, opt.raw_socket, 0,
|
|
|
|
|
(opt.connect_flags & 1) ? ASSUAN_SOCKET_CONNECT_FDPASSING : 0);
|
2005-05-18 12:48:06 +02:00
|
|
|
|
if (rc)
|
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("can't connect to socket '%s': %s\n",
|
2006-09-06 18:35:52 +02:00
|
|
|
|
opt.raw_socket, gpg_strerror (rc));
|
2005-05-18 12:48:06 +02:00
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (opt.verbose)
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_info ("connection to socket '%s' established\n", opt.raw_socket);
|
2005-05-18 12:48:06 +02:00
|
|
|
|
}
|
2010-02-26 11:52:05 +01:00
|
|
|
|
else if (opt.tcp_socket)
|
|
|
|
|
{
|
|
|
|
|
char *url;
|
|
|
|
|
|
|
|
|
|
url = xstrconcat ("assuan://", opt.tcp_socket, NULL);
|
|
|
|
|
|
|
|
|
|
rc = assuan_new (&ctx);
|
|
|
|
|
if (rc)
|
|
|
|
|
{
|
|
|
|
|
log_error ("assuan_new failed: %s\n", gpg_strerror (rc));
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc = assuan_socket_connect (ctx, opt.tcp_socket, 0, 0);
|
|
|
|
|
if (rc)
|
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("can't connect to server '%s': %s\n",
|
2010-02-26 11:52:05 +01:00
|
|
|
|
opt.tcp_socket, gpg_strerror (rc));
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (opt.verbose)
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_info ("connection to socket '%s' established\n", url);
|
2010-02-26 11:52:05 +01:00
|
|
|
|
|
|
|
|
|
xfree (url);
|
|
|
|
|
}
|
2005-05-18 12:48:06 +02:00
|
|
|
|
else
|
|
|
|
|
ctx = start_agent ();
|
2007-10-01 16:48:39 +02:00
|
|
|
|
|
|
|
|
|
/* See whether there is a line pending from the server (in case
|
|
|
|
|
assuan did not run the initial handshaking). */
|
|
|
|
|
if (assuan_pending_line (ctx))
|
|
|
|
|
{
|
2009-11-04 11:59:11 +01:00
|
|
|
|
rc = read_and_print_response (ctx, 0, &cmderr);
|
2007-10-01 16:48:39 +02:00
|
|
|
|
if (rc)
|
|
|
|
|
log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-14 15:42:28 +01:00
|
|
|
|
|
2007-10-24 17:34:23 +02:00
|
|
|
|
for (loopidx=0; loopidx < DIM (loopstack); loopidx++)
|
|
|
|
|
loopstack[loopidx].collecting = 0;
|
|
|
|
|
loopidx = -1;
|
2005-02-24 18:36:11 +01:00
|
|
|
|
line = NULL;
|
|
|
|
|
linesize = 0;
|
2007-10-24 17:34:23 +02:00
|
|
|
|
keep_line = 1;
|
2005-02-24 18:36:11 +01:00
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
int n;
|
2007-10-24 17:34:23 +02:00
|
|
|
|
size_t maxlength = 2048;
|
2005-02-24 18:36:11 +01:00
|
|
|
|
|
2007-10-24 17:34:23 +02:00
|
|
|
|
assert (loopidx < (int)DIM (loopstack));
|
|
|
|
|
if (loopidx >= 0 && loopstack[loopidx].current)
|
|
|
|
|
{
|
|
|
|
|
keep_line = 0;
|
|
|
|
|
xfree (line);
|
|
|
|
|
line = xstrdup (loopstack[loopidx].current->line);
|
|
|
|
|
n = strlen (line);
|
|
|
|
|
/* Never go beyond of the final /end. */
|
|
|
|
|
if (loopstack[loopidx].current->next)
|
|
|
|
|
loopstack[loopidx].current = loopstack[loopidx].current->next;
|
|
|
|
|
else if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
|
|
|
|
|
;
|
|
|
|
|
else
|
|
|
|
|
log_fatal ("/end command vanished\n");
|
|
|
|
|
}
|
2008-05-26 14:00:55 +02:00
|
|
|
|
else if (cmdline_commands && *cmdline_commands && !script_fp)
|
|
|
|
|
{
|
|
|
|
|
keep_line = 0;
|
|
|
|
|
xfree (line);
|
|
|
|
|
line = xstrdup (*cmdline_commands);
|
|
|
|
|
cmdline_commands++;
|
|
|
|
|
n = strlen (line);
|
|
|
|
|
if (n >= maxlength)
|
|
|
|
|
maxlength = 0;
|
|
|
|
|
}
|
2007-10-24 17:34:23 +02:00
|
|
|
|
else if (use_tty && !script_fp)
|
2007-10-19 16:51:39 +02:00
|
|
|
|
{
|
2007-10-24 17:34:23 +02:00
|
|
|
|
keep_line = 0;
|
|
|
|
|
xfree (line);
|
2007-10-19 16:51:39 +02:00
|
|
|
|
line = tty_get ("> ");
|
|
|
|
|
n = strlen (line);
|
|
|
|
|
if (n==1 && *line == CONTROL_D)
|
|
|
|
|
n = 0;
|
|
|
|
|
if (n >= maxlength)
|
|
|
|
|
maxlength = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2007-10-24 17:34:23 +02:00
|
|
|
|
if (!keep_line)
|
2007-10-19 16:51:39 +02:00
|
|
|
|
{
|
|
|
|
|
xfree (line);
|
|
|
|
|
line = NULL;
|
|
|
|
|
linesize = 0;
|
2007-10-24 17:34:23 +02:00
|
|
|
|
keep_line = 1;
|
2007-10-19 16:51:39 +02:00
|
|
|
|
}
|
2017-01-24 15:36:59 +01:00
|
|
|
|
n = gpgrt_read_line (script_fp ? script_fp : gpgrt_stdin,
|
|
|
|
|
&line, &linesize, &maxlength);
|
2007-10-19 16:51:39 +02:00
|
|
|
|
}
|
2005-02-24 18:36:11 +01:00
|
|
|
|
if (n < 0)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("error reading input: %s\n"), strerror (errno));
|
2007-10-02 23:46:29 +02:00
|
|
|
|
if (script_fp)
|
|
|
|
|
{
|
2017-01-24 15:36:59 +01:00
|
|
|
|
gpgrt_fclose (script_fp);
|
2007-10-02 23:46:29 +02:00
|
|
|
|
script_fp = NULL;
|
|
|
|
|
log_error ("stopping script execution\n");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2005-02-24 18:36:11 +01:00
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
if (!n)
|
2007-10-02 23:46:29 +02:00
|
|
|
|
{
|
|
|
|
|
/* EOF */
|
|
|
|
|
if (script_fp)
|
|
|
|
|
{
|
2017-01-24 15:36:59 +01:00
|
|
|
|
gpgrt_fclose (script_fp);
|
2007-10-02 23:46:29 +02:00
|
|
|
|
script_fp = NULL;
|
|
|
|
|
if (opt.verbose)
|
|
|
|
|
log_info ("end of script\n");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2011-12-14 15:42:28 +01:00
|
|
|
|
break;
|
2007-10-02 23:46:29 +02:00
|
|
|
|
}
|
2005-02-24 18:36:11 +01:00
|
|
|
|
if (!maxlength)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("line too long - skipped\n"));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (memchr (line, 0, n))
|
|
|
|
|
log_info (_("line shortened due to embedded Nul character\n"));
|
|
|
|
|
if (line[n-1] == '\n')
|
|
|
|
|
line[n-1] = 0;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
|
2007-10-24 17:34:23 +02:00
|
|
|
|
if (opt.trim_leading_spaces)
|
|
|
|
|
{
|
|
|
|
|
const char *s = line;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
|
2007-10-24 17:34:23 +02:00
|
|
|
|
while (spacep (s))
|
|
|
|
|
s++;
|
|
|
|
|
if (s != line)
|
|
|
|
|
{
|
|
|
|
|
for (p=line; *s;)
|
|
|
|
|
*p++ = *s++;
|
|
|
|
|
*p = 0;
|
|
|
|
|
n = p - line;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (loopidx+1 >= 0 && loopstack[loopidx+1].collecting)
|
|
|
|
|
{
|
|
|
|
|
loopline_t ll;
|
|
|
|
|
|
|
|
|
|
ll = xmalloc (sizeof *ll + strlen (line));
|
|
|
|
|
ll->next = NULL;
|
|
|
|
|
strcpy (ll->line, line);
|
|
|
|
|
*loopstack[loopidx+1].tail = ll;
|
|
|
|
|
loopstack[loopidx+1].tail = &ll->next;
|
|
|
|
|
|
|
|
|
|
if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
|
|
|
|
|
loopstack[loopidx+1].nestlevel--;
|
|
|
|
|
else if (!strncmp (line, "/while", 6) && (!line[6]||spacep(line+6)))
|
|
|
|
|
loopstack[loopidx+1].nestlevel++;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
|
2007-10-24 17:34:23 +02:00
|
|
|
|
if (loopstack[loopidx+1].nestlevel)
|
|
|
|
|
continue;
|
|
|
|
|
/* We reached the corresponding /end. */
|
|
|
|
|
loopstack[loopidx+1].collecting = 0;
|
|
|
|
|
loopidx++;
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-20 22:39:36 +02:00
|
|
|
|
if (*line == '/')
|
|
|
|
|
{
|
|
|
|
|
/* Handle control commands. */
|
|
|
|
|
char *cmd = line+1;
|
|
|
|
|
|
|
|
|
|
for (p=cmd; *p && !spacep (p); p++)
|
|
|
|
|
;
|
|
|
|
|
if (*p)
|
|
|
|
|
*p++ = 0;
|
|
|
|
|
while (spacep (p))
|
|
|
|
|
p++;
|
2007-10-02 18:30:58 +02:00
|
|
|
|
if (!strcmp (cmd, "let"))
|
|
|
|
|
{
|
2007-10-11 19:35:31 +02:00
|
|
|
|
assign_variable (p, 0);
|
|
|
|
|
}
|
|
|
|
|
else if (!strcmp (cmd, "slet"))
|
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
/* Deprecated - never used in a released version. */
|
2007-10-11 19:35:31 +02:00
|
|
|
|
assign_variable (p, 1);
|
2007-10-02 18:30:58 +02:00
|
|
|
|
}
|
|
|
|
|
else if (!strcmp (cmd, "showvar"))
|
|
|
|
|
{
|
|
|
|
|
show_variables ();
|
|
|
|
|
}
|
2007-10-19 16:51:39 +02:00
|
|
|
|
else if (!strcmp (cmd, "definq"))
|
|
|
|
|
{
|
|
|
|
|
tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
|
|
|
|
|
if (tmpline)
|
|
|
|
|
{
|
|
|
|
|
add_definq (tmpline, 1, 0);
|
|
|
|
|
xfree (tmpline);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
add_definq (p, 1, 0);
|
|
|
|
|
}
|
2007-10-02 18:30:58 +02:00
|
|
|
|
else if (!strcmp (cmd, "definqfile"))
|
2005-05-20 22:39:36 +02:00
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
|
|
|
|
|
if (tmpline)
|
|
|
|
|
{
|
|
|
|
|
add_definq (tmpline, 0, 0);
|
|
|
|
|
xfree (tmpline);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
add_definq (p, 0, 0);
|
2005-05-20 22:39:36 +02:00
|
|
|
|
}
|
|
|
|
|
else if (!strcmp (cmd, "definqprog"))
|
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
|
|
|
|
|
if (tmpline)
|
|
|
|
|
{
|
|
|
|
|
add_definq (tmpline, 0, 1);
|
|
|
|
|
xfree (tmpline);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
add_definq (p, 0, 1);
|
2005-05-20 22:39:36 +02:00
|
|
|
|
}
|
2008-10-01 18:17:39 +02:00
|
|
|
|
else if (!strcmp (cmd, "datafile"))
|
|
|
|
|
{
|
|
|
|
|
const char *fname;
|
|
|
|
|
|
|
|
|
|
if (current_datasink)
|
|
|
|
|
{
|
|
|
|
|
if (current_datasink != stdout)
|
|
|
|
|
fclose (current_datasink);
|
|
|
|
|
current_datasink = NULL;
|
|
|
|
|
}
|
|
|
|
|
tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
|
|
|
|
|
fname = tmpline? tmpline : p;
|
|
|
|
|
if (fname && !strcmp (fname, "-"))
|
|
|
|
|
current_datasink = stdout;
|
|
|
|
|
else if (fname && *fname)
|
|
|
|
|
{
|
|
|
|
|
current_datasink = fopen (fname, "wb");
|
|
|
|
|
if (!current_datasink)
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("can't open '%s': %s\n",
|
2008-10-01 18:17:39 +02:00
|
|
|
|
fname, strerror (errno));
|
|
|
|
|
}
|
|
|
|
|
xfree (tmpline);
|
|
|
|
|
}
|
2005-05-20 22:39:36 +02:00
|
|
|
|
else if (!strcmp (cmd, "showdef"))
|
|
|
|
|
{
|
|
|
|
|
show_definq ();
|
|
|
|
|
}
|
|
|
|
|
else if (!strcmp (cmd, "cleardef"))
|
|
|
|
|
{
|
|
|
|
|
clear_definq ();
|
|
|
|
|
}
|
|
|
|
|
else if (!strcmp (cmd, "echo"))
|
|
|
|
|
{
|
2007-10-02 18:30:58 +02:00
|
|
|
|
tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
|
|
|
|
|
if (tmpline)
|
|
|
|
|
{
|
|
|
|
|
puts (tmpline);
|
|
|
|
|
xfree (tmpline);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
puts (p);
|
2005-05-20 22:39:36 +02:00
|
|
|
|
}
|
2006-09-13 17:57:30 +02:00
|
|
|
|
else if (!strcmp (cmd, "sendfd"))
|
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
|
|
|
|
|
if (tmpline)
|
|
|
|
|
{
|
|
|
|
|
do_sendfd (ctx, tmpline);
|
|
|
|
|
xfree (tmpline);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
do_sendfd (ctx, p);
|
2006-09-13 17:57:30 +02:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
else if (!strcmp (cmd, "recvfd"))
|
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
|
|
|
|
|
if (tmpline)
|
|
|
|
|
{
|
|
|
|
|
do_recvfd (ctx, tmpline);
|
|
|
|
|
xfree (tmpline);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
do_recvfd (ctx, p);
|
2006-09-13 17:57:30 +02:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2007-10-02 18:30:58 +02:00
|
|
|
|
else if (!strcmp (cmd, "open"))
|
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
|
|
|
|
|
if (tmpline)
|
|
|
|
|
{
|
|
|
|
|
do_open (tmpline);
|
|
|
|
|
xfree (tmpline);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
do_open (p);
|
2007-10-02 18:30:58 +02:00
|
|
|
|
}
|
|
|
|
|
else if (!strcmp (cmd, "close"))
|
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
|
|
|
|
|
if (tmpline)
|
|
|
|
|
{
|
|
|
|
|
do_close (tmpline);
|
|
|
|
|
xfree (tmpline);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
do_close (p);
|
2007-10-02 18:30:58 +02:00
|
|
|
|
}
|
|
|
|
|
else if (!strcmp (cmd, "showopen"))
|
|
|
|
|
{
|
|
|
|
|
do_showopen ();
|
|
|
|
|
}
|
|
|
|
|
else if (!strcmp (cmd, "serverpid"))
|
|
|
|
|
{
|
|
|
|
|
do_serverpid (ctx);
|
|
|
|
|
}
|
2007-04-03 18:57:37 +02:00
|
|
|
|
else if (!strcmp (cmd, "hex"))
|
|
|
|
|
opt.hex = 1;
|
|
|
|
|
else if (!strcmp (cmd, "nohex"))
|
|
|
|
|
opt.hex = 0;
|
|
|
|
|
else if (!strcmp (cmd, "decode"))
|
|
|
|
|
opt.decode = 1;
|
|
|
|
|
else if (!strcmp (cmd, "nodecode"))
|
|
|
|
|
opt.decode = 0;
|
2007-10-02 18:30:58 +02:00
|
|
|
|
else if (!strcmp (cmd, "subst"))
|
2007-10-24 17:34:23 +02:00
|
|
|
|
{
|
|
|
|
|
opt.enable_varsubst = 1;
|
|
|
|
|
opt.trim_leading_spaces = 1;
|
|
|
|
|
}
|
2007-10-02 18:30:58 +02:00
|
|
|
|
else if (!strcmp (cmd, "nosubst"))
|
|
|
|
|
opt.enable_varsubst = 0;
|
2007-10-02 23:46:29 +02:00
|
|
|
|
else if (!strcmp (cmd, "run"))
|
|
|
|
|
{
|
|
|
|
|
char *p2;
|
2007-10-24 17:34:23 +02:00
|
|
|
|
|
2007-10-02 23:46:29 +02:00
|
|
|
|
for (p2=p; *p2 && !spacep (p2); p2++)
|
|
|
|
|
;
|
|
|
|
|
if (*p2)
|
|
|
|
|
*p2++ = 0;
|
|
|
|
|
while (spacep (p2))
|
|
|
|
|
p++;
|
|
|
|
|
if (*p2)
|
|
|
|
|
{
|
|
|
|
|
log_error ("syntax error in run command\n");
|
|
|
|
|
if (script_fp)
|
|
|
|
|
{
|
2017-01-24 15:36:59 +01:00
|
|
|
|
gpgrt_fclose (script_fp);
|
2007-10-02 23:46:29 +02:00
|
|
|
|
script_fp = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (script_fp)
|
|
|
|
|
{
|
|
|
|
|
log_error ("cannot nest run commands - stop\n");
|
2017-01-24 15:36:59 +01:00
|
|
|
|
gpgrt_fclose (script_fp);
|
2007-10-02 23:46:29 +02:00
|
|
|
|
script_fp = NULL;
|
|
|
|
|
}
|
2017-01-24 15:36:59 +01:00
|
|
|
|
else if (!(script_fp = gpgrt_fopen (p, "r")))
|
2007-10-02 23:46:29 +02:00
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("cannot open run file '%s': %s\n",
|
2007-10-02 23:46:29 +02:00
|
|
|
|
p, strerror (errno));
|
|
|
|
|
}
|
|
|
|
|
else if (opt.verbose)
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_info ("running commands from '%s'\n", p);
|
2007-10-02 23:46:29 +02:00
|
|
|
|
}
|
2007-10-24 17:34:23 +02:00
|
|
|
|
else if (!strcmp (cmd, "while"))
|
|
|
|
|
{
|
|
|
|
|
if (loopidx+2 >= (int)DIM(loopstack))
|
|
|
|
|
{
|
2008-03-05 11:08:10 +01:00
|
|
|
|
log_error ("blocks are nested too deep\n");
|
2007-10-24 17:34:23 +02:00
|
|
|
|
/* We should better die or break all loop in this
|
|
|
|
|
case as recovering from this error won't be
|
|
|
|
|
easy. */
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
loopstack[loopidx+1].head = NULL;
|
|
|
|
|
loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
|
|
|
|
|
loopstack[loopidx+1].current = NULL;
|
|
|
|
|
loopstack[loopidx+1].nestlevel = 1;
|
2008-03-05 11:08:10 +01:00
|
|
|
|
loopstack[loopidx+1].oneshot = 0;
|
2007-10-24 17:34:23 +02:00
|
|
|
|
loopstack[loopidx+1].condition = xstrdup (p);
|
|
|
|
|
loopstack[loopidx+1].collecting = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-03-05 11:08:10 +01:00
|
|
|
|
else if (!strcmp (cmd, "if"))
|
|
|
|
|
{
|
|
|
|
|
if (loopidx+2 >= (int)DIM(loopstack))
|
|
|
|
|
{
|
|
|
|
|
log_error ("blocks are nested too deep\n");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Note that we need to evaluate the condition right
|
|
|
|
|
away and not just at the end of the block as we
|
|
|
|
|
do with a WHILE. */
|
|
|
|
|
loopstack[loopidx+1].head = NULL;
|
|
|
|
|
loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
|
|
|
|
|
loopstack[loopidx+1].current = NULL;
|
|
|
|
|
loopstack[loopidx+1].nestlevel = 1;
|
|
|
|
|
loopstack[loopidx+1].oneshot = 1;
|
|
|
|
|
loopstack[loopidx+1].condition = substitute_line_copy (p);
|
|
|
|
|
loopstack[loopidx+1].collecting = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-10-24 17:34:23 +02:00
|
|
|
|
else if (!strcmp (cmd, "end"))
|
|
|
|
|
{
|
|
|
|
|
if (loopidx < 0)
|
|
|
|
|
log_error ("stray /end command encountered - ignored\n");
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char *tmpcond;
|
|
|
|
|
const char *value;
|
|
|
|
|
long condition;
|
|
|
|
|
|
|
|
|
|
/* Evaluate the condition. */
|
|
|
|
|
tmpcond = xstrdup (loopstack[loopidx].condition);
|
2008-03-05 11:08:10 +01:00
|
|
|
|
if (loopstack[loopidx].oneshot)
|
|
|
|
|
{
|
|
|
|
|
xfree (loopstack[loopidx].condition);
|
|
|
|
|
loopstack[loopidx].condition = xstrdup ("0");
|
|
|
|
|
}
|
2007-10-24 17:34:23 +02:00
|
|
|
|
tmpline = substitute_line (tmpcond);
|
|
|
|
|
value = tmpline? tmpline : tmpcond;
|
2012-01-27 15:40:24 +01:00
|
|
|
|
/* "true" or "yes" are commonly used to mean TRUE;
|
|
|
|
|
all other strings will evaluate to FALSE due to
|
|
|
|
|
the strtoul. */
|
|
|
|
|
if (!ascii_strcasecmp (value, "true")
|
|
|
|
|
|| !ascii_strcasecmp (value, "yes"))
|
|
|
|
|
condition = 1;
|
|
|
|
|
else
|
|
|
|
|
condition = strtol (value, NULL, 0);
|
2007-10-24 17:34:23 +02:00
|
|
|
|
xfree (tmpline);
|
|
|
|
|
xfree (tmpcond);
|
|
|
|
|
|
|
|
|
|
if (condition)
|
|
|
|
|
{
|
|
|
|
|
/* Run loop. */
|
|
|
|
|
loopstack[loopidx].current = loopstack[loopidx].head;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Cleanup. */
|
|
|
|
|
while (loopstack[loopidx].head)
|
|
|
|
|
{
|
|
|
|
|
loopline_t tmp = loopstack[loopidx].head->next;
|
|
|
|
|
xfree (loopstack[loopidx].head);
|
|
|
|
|
loopstack[loopidx].head = tmp;
|
|
|
|
|
}
|
|
|
|
|
loopstack[loopidx].tail = NULL;
|
|
|
|
|
loopstack[loopidx].current = NULL;
|
|
|
|
|
loopstack[loopidx].nestlevel = 0;
|
|
|
|
|
loopstack[loopidx].collecting = 0;
|
2008-03-05 11:08:10 +01:00
|
|
|
|
loopstack[loopidx].oneshot = 0;
|
2007-10-24 17:34:23 +02:00
|
|
|
|
xfree (loopstack[loopidx].condition);
|
|
|
|
|
loopstack[loopidx].condition = NULL;
|
|
|
|
|
loopidx--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-10-02 23:46:29 +02:00
|
|
|
|
else if (!strcmp (cmd, "bye"))
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
2007-10-24 17:34:23 +02:00
|
|
|
|
else if (!strcmp (cmd, "sleep"))
|
|
|
|
|
{
|
|
|
|
|
gnupg_sleep (1);
|
|
|
|
|
}
|
2005-05-20 22:39:36 +02:00
|
|
|
|
else if (!strcmp (cmd, "help"))
|
|
|
|
|
{
|
2006-09-13 17:57:30 +02:00
|
|
|
|
puts (
|
|
|
|
|
"Available commands:\n"
|
|
|
|
|
"/echo ARGS Echo ARGS.\n"
|
2007-10-02 18:30:58 +02:00
|
|
|
|
"/let NAME VALUE Set variable NAME to VALUE.\n"
|
|
|
|
|
"/showvar Show all variables.\n"
|
2007-10-19 16:51:39 +02:00
|
|
|
|
"/definq NAME VAR Use content of VAR for inquiries with NAME.\n"
|
|
|
|
|
"/definqfile NAME FILE Use content of FILE for inquiries with NAME.\n"
|
|
|
|
|
"/definqprog NAME PGM Run PGM for inquiries with NAME.\n"
|
2008-10-01 18:17:39 +02:00
|
|
|
|
"/datafile [NAME] Write all D line content to file NAME.\n"
|
2006-09-13 17:57:30 +02:00
|
|
|
|
"/showdef Print all definitions.\n"
|
|
|
|
|
"/cleardef Delete all definitions.\n"
|
2007-01-25 09:30:47 +01:00
|
|
|
|
"/sendfd FILE MODE Open FILE and pass descriptor to server.\n"
|
2007-10-02 18:30:58 +02:00
|
|
|
|
"/recvfd Receive FD from server and print.\n"
|
2011-12-14 15:42:28 +01:00
|
|
|
|
"/open VAR FILE MODE Open FILE and assign the file descriptor to VAR.\n"
|
2007-10-02 18:30:58 +02:00
|
|
|
|
"/close FD Close file with descriptor FD.\n"
|
|
|
|
|
"/showopen Show descriptors of all open files.\n"
|
|
|
|
|
"/serverpid Retrieve the pid of the server.\n"
|
2007-04-03 18:57:37 +02:00
|
|
|
|
"/[no]hex Enable hex dumping of received data lines.\n"
|
|
|
|
|
"/[no]decode Enable decoding of received data lines.\n"
|
2008-10-01 18:17:39 +02:00
|
|
|
|
"/[no]subst Enable variable substitution.\n"
|
2007-10-02 23:46:29 +02:00
|
|
|
|
"/run FILE Run commands from FILE.\n"
|
2008-03-05 11:08:10 +01:00
|
|
|
|
"/if VAR Begin conditional block controlled by VAR.\n"
|
2007-10-24 17:34:23 +02:00
|
|
|
|
"/while VAR Begin loop controlled by VAR.\n"
|
2008-03-05 11:08:10 +01:00
|
|
|
|
"/end End loop or condition\n"
|
2007-10-02 23:46:29 +02:00
|
|
|
|
"/bye Terminate gpg-connect-agent.\n"
|
2007-04-03 18:57:37 +02:00
|
|
|
|
"/help Print this help.");
|
2005-05-20 22:39:36 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error (_("unknown command '%s'\n"), cmd );
|
2011-12-14 15:42:28 +01:00
|
|
|
|
|
2005-05-20 22:39:36 +02:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2007-10-02 18:30:58 +02:00
|
|
|
|
|
2007-10-02 23:46:29 +02:00
|
|
|
|
if (opt.verbose && script_fp)
|
|
|
|
|
puts (line);
|
|
|
|
|
|
2007-10-02 18:30:58 +02:00
|
|
|
|
tmpline = opt.enable_varsubst? substitute_line (line) : NULL;
|
|
|
|
|
if (tmpline)
|
|
|
|
|
{
|
|
|
|
|
rc = assuan_write_line (ctx, tmpline);
|
|
|
|
|
xfree (tmpline);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
rc = assuan_write_line (ctx, line);
|
2005-02-24 18:36:11 +01:00
|
|
|
|
if (rc)
|
|
|
|
|
{
|
2006-09-06 18:35:52 +02:00
|
|
|
|
log_info (_("sending line failed: %s\n"), gpg_strerror (rc) );
|
2007-07-16 16:33:34 +02:00
|
|
|
|
break;
|
2005-02-24 18:36:11 +01:00
|
|
|
|
}
|
|
|
|
|
if (*line == '#' || !*line)
|
2006-09-13 17:57:30 +02:00
|
|
|
|
continue; /* Don't expect a response for a comment line. */
|
2005-02-24 18:36:11 +01:00
|
|
|
|
|
2011-12-14 15:42:28 +01:00
|
|
|
|
rc = read_and_print_response (ctx, help_cmd_p (line), &cmderr);
|
2005-02-24 18:36:11 +01:00
|
|
|
|
if (rc)
|
2006-09-06 18:35:52 +02:00
|
|
|
|
log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
|
2007-10-02 23:46:29 +02:00
|
|
|
|
if ((rc || cmderr) && script_fp)
|
|
|
|
|
{
|
|
|
|
|
log_error ("stopping script execution\n");
|
2017-01-24 15:36:59 +01:00
|
|
|
|
gpgrt_fclose (script_fp);
|
2007-10-02 23:46:29 +02:00
|
|
|
|
script_fp = NULL;
|
|
|
|
|
}
|
2011-12-14 15:42:28 +01:00
|
|
|
|
|
2007-07-16 16:33:34 +02:00
|
|
|
|
|
|
|
|
|
/* FIXME: If the last command was BYE or the server died for
|
|
|
|
|
some other reason, we won't notice until we get the next
|
|
|
|
|
input command. Probing the connection with a non-blocking
|
|
|
|
|
read could help to notice termination or other problems
|
|
|
|
|
early. */
|
2005-02-24 18:36:11 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (opt.verbose)
|
|
|
|
|
log_info ("closing connection to agent\n");
|
2011-12-14 15:42:28 +01:00
|
|
|
|
|
2016-06-30 13:53:12 +02:00
|
|
|
|
/* XXX: We would like to release the context here, but libassuan
|
|
|
|
|
nicely says good bye to the server, which results in a SIGPIPE if
|
|
|
|
|
the server died. Unfortunately, libassuan does not ignore
|
|
|
|
|
SIGPIPE when used with UNIX sockets, hence we simply leak the
|
|
|
|
|
context here. */
|
|
|
|
|
if (0)
|
|
|
|
|
assuan_release (ctx);
|
|
|
|
|
else
|
|
|
|
|
gpgrt_annotate_leaked_object (ctx);
|
|
|
|
|
xfree (line);
|
2011-12-14 15:42:28 +01:00
|
|
|
|
return 0;
|
2005-02-24 18:36:11 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-05-20 22:39:36 +02:00
|
|
|
|
/* Handle an Inquire from the server. Return False if it could not be
|
|
|
|
|
handled; in this case the caller shll complete the operation. LINE
|
|
|
|
|
is the complete line as received from the server. This function
|
|
|
|
|
may change the content of LINE. */
|
|
|
|
|
static int
|
|
|
|
|
handle_inquire (assuan_context_t ctx, char *line)
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
definq_t d;
|
2007-10-19 16:51:39 +02:00
|
|
|
|
FILE *fp = NULL;
|
2005-05-20 22:39:36 +02:00
|
|
|
|
char buffer[1024];
|
|
|
|
|
int rc, n;
|
|
|
|
|
|
|
|
|
|
/* Skip the command and trailing spaces. */
|
|
|
|
|
for (; *line && !spacep (line); line++)
|
|
|
|
|
;
|
|
|
|
|
while (spacep (line))
|
|
|
|
|
line++;
|
|
|
|
|
/* Get the name. */
|
|
|
|
|
name = line;
|
|
|
|
|
for (; *line && !spacep (line); line++)
|
|
|
|
|
;
|
|
|
|
|
if (*line)
|
|
|
|
|
*line++ = 0;
|
|
|
|
|
|
2007-12-12 17:47:52 +01:00
|
|
|
|
/* Now match it against our list. The second loop is there to
|
|
|
|
|
detect the match-all entry. */
|
2005-05-20 22:39:36 +02:00
|
|
|
|
for (d=definq_list; d; d = d->next)
|
|
|
|
|
if (d->name && !strcmp (d->name, name))
|
|
|
|
|
break;
|
|
|
|
|
if (!d)
|
|
|
|
|
for (d=definq_list; d; d = d->next)
|
|
|
|
|
if (!d->name)
|
|
|
|
|
break;
|
|
|
|
|
if (!d)
|
|
|
|
|
{
|
|
|
|
|
if (opt.verbose)
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_info ("no handler for inquiry '%s' found\n", name);
|
2005-05-20 22:39:36 +02:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 16:51:39 +02:00
|
|
|
|
if (d->is_var)
|
2005-05-20 22:39:36 +02:00
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
char *tmpvalue = get_var_ext (d->file);
|
2014-03-18 16:49:38 +01:00
|
|
|
|
if (tmpvalue)
|
|
|
|
|
rc = assuan_send_data (ctx, tmpvalue, strlen (tmpvalue));
|
|
|
|
|
else
|
|
|
|
|
rc = assuan_send_data (ctx, "", 0);
|
2007-10-19 16:51:39 +02:00
|
|
|
|
xfree (tmpvalue);
|
|
|
|
|
if (rc)
|
|
|
|
|
log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
|
2005-05-20 22:39:36 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
if (d->is_prog)
|
|
|
|
|
{
|
2010-04-14 13:24:02 +02:00
|
|
|
|
#ifdef HAVE_W32CE_SYSTEM
|
|
|
|
|
fp = NULL;
|
|
|
|
|
#else
|
2007-10-19 16:51:39 +02:00
|
|
|
|
fp = popen (d->file, "r");
|
2010-04-14 13:24:02 +02:00
|
|
|
|
#endif
|
2007-10-19 16:51:39 +02:00
|
|
|
|
if (!fp)
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("error executing '%s': %s\n",
|
2007-10-19 16:51:39 +02:00
|
|
|
|
d->file, strerror (errno));
|
|
|
|
|
else if (opt.verbose)
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("handling inquiry '%s' by running '%s'\n",
|
2007-10-19 16:51:39 +02:00
|
|
|
|
name, d->file);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fp = fopen (d->file, "rb");
|
|
|
|
|
if (!fp)
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("error opening '%s': %s\n", d->file, strerror (errno));
|
2007-10-19 16:51:39 +02:00
|
|
|
|
else if (opt.verbose)
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("handling inquiry '%s' by returning content of '%s'\n",
|
2007-10-19 16:51:39 +02:00
|
|
|
|
name, d->file);
|
|
|
|
|
}
|
2005-05-20 22:39:36 +02:00
|
|
|
|
if (!fp)
|
2007-10-19 16:51:39 +02:00
|
|
|
|
return 0;
|
2005-05-20 22:39:36 +02:00
|
|
|
|
|
2007-10-19 16:51:39 +02:00
|
|
|
|
while ( (n = fread (buffer, 1, sizeof buffer, fp)) )
|
2005-05-20 22:39:36 +02:00
|
|
|
|
{
|
2007-10-19 16:51:39 +02:00
|
|
|
|
rc = assuan_send_data (ctx, buffer, n);
|
|
|
|
|
if (rc)
|
|
|
|
|
{
|
|
|
|
|
log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
|
|
|
|
|
break;
|
|
|
|
|
}
|
2005-05-20 22:39:36 +02:00
|
|
|
|
}
|
2007-10-19 16:51:39 +02:00
|
|
|
|
if (ferror (fp))
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("error reading from '%s': %s\n", d->file, strerror (errno));
|
2005-05-20 22:39:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc = assuan_send_data (ctx, NULL, 0);
|
|
|
|
|
if (rc)
|
2006-09-06 18:35:52 +02:00
|
|
|
|
log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
|
2005-05-20 22:39:36 +02:00
|
|
|
|
|
2007-10-19 16:51:39 +02:00
|
|
|
|
if (d->is_var)
|
|
|
|
|
;
|
|
|
|
|
else if (d->is_prog)
|
2005-05-20 22:39:36 +02:00
|
|
|
|
{
|
2010-04-14 13:24:02 +02:00
|
|
|
|
#ifndef HAVE_W32CE_SYSTEM
|
2005-05-20 22:39:36 +02:00
|
|
|
|
if (pclose (fp))
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("error running '%s': %s\n", d->file, strerror (errno));
|
2010-04-14 13:24:02 +02:00
|
|
|
|
#endif
|
2005-05-20 22:39:36 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
fclose (fp);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-02-24 18:36:11 +01:00
|
|
|
|
/* Read all response lines from server and print them. Returns 0 on
|
2009-11-04 11:59:11 +01:00
|
|
|
|
success or an assuan error code. If WITHHASH istrue, comment lines
|
|
|
|
|
are printed. Sets R_GOTERR to true if the command did not returned
|
|
|
|
|
OK. */
|
2005-02-24 18:36:11 +01:00
|
|
|
|
static int
|
2009-11-04 11:59:11 +01:00
|
|
|
|
read_and_print_response (assuan_context_t ctx, int withhash, int *r_goterr)
|
2005-02-24 18:36:11 +01:00
|
|
|
|
{
|
|
|
|
|
char *line;
|
2005-06-16 10:12:03 +02:00
|
|
|
|
size_t linelen;
|
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* configure.ac (NEED_LIBASSUAN_API, NEED_LIBASSUAN_VERSION):
Update to new API (2, 1.1.0).
agent/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* gpg-agent.c (parse_rereadable_options): Don't set global assuan
log file (there ain't one anymore).
(main): Update to new API.
(check_own_socket_pid_cb): Return gpg_error_t instead of int.
(check_own_socket_thread, check_for_running_agent): Create assuan
context before connecting to server.
* command.c: Include "scdaemon.h" before <assuan.h> because of
GPG_ERR_SOURCE_DEFAULT check.
(write_and_clear_outbuf): Use gpg_error_t instead of
assuan_error_t.
(cmd_geteventcounter, cmd_istrusted, cmd_listtrusted)
(cmd_marktrusted, cmd_havekey, cmd_sigkey, cmd_setkeydesc)
(cmd_sethash, cmd_pksign, cmd_pkdecrypt, cmd_genkey, cmd_readkey)
(cmd_keyinfo, cmd_get_passphrase, cmd_clear_passphrase)
(cmd_get_confirmation, cmd_learn, cmd_passwd)
(cmd_preset_passphrase, cmd_scd, cmd_getval, cmd_putval)
(cmd_updatestartuptty, cmd_killagent, cmd_reloadagent)
(cmd_getinfo, option_handler): Return gpg_error_t instead of int.
(post_cmd_notify): Change type of ERR to gpg_error_t from int.
(io_monitor): Add hook argument. Use symbols for constants.
(register_commands): Change return type of HANDLER to gpg_error_t.
(start_command_handler): Allocate assuan context before starting
server.
* call-pinentry.c: Include "scdaemon.h" before <assuan.h> because
of GPG_ERR_SOURCE_DEFAULT check.
(unlock_pinentry): Call assuan_release instead of
assuan_disconnect.
(getinfo_pid_cb, getpin_cb): Return gpg_error_t instead of int.
(start_pinentry): Allocate assuan context before connecting to
server.
* call-scd.c (membuf_data_cb, learn_status_cb, get_serialno_cb)
(membuf_data_cb, inq_needpin, card_getattr_cb, pass_status_thru)
(pass_data_thru): Change return type to gpg_error_t.
(start_scd): Allocate assuan context before connecting to server.
common/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* asshelp.c (start_new_gpg_agent): Allocate assuan context before
starting server.
g10/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* call-agent.c: Include "scdaemon.h" before <assuan.h> because of
GPG_ERR_SOURCE_DEFAULT check.
(learn_status_cb, dummy_data_cb, get_serialno_cb, default_inq_cb)
(learn_status_cb, inq_writecert_parms, inq_writekey_parms)
(scd_genkey_cb, membuf_data_cb): Return gpg_error_t instead of
int.
* gpg.c: Include "scdaemon.h" before <assuan.h> because of
GPG_ERR_SOURCE_DEFAULT check.
(main): Update to new Assuan API.
* server.c: Include "scdaemon.h" before <assuan.h> because of
GPG_ERR_SOURCE_DEFAULT check.
(option_handler, cmd_recipient, cmd_signer, cmd_encrypt)
(cmd_decrypt, cmd_verify, cmd_sign, cmd_import, cmd_export)
(cmd_delkeys, cmd_message, do_listkeys, cmd_listkeys)
(cmd_listsecretkeys, cmd_genkey, cmd_getinfo): Return gpg_error_t
instead of int.
(register_commands): Allocate assuan context before starting
server.
(gpg_server): Allocate assuan_context before starting server.
scd/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* command.c: Include "scdaemon.h" before <assuan.h> because of
GPG_ERR_SOURCE_DEFAULT check.
(option_handler, open_card, cmd_serialno, cmd_lean, cmd_readcert)
(cmd_readkey, cmd_setdata, cmd_pksign, cmd_pkauth, cmd_pkdecrypt)
(cmd_getattr, cmd_setattr, cmd_writecert, cmd_writekey)
(cmd_genkey, cmd_random, cmd_passwd, cmd_checkpin, cmd_lock)
(cmd_unlock, cmd_getinfo, cmd_restart, cmd_disconnect, cmd_apdu)
(cmd_killscd): Return gpg_error_t instead of int.
(scd_command_handler): Allocate assuan context before starting server.
* scdaemon.c (main): Update to new Assuan API.
sm/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* gpgsm.c (main): Update to new assuan API.
* server.c: Include "gpgsm.h" before <assuan.h> due to check for
GPG_ERR_SOURCE_DEFAULT and assuan.h now including gpg-error.h.
(option_handler, cmd_recipient, cmd_signer, cmd_encrypt)
(cmd_decrypt, cmd_verify, cmd_sign, cmd_import, cmd_export)
(cmd_delkeys, cmd_message, cmd_listkeys, cmd_dumpkeys)
(cmd_listsecretkeys, cmd_dumpsecretkeys, cmd_genkey)
(cmd_getauditlog, cmd_getinfo): Return gpg_error_t instead of int.
(register_commands): Same for member HANDLER in table.
(gpgsm_server): Allocate assuan context before starting server.
* sm/call-dirmngr.c:
* call-dirmngr.c (prepare_dirmngr): Check for CTX and error before
setting LDAPSERVER.
(start_dirmngr_ext): Allocate assuan context before starting
server.
(inq_certificate, isvalid_status_cb, lookup_cb, lookup_status_cb)
(run_command_cb, run_command_inq_cb, run_command_status_cb):
Return gpg_error_t instead of int.
tools/
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
* gpg-connect-agent.c (getinfo_pid_cb, read_and_print_response)
(main): Update to new Assuan API.
2009-09-23 02:01:25 +02:00
|
|
|
|
gpg_error_t rc;
|
2005-02-25 17:14:55 +01:00
|
|
|
|
int i, j;
|
2007-04-03 18:57:37 +02:00
|
|
|
|
int need_lf = 0;
|
2005-02-24 18:36:11 +01:00
|
|
|
|
|
2007-10-02 23:46:29 +02:00
|
|
|
|
*r_goterr = 0;
|
2005-02-24 18:36:11 +01:00
|
|
|
|
for (;;)
|
|
|
|
|
{
|
2011-12-14 15:42:28 +01:00
|
|
|
|
do
|
2005-02-24 18:36:11 +01:00
|
|
|
|
{
|
|
|
|
|
rc = assuan_read_line (ctx, &line, &linelen);
|
|
|
|
|
if (rc)
|
|
|
|
|
return rc;
|
2006-09-13 17:57:30 +02:00
|
|
|
|
|
2009-11-04 11:59:11 +01:00
|
|
|
|
if ((withhash || opt.verbose > 1) && *line == '#')
|
2006-09-13 17:57:30 +02:00
|
|
|
|
{
|
|
|
|
|
fwrite (line, linelen, 1, stdout);
|
|
|
|
|
putchar ('\n');
|
|
|
|
|
}
|
2011-12-14 15:42:28 +01:00
|
|
|
|
}
|
2005-02-24 18:36:11 +01:00
|
|
|
|
while (*line == '#' || !linelen);
|
|
|
|
|
|
|
|
|
|
if (linelen >= 1
|
|
|
|
|
&& line[0] == 'D' && line[1] == ' ')
|
|
|
|
|
{
|
2008-10-01 18:17:39 +02:00
|
|
|
|
if (current_datasink)
|
|
|
|
|
{
|
|
|
|
|
const unsigned char *s;
|
|
|
|
|
int c = 0;
|
|
|
|
|
|
|
|
|
|
for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
|
|
|
|
|
{
|
|
|
|
|
if (*s == '%' && j+2 < linelen)
|
2011-12-14 15:42:28 +01:00
|
|
|
|
{
|
2008-10-01 18:17:39 +02:00
|
|
|
|
s++; j++;
|
|
|
|
|
c = xtoi_2 ( s );
|
|
|
|
|
s++; j++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
c = *s;
|
|
|
|
|
putc (c, current_datasink);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (opt.hex)
|
2005-02-25 17:14:55 +01:00
|
|
|
|
{
|
|
|
|
|
for (i=2; i < linelen; )
|
|
|
|
|
{
|
|
|
|
|
int save_i = i;
|
|
|
|
|
|
|
|
|
|
printf ("D[%04X] ", i-2);
|
|
|
|
|
for (j=0; j < 16 ; j++, i++)
|
|
|
|
|
{
|
|
|
|
|
if (j == 8)
|
|
|
|
|
putchar (' ');
|
|
|
|
|
if (i < linelen)
|
|
|
|
|
printf (" %02X", ((unsigned char*)line)[i]);
|
|
|
|
|
else
|
|
|
|
|
fputs (" ", stdout);
|
|
|
|
|
}
|
|
|
|
|
fputs (" ", stdout);
|
|
|
|
|
i= save_i;
|
|
|
|
|
for (j=0; j < 16; j++, i++)
|
|
|
|
|
{
|
|
|
|
|
unsigned int c = ((unsigned char*)line)[i];
|
|
|
|
|
if ( i >= linelen )
|
|
|
|
|
putchar (' ');
|
|
|
|
|
else if (isascii (c) && isprint (c) && !iscntrl (c))
|
|
|
|
|
putchar (c);
|
|
|
|
|
else
|
|
|
|
|
putchar ('.');
|
|
|
|
|
}
|
|
|
|
|
putchar ('\n');
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-04-03 18:57:37 +02:00
|
|
|
|
else if (opt.decode)
|
|
|
|
|
{
|
|
|
|
|
const unsigned char *s;
|
|
|
|
|
int need_d = 1;
|
|
|
|
|
int c = 0;
|
|
|
|
|
|
|
|
|
|
for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
|
|
|
|
|
{
|
|
|
|
|
if (need_d)
|
|
|
|
|
{
|
|
|
|
|
fputs ("D ", stdout);
|
|
|
|
|
need_d = 0;
|
|
|
|
|
}
|
|
|
|
|
if (*s == '%' && j+2 < linelen)
|
2011-12-14 15:42:28 +01:00
|
|
|
|
{
|
2007-04-03 18:57:37 +02:00
|
|
|
|
s++; j++;
|
|
|
|
|
c = xtoi_2 ( s );
|
|
|
|
|
s++; j++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
c = *s;
|
|
|
|
|
if (c == '\n')
|
|
|
|
|
need_d = 1;
|
|
|
|
|
putchar (c);
|
|
|
|
|
}
|
|
|
|
|
need_lf = (c != '\n');
|
|
|
|
|
}
|
2005-02-25 17:14:55 +01:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fwrite (line, linelen, 1, stdout);
|
|
|
|
|
putchar ('\n');
|
|
|
|
|
}
|
2005-02-24 18:36:11 +01:00
|
|
|
|
}
|
2011-12-14 15:42:28 +01:00
|
|
|
|
else
|
2005-02-24 18:36:11 +01:00
|
|
|
|
{
|
2007-04-03 18:57:37 +02:00
|
|
|
|
if (need_lf)
|
|
|
|
|
{
|
2008-10-01 18:17:39 +02:00
|
|
|
|
if (!current_datasink || current_datasink != stdout)
|
|
|
|
|
putchar ('\n');
|
2007-04-03 18:57:37 +02:00
|
|
|
|
need_lf = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (linelen >= 1
|
2011-12-14 15:42:28 +01:00
|
|
|
|
&& line[0] == 'S'
|
2007-04-03 18:57:37 +02:00
|
|
|
|
&& (line[1] == '\0' || line[1] == ' '))
|
|
|
|
|
{
|
2008-10-01 18:17:39 +02:00
|
|
|
|
if (!current_datasink || current_datasink != stdout)
|
|
|
|
|
{
|
|
|
|
|
fwrite (line, linelen, 1, stdout);
|
|
|
|
|
putchar ('\n');
|
|
|
|
|
}
|
2011-12-14 15:42:28 +01:00
|
|
|
|
}
|
2007-04-03 18:57:37 +02:00
|
|
|
|
else if (linelen >= 2
|
|
|
|
|
&& line[0] == 'O' && line[1] == 'K'
|
|
|
|
|
&& (line[2] == '\0' || line[2] == ' '))
|
|
|
|
|
{
|
2008-10-01 18:17:39 +02:00
|
|
|
|
if (!current_datasink || current_datasink != stdout)
|
|
|
|
|
{
|
|
|
|
|
fwrite (line, linelen, 1, stdout);
|
|
|
|
|
putchar ('\n');
|
|
|
|
|
}
|
2008-03-05 11:08:10 +01:00
|
|
|
|
set_int_var ("?", 0);
|
2007-04-03 18:57:37 +02:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else if (linelen >= 3
|
|
|
|
|
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
|
|
|
|
|
&& (line[3] == '\0' || line[3] == ' '))
|
|
|
|
|
{
|
2008-03-05 11:08:10 +01:00
|
|
|
|
int errval;
|
|
|
|
|
|
|
|
|
|
errval = strtol (line+3, NULL, 10);
|
|
|
|
|
if (!errval)
|
|
|
|
|
errval = -1;
|
|
|
|
|
set_int_var ("?", errval);
|
2008-10-01 18:17:39 +02:00
|
|
|
|
if (!current_datasink || current_datasink != stdout)
|
|
|
|
|
{
|
|
|
|
|
fwrite (line, linelen, 1, stdout);
|
|
|
|
|
putchar ('\n');
|
|
|
|
|
}
|
2007-10-02 23:46:29 +02:00
|
|
|
|
*r_goterr = 1;
|
2007-04-03 18:57:37 +02:00
|
|
|
|
return 0;
|
2011-12-14 15:42:28 +01:00
|
|
|
|
}
|
2007-04-03 18:57:37 +02:00
|
|
|
|
else if (linelen >= 7
|
|
|
|
|
&& line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
|
|
|
|
|
&& line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
|
2011-12-14 15:42:28 +01:00
|
|
|
|
&& line[6] == 'E'
|
2007-04-03 18:57:37 +02:00
|
|
|
|
&& (line[7] == '\0' || line[7] == ' '))
|
|
|
|
|
{
|
2008-10-01 18:17:39 +02:00
|
|
|
|
if (!current_datasink || current_datasink != stdout)
|
|
|
|
|
{
|
|
|
|
|
fwrite (line, linelen, 1, stdout);
|
|
|
|
|
putchar ('\n');
|
|
|
|
|
}
|
2007-04-03 18:57:37 +02:00
|
|
|
|
if (!handle_inquire (ctx, line))
|
|
|
|
|
assuan_write_line (ctx, "CANCEL");
|
|
|
|
|
}
|
|
|
|
|
else if (linelen >= 3
|
|
|
|
|
&& line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
|
|
|
|
|
&& (line[3] == '\0' || line[3] == ' '))
|
|
|
|
|
{
|
2008-10-01 18:17:39 +02:00
|
|
|
|
if (!current_datasink || current_datasink != stdout)
|
|
|
|
|
{
|
|
|
|
|
fwrite (line, linelen, 1, stdout);
|
|
|
|
|
putchar ('\n');
|
|
|
|
|
}
|
2007-04-03 18:57:37 +02:00
|
|
|
|
/* Received from server, thus more responses are expected. */
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return gpg_error (GPG_ERR_ASS_INV_RESPONSE);
|
2005-02-24 18:36:11 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2005-04-11 18:21:49 +02:00
|
|
|
|
/* Connect to the agent and send the standard options. */
|
2005-02-24 18:36:11 +01:00
|
|
|
|
static assuan_context_t
|
|
|
|
|
start_agent (void)
|
|
|
|
|
{
|
2010-10-14 10:32:55 +02:00
|
|
|
|
gpg_error_t err;
|
2005-02-24 18:36:11 +01:00
|
|
|
|
assuan_context_t ctx;
|
2009-07-07 12:02:41 +02:00
|
|
|
|
session_env_t session_env;
|
|
|
|
|
|
2009-07-07 12:29:52 +02:00
|
|
|
|
session_env = session_env_new ();
|
|
|
|
|
if (!session_env)
|
|
|
|
|
log_fatal ("error allocating session environment block: %s\n",
|
|
|
|
|
strerror (errno));
|
2014-03-14 19:25:58 +01:00
|
|
|
|
if (opt.use_dirmngr)
|
|
|
|
|
err = start_new_dirmngr (&ctx,
|
2010-10-14 10:32:55 +02:00
|
|
|
|
GPG_ERR_SOURCE_DEFAULT,
|
2014-03-14 19:25:58 +01:00
|
|
|
|
opt.dirmngr_program,
|
2014-11-19 10:31:34 +01:00
|
|
|
|
opt.autostart,
|
2010-10-14 10:32:55 +02:00
|
|
|
|
!opt.quiet, 0,
|
|
|
|
|
NULL, NULL);
|
2014-03-14 19:25:58 +01:00
|
|
|
|
else
|
|
|
|
|
err = start_new_gpg_agent (&ctx,
|
|
|
|
|
GPG_ERR_SOURCE_DEFAULT,
|
|
|
|
|
opt.agent_program,
|
|
|
|
|
NULL, NULL,
|
|
|
|
|
session_env,
|
2014-11-19 10:31:34 +01:00
|
|
|
|
opt.autostart,
|
2014-03-14 19:25:58 +01:00
|
|
|
|
!opt.quiet, 0,
|
|
|
|
|
NULL, NULL);
|
2010-10-14 10:32:55 +02:00
|
|
|
|
|
2009-07-07 12:29:52 +02:00
|
|
|
|
session_env_release (session_env);
|
2010-10-14 10:32:55 +02:00
|
|
|
|
if (err)
|
2005-02-24 18:36:11 +01:00
|
|
|
|
{
|
2014-11-19 10:31:34 +01:00
|
|
|
|
if (!opt.autostart
|
|
|
|
|
&& (gpg_err_code (err)
|
2017-04-12 09:01:16 +02:00
|
|
|
|
== (opt.use_dirmngr? GPG_ERR_NO_DIRMNGR : GPG_ERR_NO_AGENT)))
|
2014-11-19 10:31:34 +01:00
|
|
|
|
{
|
|
|
|
|
/* In the no-autostart case we don't make gpg-connect-agent
|
|
|
|
|
fail on a missing server. */
|
|
|
|
|
log_info (opt.use_dirmngr?
|
|
|
|
|
_("no dirmngr running in this session\n"):
|
|
|
|
|
_("no gpg-agent running in this session\n"));
|
|
|
|
|
exit (0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
log_error (_("error sending standard options: %s\n"),
|
|
|
|
|
gpg_strerror (err));
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
2005-02-24 18:36:11 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ctx;
|
|
|
|
|
}
|