agent: Pass comment lines from scd verbatim thru gpg-agent.

* agent/call-scd.c (pass_status_thru): Pass comment lines verbatim.
* tools/gpg-connect-agent.c (help_cmd_p): New.
(main): Treat an "SCD HELP" the same as "HELP".
This commit is contained in:
Werner Koch 2011-12-14 15:42:28 +01:00
parent 2d91febbd8
commit 45cf9de341
3 changed files with 121 additions and 81 deletions

13
NEWS
View File

@ -9,6 +9,19 @@ Noteworthy changes in version 2.1.0beta3
* The Assuan commands KILLAGENT and KILLSCD are working again. * The Assuan commands KILLAGENT and KILLSCD are working again.
* SCdaemon does not anymore block after changing a card (regression
fix).
* gpg-connect-agent does now proberly display the help output for
"SCD HELP" commands.
* New GPGSM validation model "steed".
* Improved certificate creation in GPGSM.
* New option for GPG_AGENT to select a passphrase mode. The loopback
mode may be used to bypass Pinentry.
Noteworthy changes in version 2.1.0beta2 (2011-03-08) Noteworthy changes in version 2.1.0beta2 (2011-03-08)
----------------------------------------------------- -----------------------------------------------------

View File

@ -1,5 +1,6 @@
/* call-scd.c - fork of the scdaemon to do SC operations /* call-scd.c - fork of the scdaemon to do SC operations
* Copyright (C) 2001, 2002, 2005, 2007, 2010 Free Software Foundation, Inc. * Copyright (C) 2001, 2002, 2005, 2007, 2010,
* 2011 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -1129,16 +1130,28 @@ pass_status_thru (void *opaque, const char *line)
char keyword[200]; char keyword[200];
int i; int i;
for (i=0; *line && !spacep (line) && i < DIM(keyword)-1; line++, i++) if (line[0] == '#' && (!line[1] || spacep (line+1)))
keyword[i] = *line; {
keyword[i] = 0; /* We are called in convey comments mode. Now, if we see a
/* truncate any remaining keyword stuff. */ comment marker as keyword we forward the line verbatim to the
for (; *line && !spacep (line); line++) the caller. This way the comment lines from scdaemon won't
; appear as status lines with keyword '#'. */
while (spacep (line)) assuan_write_line (ctx, line);
line++; }
else
{
for (i=0; *line && !spacep (line) && i < DIM(keyword)-1; line++, i++)
keyword[i] = *line;
keyword[i] = 0;
assuan_write_status (ctx, keyword, line); /* Truncate any remaining keyword stuff. */
for (; *line && !spacep (line); line++)
;
while (spacep (line))
line++;
assuan_write_status (ctx, keyword, line);
}
return 0; return 0;
} }

View File

@ -67,25 +67,25 @@ enum cmd_and_opt_values
/* The list of commands and options. */ /* The list of commands and options. */
static ARGPARSE_OPTS opts[] = { static ARGPARSE_OPTS opts[] = {
ARGPARSE_group (301, N_("@\nOptions:\n ")), ARGPARSE_group (301, N_("@\nOptions:\n ")),
ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")), ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
ARGPARSE_s_n (oQuiet, "quiet", N_("quiet")), ARGPARSE_s_n (oQuiet, "quiet", N_("quiet")),
ARGPARSE_s_n (oHex, "hex", N_("print data out hex encoded")), ARGPARSE_s_n (oHex, "hex", N_("print data out hex encoded")),
ARGPARSE_s_n (oDecode,"decode", N_("decode received data lines")), ARGPARSE_s_n (oDecode,"decode", N_("decode received data lines")),
ARGPARSE_s_s (oRawSocket, "raw-socket", ARGPARSE_s_s (oRawSocket, "raw-socket",
N_("|NAME|connect to Assuan socket NAME")), N_("|NAME|connect to Assuan socket NAME")),
ARGPARSE_s_s (oTcpSocket, "tcp-socket", ARGPARSE_s_s (oTcpSocket, "tcp-socket",
N_("|ADDR|connect to Assuan server at ADDR")), N_("|ADDR|connect to Assuan server at ADDR")),
ARGPARSE_s_n (oExec, "exec", ARGPARSE_s_n (oExec, "exec",
N_("run the Assuan server given on the command line")), N_("run the Assuan server given on the command line")),
ARGPARSE_s_n (oNoExtConnect, "no-ext-connect", ARGPARSE_s_n (oNoExtConnect, "no-ext-connect",
N_("do not use extended connect mode")), N_("do not use extended connect mode")),
ARGPARSE_s_s (oRun, "run", ARGPARSE_s_s (oRun, "run",
N_("|FILE|run commands from FILE on startup")), N_("|FILE|run commands from FILE on startup")),
ARGPARSE_s_n (oSubst, "subst", N_("run /subst on startup")), ARGPARSE_s_n (oSubst, "subst", N_("run /subst on startup")),
ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"), ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"),
ARGPARSE_s_s (oHomedir, "homedir", "@" ), ARGPARSE_s_s (oHomedir, "homedir", "@" ),
ARGPARSE_s_s (oAgentProgram, "agent-program", "@"), ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
ARGPARSE_end () ARGPARSE_end ()
@ -216,7 +216,7 @@ gnu_getcwd (void)
#ifdef HAVE_W32CE_SYSTEM #ifdef HAVE_W32CE_SYSTEM
strcpy (buffer, "/"); strcpy (buffer, "/");
return buffer; return buffer;
#else #else
if (getcwd (buffer, size) == buffer) if (getcwd (buffer, size) == buffer)
return buffer; return buffer;
xfree (buffer); xfree (buffer);
@ -246,22 +246,22 @@ unescape_string (const char *string)
{ {
switch (*s) switch (*s)
{ {
case 'b': case 'b':
case 't': case 't':
case 'v': case 'v':
case 'n': case 'n':
case 'f': case 'f':
case 'r': case 'r':
case '"': case '"':
case '\'': case '\'':
case '\\': n++; break; case '\\': n++; break;
case 'x': case 'x':
if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2)) if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
n++; n++;
break; break;
default: default:
if (s[1] && s[2] if (s[1] && s[2]
&& octdigitp (s) && octdigitp (s+1) && octdigitp (s+2)) && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
n++; n++;
break; break;
@ -272,7 +272,7 @@ unescape_string (const char *string)
esc = 1; esc = 1;
else else
n++; n++;
} }
buffer = xmalloc (n+1); buffer = xmalloc (n+1);
d = (unsigned char*)buffer; d = (unsigned char*)buffer;
@ -291,7 +291,7 @@ unescape_string (const char *string)
case '"': *d++ = '\"'; break; case '"': *d++ = '\"'; break;
case '\'': *d++ = '\''; break; case '\'': *d++ = '\''; break;
case '\\': *d++ = '\\'; break; case '\\': *d++ = '\\'; break;
case 'x': case 'x':
if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2)) if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
{ {
s++; s++;
@ -301,7 +301,7 @@ unescape_string (const char *string)
break; break;
default: default:
if (s[1] && s[2] if (s[1] && s[2]
&& octdigitp (s) && octdigitp (s+1) && octdigitp (s+2)) && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
{ {
*d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2); *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2);
@ -315,7 +315,7 @@ unescape_string (const char *string)
esc = 1; esc = 1;
else else
*d++ = *s; *d++ = *s;
} }
*d = 0; *d = 0;
return buffer; return buffer;
} }
@ -334,7 +334,7 @@ unpercent_string (const char *string, int with_plus)
for (s=(const unsigned char *)string; *s; s++) for (s=(const unsigned char *)string; *s; s++)
{ {
if (*s == '%' && s[1] && s[2]) if (*s == '%' && s[1] && s[2])
{ {
s++; s++;
n++; n++;
s++; s++;
@ -350,7 +350,7 @@ unpercent_string (const char *string, int with_plus)
for (s=(const unsigned char *)string; *s; s++) for (s=(const unsigned char *)string; *s; s++)
{ {
if (*s == '%' && s[1] && s[2]) if (*s == '%' && s[1] && s[2])
{ {
s++; s++;
*p++ = xtoi_2 (s); *p++ = xtoi_2 (s);
s++; s++;
@ -387,7 +387,7 @@ set_var (const char *name, const char *value)
xfree (var->value); xfree (var->value);
var->value = value? xstrdup (value) : NULL; var->value = value? xstrdup (value) : NULL;
return var->value; return var->value;
} }
static void static void
@ -455,12 +455,12 @@ arithmetic_op (int operator, const char *operands)
case '+': result += value; break; case '+': result += value; break;
case '-': result -= value; break; case '-': result -= value; break;
case '*': result *= value; break; case '*': result *= value; break;
case '/': case '/':
if (!value) if (!value)
return NULL; return NULL;
result /= value; result /= value;
break; break;
case '%': case '%':
if (!value) if (!value)
return NULL; return NULL;
result %= value; result %= value;
@ -480,10 +480,10 @@ arithmetic_op (int operator, const char *operands)
/* Extended version of get_var. This returns a malloced string and /* Extended version of get_var. This returns a malloced string and
understand the function syntax: "func args". understand the function syntax: "func args".
Defined functions are Defined functions are
get - Return a value described by the next argument: get - Return a value described by the next argument:
cwd - The current working directory. cwd - The current working directory.
homedir - The gnupg homedir. homedir - The gnupg homedir.
@ -525,7 +525,7 @@ arithmetic_op (int operator, const char *operands)
Example: get_var_ext ("get sysconfdir") -> "/etc/gnupg" Example: get_var_ext ("get sysconfdir") -> "/etc/gnupg"
*/ */
static char * static char *
get_var_ext (const char *name) get_var_ext (const char *name)
@ -630,7 +630,7 @@ get_var_ext (const char *name)
{ {
s++; s++;
intvalue = (int)strtol (s, NULL, 0); intvalue = (int)strtol (s, NULL, 0);
result = xasprintf ("%s <%s>", result = xasprintf ("%s <%s>",
gpg_strerror (intvalue), gpg_strsource (intvalue)); gpg_strerror (intvalue), gpg_strsource (intvalue));
} }
else if ( (s - name) == 1 && strchr ("+-*/%!|&", *name)) else if ( (s - name) == 1 && strchr ("+-*/%!|&", *name))
@ -642,7 +642,7 @@ get_var_ext (const char *name)
log_error ("unknown variable function `%.*s'\n", (int)(s-name), name); log_error ("unknown variable function `%.*s'\n", (int)(s-name), name);
result = NULL; result = NULL;
} }
xfree (free_me); xfree (free_me);
recursion_count--; recursion_count--;
return result; return result;
@ -667,7 +667,7 @@ substitute_line (char *buffer)
p = strchr (line, '$'); p = strchr (line, '$');
if (!p) if (!p)
return result; /* No more variables. */ return result; /* No more variables. */
if (p[1] == '$') /* Escaped dollar sign. */ if (p[1] == '$') /* Escaped dollar sign. */
{ {
memmove (p, p+1, strlen (p+1)+1); memmove (p, p+1, strlen (p+1)+1);
@ -751,7 +751,7 @@ static char *
substitute_line_copy (const char *buffer) substitute_line_copy (const char *buffer)
{ {
char *result, *p; char *result, *p;
p = xstrdup (buffer?buffer:""); p = xstrdup (buffer?buffer:"");
result = substitute_line (p); result = substitute_line (p);
if (!result) if (!result)
@ -777,7 +777,7 @@ assign_variable (char *line, int syslet)
p++; p++;
if (!*p) if (!*p)
set_var (name, NULL); /* Remove variable. */ set_var (name, NULL); /* Remove variable. */
else if (syslet) else if (syslet)
{ {
free_me = opt.enable_varsubst? substitute_line_copy (p) : NULL; free_me = opt.enable_varsubst? substitute_line_copy (p) : NULL;
@ -791,7 +791,7 @@ assign_variable (char *line, int syslet)
xfree (tmp); xfree (tmp);
xfree (free_me); xfree (free_me);
} }
else else
{ {
tmp = opt.enable_varsubst? substitute_line_copy (p) : NULL; tmp = opt.enable_varsubst? substitute_line_copy (p) : NULL;
if (tmp) if (tmp)
@ -857,11 +857,11 @@ show_definq (void)
for (d=definq_list; d; d = d->next) for (d=definq_list; d; d = d->next)
if (d->name) if (d->name)
printf ("%-20s %c %s\n", printf ("%-20s %c %s\n",
d->name, d->is_var? 'v' : d->is_prog? 'p':'f', d->file); d->name, d->is_var? 'v' : d->is_prog? 'p':'f', d->file);
for (d=definq_list; d; d = d->next) for (d=definq_list; d; d = d->next)
if (!d->name) if (!d->name)
printf ("%-20s %c %s\n", "*", printf ("%-20s %c %s\n", "*",
d->is_var? 'v': d->is_prog? 'p':'f', d->file); d->is_var? 'v': d->is_prog? 'p':'f', d->file);
} }
@ -871,14 +871,14 @@ static void
clear_definq (void) clear_definq (void)
{ {
while (definq_list) while (definq_list)
{ {
definq_t tmp = definq_list->next; definq_t tmp = definq_list->next;
xfree (definq_list->name); xfree (definq_list->name);
xfree (definq_list); xfree (definq_list);
definq_list = tmp; definq_list = tmp;
} }
definq_list_tail = &definq_list; definq_list_tail = &definq_list;
} }
static void static void
@ -1005,7 +1005,7 @@ do_open (char *line)
HANDLE prochandle, handle, newhandle; HANDLE prochandle, handle, newhandle;
handle = (void*)_get_osfhandle (fd); handle = (void*)_get_osfhandle (fd);
prochandle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, server_pid); prochandle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, server_pid);
if (!prochandle) if (!prochandle)
{ {
@ -1030,7 +1030,7 @@ do_open (char *line)
log_info ("file `%s' opened in \"%s\" mode, fd=%d (libc=%d)\n", log_info ("file `%s' opened in \"%s\" mode, fd=%d (libc=%d)\n",
name, mode, (int)open_fd_table[fd].handle, fd); name, mode, (int)open_fd_table[fd].handle, fd);
set_int_var (varname, (int)open_fd_table[fd].handle); set_int_var (varname, (int)open_fd_table[fd].handle);
#else #else
if (opt.verbose) if (opt.verbose)
log_info ("file `%s' opened in \"%s\" mode, fd=%d\n", log_info ("file `%s' opened in \"%s\" mode, fd=%d\n",
name, mode, fd); name, mode, fd);
@ -1117,14 +1117,14 @@ do_serverpid (assuan_context_t ctx)
int rc; int rc;
membuf_t mb; membuf_t mb;
char *buffer; char *buffer;
init_membuf (&mb, 100); init_membuf (&mb, 100);
rc = assuan_transact (ctx, "GETINFO pid", getinfo_pid_cb, &mb, rc = assuan_transact (ctx, "GETINFO pid", getinfo_pid_cb, &mb,
NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL);
put_membuf (&mb, "", 1); put_membuf (&mb, "", 1);
buffer = get_membuf (&mb, NULL); buffer = get_membuf (&mb, NULL);
if (rc || !buffer) if (rc || !buffer)
log_error ("command \"%s\" failed: %s\n", log_error ("command \"%s\" failed: %s\n",
"GETINFO pid", gpg_strerror (rc)); "GETINFO pid", gpg_strerror (rc));
else else
{ {
@ -1136,6 +1136,22 @@ do_serverpid (assuan_context_t ctx)
} }
/* 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]));
}
/* gpg-connect-agent's entry point. */ /* gpg-connect-agent's entry point. */
int int
main (int argc, char **argv) main (int argc, char **argv)
@ -1156,7 +1172,7 @@ main (int argc, char **argv)
loopline_t head; loopline_t head;
loopline_t *tail; loopline_t *tail;
loopline_t current; loopline_t current;
unsigned int nestlevel; unsigned int nestlevel;
int oneshot; int oneshot;
char *condition; char *condition;
} loopstack[20]; } loopstack[20];
@ -1197,7 +1213,7 @@ main (int argc, char **argv)
case oExec: opt.exec = 1; break; case oExec: opt.exec = 1; break;
case oNoExtConnect: opt.connect_flags &= ~(1); break; case oNoExtConnect: opt.connect_flags &= ~(1); break;
case oRun: opt_run = pargs.r.ret_str; break; case oRun: opt_run = pargs.r.ret_str; break;
case oSubst: case oSubst:
opt.enable_varsubst = 1; opt.enable_varsubst = 1;
opt.trim_leading_spaces = 1; opt.trim_leading_spaces = 1;
break; break;
@ -1339,7 +1355,7 @@ main (int argc, char **argv)
log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) ); log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
} }
for (loopidx=0; loopidx < DIM (loopstack); loopidx++) for (loopidx=0; loopidx < DIM (loopstack); loopidx++)
loopstack[loopidx].collecting = 0; loopstack[loopidx].collecting = 0;
loopidx = -1; loopidx = -1;
@ -1396,7 +1412,7 @@ main (int argc, char **argv)
linesize = 0; linesize = 0;
keep_line = 1; keep_line = 1;
} }
n = read_line (script_fp? script_fp:stdin, n = read_line (script_fp? script_fp:stdin,
&line, &linesize, &maxlength); &line, &linesize, &maxlength);
} }
if (n < 0) if (n < 0)
@ -1422,7 +1438,7 @@ main (int argc, char **argv)
log_info ("end of script\n"); log_info ("end of script\n");
continue; continue;
} }
break; break;
} }
if (!maxlength) if (!maxlength)
{ {
@ -1433,11 +1449,11 @@ main (int argc, char **argv)
log_info (_("line shortened due to embedded Nul character\n")); log_info (_("line shortened due to embedded Nul character\n"));
if (line[n-1] == '\n') if (line[n-1] == '\n')
line[n-1] = 0; line[n-1] = 0;
if (opt.trim_leading_spaces) if (opt.trim_leading_spaces)
{ {
const char *s = line; const char *s = line;
while (spacep (s)) while (spacep (s))
s++; s++;
if (s != line) if (s != line)
@ -1463,7 +1479,7 @@ main (int argc, char **argv)
loopstack[loopidx+1].nestlevel--; loopstack[loopidx+1].nestlevel--;
else if (!strncmp (line, "/while", 6) && (!line[6]||spacep(line+6))) else if (!strncmp (line, "/while", 6) && (!line[6]||spacep(line+6)))
loopstack[loopidx+1].nestlevel++; loopstack[loopidx+1].nestlevel++;
if (loopstack[loopidx+1].nestlevel) if (loopstack[loopidx+1].nestlevel)
continue; continue;
/* We reached the corresponding /end. */ /* We reached the corresponding /end. */
@ -1546,7 +1562,7 @@ main (int argc, char **argv)
{ {
current_datasink = fopen (fname, "wb"); current_datasink = fopen (fname, "wb");
if (!current_datasink) if (!current_datasink)
log_error ("can't open `%s': %s\n", log_error ("can't open `%s': %s\n",
fname, strerror (errno)); fname, strerror (errno));
} }
xfree (tmpline); xfree (tmpline);
@ -1783,7 +1799,7 @@ main (int argc, char **argv)
"/cleardef Delete all definitions.\n" "/cleardef Delete all definitions.\n"
"/sendfd FILE MODE Open FILE and pass descriptor to server.\n" "/sendfd FILE MODE Open FILE and pass descriptor to server.\n"
"/recvfd Receive FD from server and print.\n" "/recvfd Receive FD from server and print.\n"
"/open VAR FILE MODE Open FILE and assign the file descriptor to VAR.\n" "/open VAR FILE MODE Open FILE and assign the file descriptor to VAR.\n"
"/close FD Close file with descriptor FD.\n" "/close FD Close file with descriptor FD.\n"
"/showopen Show descriptors of all open files.\n" "/showopen Show descriptors of all open files.\n"
"/serverpid Retrieve the pid of the server.\n" "/serverpid Retrieve the pid of the server.\n"
@ -1799,7 +1815,7 @@ main (int argc, char **argv)
} }
else else
log_error (_("unknown command `%s'\n"), cmd ); log_error (_("unknown command `%s'\n"), cmd );
continue; continue;
} }
@ -1822,9 +1838,7 @@ main (int argc, char **argv)
if (*line == '#' || !*line) if (*line == '#' || !*line)
continue; /* Don't expect a response for a comment line. */ continue; /* Don't expect a response for a comment line. */
rc = read_and_print_response (ctx, (!ascii_strncasecmp (line, "HELP", 4) rc = read_and_print_response (ctx, help_cmd_p (line), &cmderr);
&& (spacep (line+4) || !line[4])),
&cmderr);
if (rc) if (rc)
log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) ); log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
if ((rc || cmderr) && script_fp) if ((rc || cmderr) && script_fp)
@ -1833,7 +1847,7 @@ main (int argc, char **argv)
fclose (script_fp); fclose (script_fp);
script_fp = NULL; script_fp = NULL;
} }
/* FIXME: If the last command was BYE or the server died for /* FIXME: If the last command was BYE or the server died for
some other reason, we won't notice until we get the next some other reason, we won't notice until we get the next
@ -1844,8 +1858,8 @@ main (int argc, char **argv)
if (opt.verbose) if (opt.verbose)
log_info ("closing connection to agent\n"); log_info ("closing connection to agent\n");
return 0; return 0;
} }
@ -1911,7 +1925,7 @@ handle_inquire (assuan_context_t ctx, char *line)
log_error ("error executing `%s': %s\n", log_error ("error executing `%s': %s\n",
d->file, strerror (errno)); d->file, strerror (errno));
else if (opt.verbose) else if (opt.verbose)
log_error ("handling inquiry `%s' by running `%s'\n", log_error ("handling inquiry `%s' by running `%s'\n",
name, d->file); name, d->file);
} }
else else
@ -1974,7 +1988,7 @@ read_and_print_response (assuan_context_t ctx, int withhash, int *r_goterr)
*r_goterr = 0; *r_goterr = 0;
for (;;) for (;;)
{ {
do do
{ {
rc = assuan_read_line (ctx, &line, &linelen); rc = assuan_read_line (ctx, &line, &linelen);
if (rc) if (rc)
@ -1985,7 +1999,7 @@ read_and_print_response (assuan_context_t ctx, int withhash, int *r_goterr)
fwrite (line, linelen, 1, stdout); fwrite (line, linelen, 1, stdout);
putchar ('\n'); putchar ('\n');
} }
} }
while (*line == '#' || !linelen); while (*line == '#' || !linelen);
if (linelen >= 1 if (linelen >= 1
@ -1999,7 +2013,7 @@ read_and_print_response (assuan_context_t ctx, int withhash, int *r_goterr)
for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ ) for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
{ {
if (*s == '%' && j+2 < linelen) if (*s == '%' && j+2 < linelen)
{ {
s++; j++; s++; j++;
c = xtoi_2 ( s ); c = xtoi_2 ( s );
s++; j++; s++; j++;
@ -2054,7 +2068,7 @@ read_and_print_response (assuan_context_t ctx, int withhash, int *r_goterr)
need_d = 0; need_d = 0;
} }
if (*s == '%' && j+2 < linelen) if (*s == '%' && j+2 < linelen)
{ {
s++; j++; s++; j++;
c = xtoi_2 ( s ); c = xtoi_2 ( s );
s++; j++; s++; j++;
@ -2073,7 +2087,7 @@ read_and_print_response (assuan_context_t ctx, int withhash, int *r_goterr)
putchar ('\n'); putchar ('\n');
} }
} }
else else
{ {
if (need_lf) if (need_lf)
{ {
@ -2083,7 +2097,7 @@ read_and_print_response (assuan_context_t ctx, int withhash, int *r_goterr)
} }
if (linelen >= 1 if (linelen >= 1
&& line[0] == 'S' && line[0] == 'S'
&& (line[1] == '\0' || line[1] == ' ')) && (line[1] == '\0' || line[1] == ' '))
{ {
if (!current_datasink || current_datasink != stdout) if (!current_datasink || current_datasink != stdout)
@ -2091,7 +2105,7 @@ read_and_print_response (assuan_context_t ctx, int withhash, int *r_goterr)
fwrite (line, linelen, 1, stdout); fwrite (line, linelen, 1, stdout);
putchar ('\n'); putchar ('\n');
} }
} }
else if (linelen >= 2 else if (linelen >= 2
&& line[0] == 'O' && line[1] == 'K' && line[0] == 'O' && line[1] == 'K'
&& (line[2] == '\0' || line[2] == ' ')) && (line[2] == '\0' || line[2] == ' '))
@ -2121,11 +2135,11 @@ read_and_print_response (assuan_context_t ctx, int withhash, int *r_goterr)
} }
*r_goterr = 1; *r_goterr = 1;
return 0; return 0;
} }
else if (linelen >= 7 else if (linelen >= 7
&& line[0] == 'I' && line[1] == 'N' && line[2] == 'Q' && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
&& line[3] == 'U' && line[4] == 'I' && line[5] == 'R' && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
&& line[6] == 'E' && line[6] == 'E'
&& (line[7] == '\0' || line[7] == ' ')) && (line[7] == '\0' || line[7] == ' '))
{ {
if (!current_datasink || current_datasink != stdout) if (!current_datasink || current_datasink != stdout)