Line data Source code
1 : /* gpg-connect-agent.c - Tool to connect to the agent.
2 : * Copyright (C) 2005, 2007, 2008, 2010 Free Software Foundation, Inc.
3 : * Copyright (C) 2014 Werner Koch
4 : *
5 : * This file is part of GnuPG.
6 : *
7 : * GnuPG is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU General Public License as published by
9 : * the Free Software Foundation; either version 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * GnuPG is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License
18 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <config.h>
22 :
23 : #include <stdio.h>
24 : #include <stdlib.h>
25 : #include <string.h>
26 : #include <errno.h>
27 : #include <ctype.h>
28 : #include <assuan.h>
29 : #include <unistd.h>
30 : #include <assert.h>
31 :
32 : #include "i18n.h"
33 : #include "../common/util.h"
34 : #include "../common/asshelp.h"
35 : #include "../common/sysutils.h"
36 : #include "../common/membuf.h"
37 : #include "../common/ttyio.h"
38 : #ifdef HAVE_W32_SYSTEM
39 : # include "../common/exechelp.h"
40 : #endif
41 : #include "../common/init.h"
42 :
43 :
44 : #define CONTROL_D ('D' - 'A' + 1)
45 : #define octdigitp(p) (*(p) >= '0' && *(p) <= '7')
46 :
47 : /* Constants to identify the commands and options. */
48 : enum cmd_and_opt_values
49 : {
50 : aNull = 0,
51 : oQuiet = 'q',
52 : oVerbose = 'v',
53 : oRawSocket = 'S',
54 : oTcpSocket = 'T',
55 : oExec = 'E',
56 : oRun = 'r',
57 : oSubst = 's',
58 :
59 : oNoVerbose = 500,
60 : oHomedir,
61 : oAgentProgram,
62 : oDirmngrProgram,
63 : oHex,
64 : oDecode,
65 : oNoExtConnect,
66 : oDirmngr,
67 : oUIServer,
68 : oNoAutostart,
69 :
70 : };
71 :
72 :
73 : /* The list of commands and options. */
74 : static ARGPARSE_OPTS opts[] = {
75 : ARGPARSE_group (301, N_("@\nOptions:\n ")),
76 :
77 : ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
78 : ARGPARSE_s_n (oQuiet, "quiet", N_("quiet")),
79 : ARGPARSE_s_n (oHex, "hex", N_("print data out hex encoded")),
80 : ARGPARSE_s_n (oDecode,"decode", N_("decode received data lines")),
81 : ARGPARSE_s_n (oDirmngr,"dirmngr", N_("connect to the dirmngr")),
82 : ARGPARSE_s_n (oUIServer, "uiserver", "@"),
83 : ARGPARSE_s_s (oRawSocket, "raw-socket",
84 : N_("|NAME|connect to Assuan socket NAME")),
85 : ARGPARSE_s_s (oTcpSocket, "tcp-socket",
86 : N_("|ADDR|connect to Assuan server at ADDR")),
87 : ARGPARSE_s_n (oExec, "exec",
88 : N_("run the Assuan server given on the command line")),
89 : ARGPARSE_s_n (oNoExtConnect, "no-ext-connect",
90 : N_("do not use extended connect mode")),
91 : ARGPARSE_s_s (oRun, "run",
92 : N_("|FILE|run commands from FILE on startup")),
93 : ARGPARSE_s_n (oSubst, "subst", N_("run /subst on startup")),
94 :
95 : ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
96 : ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"),
97 : ARGPARSE_s_s (oHomedir, "homedir", "@" ),
98 : ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
99 : ARGPARSE_s_s (oDirmngrProgram, "dirmngr-program", "@"),
100 :
101 : ARGPARSE_end ()
102 : };
103 :
104 :
105 : /* We keep all global options in the structure OPT. */
106 : struct
107 : {
108 : int verbose; /* Verbosity level. */
109 : int quiet; /* Be extra quiet. */
110 : int autostart; /* Start the server if not running. */
111 : const char *homedir; /* Configuration directory name */
112 : const char *agent_program; /* Value of --agent-program. */
113 : const char *dirmngr_program; /* Value of --dirmngr-program. */
114 : int hex; /* Print data lines in hex format. */
115 : int decode; /* Decode received data lines. */
116 : int use_dirmngr; /* Use the dirmngr and not gpg-agent. */
117 : int use_uiserver; /* Use the standard UI server. */
118 : const char *raw_socket; /* Name of socket to connect in raw mode. */
119 : const char *tcp_socket; /* Name of server to connect in tcp mode. */
120 : int exec; /* Run the pgm given on the command line. */
121 : unsigned int connect_flags; /* Flags used for connecting. */
122 : int enable_varsubst; /* Set if variable substitution is enabled. */
123 : int trim_leading_spaces;
124 : } opt;
125 :
126 :
127 :
128 : /* Definitions for /definq commands and a global linked list with all
129 : the definitions. */
130 : struct definq_s
131 : {
132 : struct definq_s *next;
133 : char *name; /* Name of inquiry or NULL for any name. */
134 : int is_var; /* True if FILE is a variable name. */
135 : int is_prog; /* True if FILE is a program to run. */
136 : char file[1]; /* Name of file or program. */
137 : };
138 : typedef struct definq_s *definq_t;
139 :
140 : static definq_t definq_list;
141 : static definq_t *definq_list_tail = &definq_list;
142 :
143 :
144 : /* Variable definitions and glovbal table. */
145 : struct variable_s
146 : {
147 : struct variable_s *next;
148 : char *value; /* Malloced value - always a string. */
149 : char name[1]; /* Name of the variable. */
150 : };
151 : typedef struct variable_s *variable_t;
152 :
153 : static variable_t variable_table;
154 :
155 :
156 : /* To implement loops we store entire lines in a linked list. */
157 : struct loopline_s
158 : {
159 : struct loopline_s *next;
160 : char line[1];
161 : };
162 : typedef struct loopline_s *loopline_t;
163 :
164 :
165 : /* This is used to store the pid of the server. */
166 : static pid_t server_pid = (pid_t)(-1);
167 :
168 : /* The current datasink file or NULL. */
169 : static FILE *current_datasink;
170 :
171 : /* A list of open file descriptors. */
172 : static struct
173 : {
174 : int inuse;
175 : #ifdef HAVE_W32_SYSTEM
176 : HANDLE handle;
177 : #endif
178 : } open_fd_table[256];
179 :
180 :
181 : /*-- local prototypes --*/
182 : static char *substitute_line_copy (const char *buffer);
183 : static int read_and_print_response (assuan_context_t ctx, int withhash,
184 : int *r_goterr);
185 : static assuan_context_t start_agent (void);
186 :
187 :
188 :
189 :
190 : /* Print usage information and and provide strings for help. */
191 : static const char *
192 0 : my_strusage( int level )
193 : {
194 : const char *p;
195 :
196 0 : switch (level)
197 : {
198 0 : case 11: p = "@GPG@-connect-agent (@GNUPG@)";
199 0 : break;
200 0 : case 13: p = VERSION; break;
201 0 : case 17: p = PRINTABLE_OS_NAME; break;
202 0 : case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
203 :
204 : case 1:
205 0 : case 40: p = _("Usage: @GPG@-connect-agent [options] (-h for help)");
206 0 : break;
207 : case 41:
208 0 : p = _("Syntax: @GPG@-connect-agent [options]\n"
209 : "Connect to a running agent and send commands\n");
210 0 : break;
211 0 : case 31: p = "\nHome: "; break;
212 0 : case 32: p = opt.homedir; break;
213 0 : case 33: p = "\n"; break;
214 :
215 0 : default: p = NULL; break;
216 : }
217 0 : return p;
218 : }
219 :
220 :
221 : /* Unescape STRING and returned the malloced result. The surrounding
222 : quotes must already be removed from STRING. */
223 : static char *
224 0 : unescape_string (const char *string)
225 : {
226 : const unsigned char *s;
227 : int esc;
228 : size_t n;
229 : char *buffer;
230 : unsigned char *d;
231 :
232 0 : n = 0;
233 0 : for (s = (const unsigned char*)string, esc=0; *s; s++)
234 : {
235 0 : if (esc)
236 : {
237 0 : switch (*s)
238 : {
239 : case 'b':
240 : case 't':
241 : case 'v':
242 : case 'n':
243 : case 'f':
244 : case 'r':
245 : case '"':
246 : case '\'':
247 0 : case '\\': n++; break;
248 : case 'x':
249 0 : if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
250 0 : n++;
251 0 : break;
252 :
253 : default:
254 0 : if (s[1] && s[2]
255 0 : && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
256 0 : n++;
257 0 : break;
258 : }
259 0 : esc = 0;
260 : }
261 0 : else if (*s == '\\')
262 0 : esc = 1;
263 : else
264 0 : n++;
265 : }
266 :
267 0 : buffer = xmalloc (n+1);
268 0 : d = (unsigned char*)buffer;
269 0 : for (s = (const unsigned char*)string, esc=0; *s; s++)
270 : {
271 0 : if (esc)
272 : {
273 0 : switch (*s)
274 : {
275 0 : case 'b': *d++ = '\b'; break;
276 0 : case 't': *d++ = '\t'; break;
277 0 : case 'v': *d++ = '\v'; break;
278 0 : case 'n': *d++ = '\n'; break;
279 0 : case 'f': *d++ = '\f'; break;
280 0 : case 'r': *d++ = '\r'; break;
281 0 : case '"': *d++ = '\"'; break;
282 0 : case '\'': *d++ = '\''; break;
283 0 : case '\\': *d++ = '\\'; break;
284 : case 'x':
285 0 : if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
286 : {
287 0 : s++;
288 0 : *d++ = xtoi_2 (s);
289 0 : s++;
290 : }
291 0 : break;
292 :
293 : default:
294 0 : if (s[1] && s[2]
295 0 : && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
296 : {
297 0 : *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2);
298 0 : s += 2;
299 : }
300 0 : break;
301 : }
302 0 : esc = 0;
303 : }
304 0 : else if (*s == '\\')
305 0 : esc = 1;
306 : else
307 0 : *d++ = *s;
308 : }
309 0 : *d = 0;
310 0 : return buffer;
311 : }
312 :
313 :
314 : /* Do the percent unescaping and return a newly malloced string.
315 : If WITH_PLUS is set '+' characters will be changed to space. */
316 : static char *
317 0 : unpercent_string (const char *string, int with_plus)
318 : {
319 : const unsigned char *s;
320 : unsigned char *buffer, *p;
321 : size_t n;
322 :
323 0 : n = 0;
324 0 : for (s=(const unsigned char *)string; *s; s++)
325 : {
326 0 : if (*s == '%' && s[1] && s[2])
327 : {
328 0 : s++;
329 0 : n++;
330 0 : s++;
331 : }
332 0 : else if (with_plus && *s == '+')
333 0 : n++;
334 : else
335 0 : n++;
336 : }
337 :
338 0 : buffer = xmalloc (n+1);
339 0 : p = buffer;
340 0 : for (s=(const unsigned char *)string; *s; s++)
341 : {
342 0 : if (*s == '%' && s[1] && s[2])
343 : {
344 0 : s++;
345 0 : *p++ = xtoi_2 (s);
346 0 : s++;
347 : }
348 0 : else if (with_plus && *s == '+')
349 0 : *p++ = ' ';
350 : else
351 0 : *p++ = *s;
352 : }
353 0 : *p = 0;
354 0 : return (char*)buffer;
355 : }
356 :
357 :
358 :
359 :
360 :
361 : static const char *
362 1 : set_var (const char *name, const char *value)
363 : {
364 : variable_t var;
365 :
366 1 : for (var = variable_table; var; var = var->next)
367 0 : if (!strcmp (var->name, name))
368 0 : break;
369 1 : if (!var)
370 : {
371 1 : var = xmalloc (sizeof *var + strlen (name));
372 1 : var->value = NULL;
373 1 : strcpy (var->name, name);
374 1 : var->next = variable_table;
375 1 : variable_table = var;
376 : }
377 1 : xfree (var->value);
378 1 : var->value = value? xstrdup (value) : NULL;
379 1 : return var->value;
380 : }
381 :
382 :
383 : static void
384 1 : set_int_var (const char *name, int value)
385 : {
386 : char numbuf[35];
387 :
388 1 : snprintf (numbuf, sizeof numbuf, "%d", value);
389 1 : set_var (name, numbuf);
390 1 : }
391 :
392 :
393 : /* Return the value of a variable. That value is valid until a
394 : variable of the name is changed. Return NULL if not found. Note
395 : that envvars are copied to our variable list at the first access
396 : and not at oprogram start. */
397 : static const char *
398 0 : get_var (const char *name)
399 : {
400 : variable_t var;
401 : const char *s;
402 :
403 0 : if (!*name)
404 0 : return "";
405 0 : for (var = variable_table; var; var = var->next)
406 0 : if (!strcmp (var->name, name))
407 0 : break;
408 0 : if (!var && (s = getenv (name)))
409 0 : return set_var (name, s);
410 0 : if (!var || !var->value)
411 0 : return NULL;
412 0 : return var->value;
413 : }
414 :
415 :
416 : /* Perform some simple arithmentic operations. Caller must release
417 : the return value. On error the return value is NULL. */
418 : static char *
419 0 : arithmetic_op (int operator, const char *operands)
420 : {
421 : long result, value;
422 : char numbuf[35];
423 :
424 0 : while ( spacep (operands) )
425 0 : operands++;
426 0 : if (!*operands)
427 0 : return NULL;
428 0 : result = strtol (operands, NULL, 0);
429 0 : while (*operands && !spacep (operands) )
430 0 : operands++;
431 0 : if (operator == '!')
432 0 : result = !result;
433 :
434 0 : while (*operands)
435 : {
436 0 : while ( spacep (operands) )
437 0 : operands++;
438 0 : if (!*operands)
439 0 : break;
440 0 : value = strtol (operands, NULL, 0);
441 0 : while (*operands && !spacep (operands) )
442 0 : operands++;
443 0 : switch (operator)
444 : {
445 0 : case '+': result += value; break;
446 0 : case '-': result -= value; break;
447 0 : case '*': result *= value; break;
448 : case '/':
449 0 : if (!value)
450 0 : return NULL;
451 0 : result /= value;
452 0 : break;
453 : case '%':
454 0 : if (!value)
455 0 : return NULL;
456 0 : result %= value;
457 0 : break;
458 0 : case '!': result = !value; break;
459 0 : case '|': result = result || value; break;
460 0 : case '&': result = result && value; break;
461 : default:
462 0 : log_error ("unknown arithmetic operator '%c'\n", operator);
463 0 : return NULL;
464 : }
465 : }
466 0 : snprintf (numbuf, sizeof numbuf, "%ld", result);
467 0 : return xstrdup (numbuf);
468 : }
469 :
470 :
471 :
472 : /* Extended version of get_var. This returns a malloced string and
473 : understand the function syntax: "func args".
474 :
475 : Defined functions are
476 :
477 : get - Return a value described by the next argument:
478 : cwd - The current working directory.
479 : homedir - The gnupg homedir.
480 : sysconfdir - GnuPG's system configuration directory.
481 : bindir - GnuPG's binary directory.
482 : libdir - GnuPG's library directory.
483 : libexecdir - GnuPG's library directory for executable files.
484 : datadir - GnuPG's data directory.
485 : serverpid - The PID of the current server.
486 :
487 : unescape ARGS
488 : Remove C-style escapes from string. Note that "\0" and
489 : "\x00" terminate the string implictly. Use "\x7d" to
490 : represent the closing brace. The args start right after
491 : the first space after the function name.
492 :
493 : unpercent ARGS
494 : unpercent+ ARGS
495 : Remove percent style ecaping from string. Note that "%00
496 : terminates the string implicitly. Use "%7d" to represetn
497 : the closing brace. The args start right after the first
498 : space after the function name. "unpercent+" also maps '+'
499 : to space.
500 :
501 : percent ARGS
502 : percent+ ARGS
503 : Escape the args using the percent style. Tabs, formfeeds,
504 : linefeeds, carriage return, and the plus sign are also
505 : escaped. "percent+" also maps spaces to plus characters.
506 :
507 : errcode ARG
508 : Assuming ARG is an integer, return the gpg-error code.
509 :
510 : errsource ARG
511 : Assuming ARG is an integer, return the gpg-error source.
512 :
513 : errstring ARG
514 : Assuming ARG is an integer return a formatted fpf error string.
515 :
516 :
517 : Example: get_var_ext ("get sysconfdir") -> "/etc/gnupg"
518 :
519 : */
520 : static char *
521 0 : get_var_ext (const char *name)
522 : {
523 : static int recursion_count;
524 : const char *s;
525 : char *result;
526 : char *p;
527 0 : char *free_me = NULL;
528 : int intvalue;
529 :
530 0 : if (recursion_count > 50)
531 : {
532 0 : log_error ("variables nested too deeply\n");
533 0 : return NULL;
534 : }
535 :
536 0 : recursion_count++;
537 0 : free_me = opt.enable_varsubst? substitute_line_copy (name) : NULL;
538 0 : if (free_me)
539 0 : name = free_me;
540 0 : for (s=name; *s && !spacep (s); s++)
541 : ;
542 0 : if (!*s)
543 : {
544 0 : s = get_var (name);
545 0 : result = s? xstrdup (s): NULL;
546 : }
547 0 : else if ( (s - name) == 3 && !strncmp (name, "get", 3))
548 : {
549 0 : while ( spacep (s) )
550 0 : s++;
551 0 : if (!strcmp (s, "cwd"))
552 : {
553 0 : result = gnupg_getcwd ();
554 0 : if (!result)
555 0 : log_error ("getcwd failed: %s\n", strerror (errno));
556 : }
557 0 : else if (!strcmp (s, "homedir"))
558 0 : result = make_filename (opt.homedir, NULL);
559 0 : else if (!strcmp (s, "sysconfdir"))
560 0 : result = xstrdup (gnupg_sysconfdir ());
561 0 : else if (!strcmp (s, "bindir"))
562 0 : result = xstrdup (gnupg_bindir ());
563 0 : else if (!strcmp (s, "libdir"))
564 0 : result = xstrdup (gnupg_libdir ());
565 0 : else if (!strcmp (s, "libexecdir"))
566 0 : result = xstrdup (gnupg_libexecdir ());
567 0 : else if (!strcmp (s, "datadir"))
568 0 : result = xstrdup (gnupg_datadir ());
569 0 : else if (!strcmp (s, "serverpid"))
570 0 : result = xasprintf ("%d", (int)server_pid);
571 : else
572 : {
573 0 : log_error ("invalid argument '%s' for variable function 'get'\n", s);
574 0 : log_info ("valid are: cwd, "
575 : "{home,bin,lib,libexec,data}dir, serverpid\n");
576 0 : result = NULL;
577 : }
578 : }
579 0 : else if ( (s - name) == 8 && !strncmp (name, "unescape", 8))
580 : {
581 0 : s++;
582 0 : result = unescape_string (s);
583 : }
584 0 : else if ( (s - name) == 9 && !strncmp (name, "unpercent", 9))
585 : {
586 0 : s++;
587 0 : result = unpercent_string (s, 0);
588 : }
589 0 : else if ( (s - name) == 10 && !strncmp (name, "unpercent+", 10))
590 : {
591 0 : s++;
592 0 : result = unpercent_string (s, 1);
593 : }
594 0 : else if ( (s - name) == 7 && !strncmp (name, "percent", 7))
595 : {
596 0 : s++;
597 0 : result = percent_escape (s, "+\t\r\n\f\v");
598 : }
599 0 : else if ( (s - name) == 8 && !strncmp (name, "percent+", 8))
600 : {
601 0 : s++;
602 0 : result = percent_escape (s, "+\t\r\n\f\v");
603 0 : for (p=result; *p; p++)
604 0 : if (*p == ' ')
605 0 : *p = '+';
606 : }
607 0 : else if ( (s - name) == 7 && !strncmp (name, "errcode", 7))
608 : {
609 0 : s++;
610 0 : intvalue = (int)strtol (s, NULL, 0);
611 0 : result = xasprintf ("%d", gpg_err_code (intvalue));
612 : }
613 0 : else if ( (s - name) == 9 && !strncmp (name, "errsource", 9))
614 : {
615 0 : s++;
616 0 : intvalue = (int)strtol (s, NULL, 0);
617 0 : result = xasprintf ("%d", gpg_err_source (intvalue));
618 : }
619 0 : else if ( (s - name) == 9 && !strncmp (name, "errstring", 9))
620 : {
621 0 : s++;
622 0 : intvalue = (int)strtol (s, NULL, 0);
623 0 : result = xasprintf ("%s <%s>",
624 : gpg_strerror (intvalue), gpg_strsource (intvalue));
625 : }
626 0 : else if ( (s - name) == 1 && strchr ("+-*/%!|&", *name))
627 : {
628 0 : result = arithmetic_op (*name, s+1);
629 : }
630 : else
631 : {
632 0 : log_error ("unknown variable function '%.*s'\n", (int)(s-name), name);
633 0 : result = NULL;
634 : }
635 :
636 0 : xfree (free_me);
637 0 : recursion_count--;
638 0 : return result;
639 : }
640 :
641 :
642 : /* Substitute variables in LINE and return a new allocated buffer if
643 : required. The function might modify LINE if the expanded version
644 : fits into it. */
645 : static char *
646 0 : substitute_line (char *buffer)
647 : {
648 0 : char *line = buffer;
649 : char *p, *pend;
650 : const char *value;
651 : size_t valuelen, n;
652 0 : char *result = NULL;
653 0 : char *freeme = NULL;
654 :
655 0 : while (*line)
656 : {
657 0 : p = strchr (line, '$');
658 0 : if (!p)
659 0 : return result; /* No more variables. */
660 :
661 0 : if (p[1] == '$') /* Escaped dollar sign. */
662 : {
663 0 : memmove (p, p+1, strlen (p+1)+1);
664 0 : line = p + 1;
665 0 : continue;
666 : }
667 0 : if (p[1] == '{')
668 : {
669 0 : int count = 0;
670 :
671 0 : for (pend=p+2; *pend; pend++)
672 : {
673 0 : if (*pend == '{')
674 0 : count++;
675 0 : else if (*pend == '}')
676 : {
677 0 : if (--count < 0)
678 0 : break;
679 : }
680 : }
681 0 : if (!*pend)
682 0 : return result; /* Unclosed - don't substitute. */
683 : }
684 : else
685 : {
686 0 : for (pend=p+1; *pend && !spacep (pend) && *pend != '$' ; pend++)
687 : ;
688 : }
689 0 : if (p[1] == '{' && *pend == '}')
690 0 : {
691 0 : int save = *pend;
692 0 : *pend = 0;
693 0 : freeme = get_var_ext (p+2);
694 0 : value = freeme;
695 0 : *pend++ = save;
696 : }
697 0 : else if (*pend)
698 : {
699 0 : int save = *pend;
700 0 : *pend = 0;
701 0 : value = get_var (p+1);
702 0 : *pend = save;
703 : }
704 : else
705 0 : value = get_var (p+1);
706 0 : if (!value)
707 0 : value = "";
708 0 : valuelen = strlen (value);
709 0 : if (valuelen <= pend - p)
710 : {
711 0 : memcpy (p, value, valuelen);
712 0 : p += valuelen;
713 0 : n = pend - p;
714 0 : if (n)
715 0 : memmove (p, p+n, strlen (p+n)+1);
716 0 : line = p;
717 : }
718 : else
719 : {
720 0 : char *src = result? result : buffer;
721 : char *dst;
722 :
723 0 : dst = xmalloc (strlen (src) + valuelen + 1);
724 0 : n = p - src;
725 0 : memcpy (dst, src, n);
726 0 : memcpy (dst + n, value, valuelen);
727 0 : n += valuelen;
728 0 : strcpy (dst + n, pend);
729 0 : line = dst + n;
730 0 : xfree (result);
731 0 : result = dst;
732 : }
733 0 : xfree (freeme);
734 0 : freeme = NULL;
735 : }
736 0 : return result;
737 : }
738 :
739 : /* Same as substitute_line but do not modify BUFFER. */
740 : static char *
741 0 : substitute_line_copy (const char *buffer)
742 : {
743 : char *result, *p;
744 :
745 0 : p = xstrdup (buffer?buffer:"");
746 0 : result = substitute_line (p);
747 0 : if (!result)
748 0 : result = p;
749 : else
750 0 : xfree (p);
751 0 : return result;
752 : }
753 :
754 :
755 : static void
756 0 : assign_variable (char *line, int syslet)
757 : {
758 : char *name, *p, *tmp, *free_me, *buffer;
759 :
760 : /* Get the name. */
761 0 : name = line;
762 0 : for (p=name; *p && !spacep (p); p++)
763 : ;
764 0 : if (*p)
765 0 : *p++ = 0;
766 0 : while (spacep (p))
767 0 : p++;
768 :
769 0 : if (!*p)
770 0 : set_var (name, NULL); /* Remove variable. */
771 0 : else if (syslet)
772 : {
773 0 : free_me = opt.enable_varsubst? substitute_line_copy (p) : NULL;
774 0 : if (free_me)
775 0 : p = free_me;
776 0 : buffer = xmalloc (4 + strlen (p) + 1);
777 0 : strcpy (stpcpy (buffer, "get "), p);
778 0 : tmp = get_var_ext (buffer);
779 0 : xfree (buffer);
780 0 : set_var (name, tmp);
781 0 : xfree (tmp);
782 0 : xfree (free_me);
783 : }
784 : else
785 : {
786 0 : tmp = opt.enable_varsubst? substitute_line_copy (p) : NULL;
787 0 : if (tmp)
788 : {
789 0 : set_var (name, tmp);
790 0 : xfree (tmp);
791 : }
792 : else
793 0 : set_var (name, p);
794 : }
795 0 : }
796 :
797 :
798 : static void
799 0 : show_variables (void)
800 : {
801 : variable_t var;
802 :
803 0 : for (var = variable_table; var; var = var->next)
804 0 : if (var->value)
805 0 : printf ("%-20s %s\n", var->name, var->value);
806 0 : }
807 :
808 :
809 : /* Store an inquire response pattern. Note, that this function may
810 : change the content of LINE. We assume that leading white spaces
811 : are already removed. */
812 : static void
813 0 : add_definq (char *line, int is_var, int is_prog)
814 : {
815 : definq_t d;
816 : char *name, *p;
817 :
818 : /* Get name. */
819 0 : name = line;
820 0 : for (p=name; *p && !spacep (p); p++)
821 : ;
822 0 : if (*p)
823 0 : *p++ = 0;
824 0 : while (spacep (p))
825 0 : p++;
826 :
827 0 : d = xmalloc (sizeof *d + strlen (p) );
828 0 : strcpy (d->file, p);
829 0 : d->is_var = is_var;
830 0 : d->is_prog = is_prog;
831 0 : if ( !strcmp (name, "*"))
832 0 : d->name = NULL;
833 : else
834 0 : d->name = xstrdup (name);
835 :
836 0 : d->next = NULL;
837 0 : *definq_list_tail = d;
838 0 : definq_list_tail = &d->next;
839 0 : }
840 :
841 :
842 : /* Show all inquiry defintions. */
843 : static void
844 0 : show_definq (void)
845 : {
846 : definq_t d;
847 :
848 0 : for (d=definq_list; d; d = d->next)
849 0 : if (d->name)
850 0 : printf ("%-20s %c %s\n",
851 0 : d->name, d->is_var? 'v' : d->is_prog? 'p':'f', d->file);
852 0 : for (d=definq_list; d; d = d->next)
853 0 : if (!d->name)
854 0 : printf ("%-20s %c %s\n", "*",
855 0 : d->is_var? 'v': d->is_prog? 'p':'f', d->file);
856 0 : }
857 :
858 :
859 : /* Clear all inquiry definitions. */
860 : static void
861 0 : clear_definq (void)
862 : {
863 0 : while (definq_list)
864 : {
865 0 : definq_t tmp = definq_list->next;
866 0 : xfree (definq_list->name);
867 0 : xfree (definq_list);
868 0 : definq_list = tmp;
869 : }
870 0 : definq_list_tail = &definq_list;
871 0 : }
872 :
873 :
874 : static void
875 0 : do_sendfd (assuan_context_t ctx, char *line)
876 : {
877 : FILE *fp;
878 : char *name, *mode, *p;
879 : int rc, fd;
880 :
881 : /* Get file name. */
882 0 : name = line;
883 0 : for (p=name; *p && !spacep (p); p++)
884 : ;
885 0 : if (*p)
886 0 : *p++ = 0;
887 0 : while (spacep (p))
888 0 : p++;
889 :
890 : /* Get mode. */
891 0 : mode = p;
892 0 : if (!*mode)
893 0 : mode = "r";
894 : else
895 : {
896 0 : for (p=mode; *p && !spacep (p); p++)
897 : ;
898 0 : if (*p)
899 0 : *p++ = 0;
900 : }
901 :
902 : /* Open and send. */
903 0 : fp = fopen (name, mode);
904 0 : if (!fp)
905 : {
906 0 : log_error ("can't open '%s' in \"%s\" mode: %s\n",
907 0 : name, mode, strerror (errno));
908 0 : return;
909 : }
910 0 : fd = fileno (fp);
911 :
912 0 : if (opt.verbose)
913 0 : log_error ("file '%s' opened in \"%s\" mode, fd=%d\n",
914 : name, mode, fd);
915 :
916 0 : rc = assuan_sendfd (ctx, INT2FD (fd) );
917 0 : if (rc)
918 0 : log_error ("sending descriptor %d failed: %s\n", fd, gpg_strerror (rc));
919 0 : fclose (fp);
920 : }
921 :
922 :
923 : static void
924 0 : do_recvfd (assuan_context_t ctx, char *line)
925 : {
926 : (void)ctx;
927 : (void)line;
928 0 : log_info ("This command has not yet been implemented\n");
929 0 : }
930 :
931 :
932 : static void
933 0 : do_open (char *line)
934 : {
935 : FILE *fp;
936 : char *varname, *name, *mode, *p;
937 : int fd;
938 :
939 : #ifdef HAVE_W32_SYSTEM
940 : if (server_pid == (pid_t)(-1))
941 : {
942 : log_error ("the pid of the server is unknown\n");
943 : log_info ("use command \"/serverpid\" first\n");
944 : return;
945 : }
946 : #endif
947 :
948 : /* Get variable name. */
949 0 : varname = line;
950 0 : for (p=varname; *p && !spacep (p); p++)
951 : ;
952 0 : if (*p)
953 0 : *p++ = 0;
954 0 : while (spacep (p))
955 0 : p++;
956 :
957 : /* Get file name. */
958 0 : name = p;
959 0 : for (p=name; *p && !spacep (p); p++)
960 : ;
961 0 : if (*p)
962 0 : *p++ = 0;
963 0 : while (spacep (p))
964 0 : p++;
965 :
966 : /* Get mode. */
967 0 : mode = p;
968 0 : if (!*mode)
969 0 : mode = "r";
970 : else
971 : {
972 0 : for (p=mode; *p && !spacep (p); p++)
973 : ;
974 0 : if (*p)
975 0 : *p++ = 0;
976 : }
977 :
978 : /* Open and send. */
979 0 : fp = fopen (name, mode);
980 0 : if (!fp)
981 : {
982 0 : log_error ("can't open '%s' in \"%s\" mode: %s\n",
983 0 : name, mode, strerror (errno));
984 0 : return;
985 : }
986 0 : fd = fileno (fp);
987 0 : if (fd >= 0 && fd < DIM (open_fd_table))
988 : {
989 0 : open_fd_table[fd].inuse = 1;
990 : #ifdef HAVE_W32CE_SYSTEM
991 : # warning fixme: implement our pipe emulation.
992 : #endif
993 : #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
994 : {
995 : HANDLE prochandle, handle, newhandle;
996 :
997 : handle = (void*)_get_osfhandle (fd);
998 :
999 : prochandle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, server_pid);
1000 : if (!prochandle)
1001 : {
1002 : log_error ("failed to open the server process\n");
1003 : close (fd);
1004 : return;
1005 : }
1006 :
1007 : if (!DuplicateHandle (GetCurrentProcess(), handle,
1008 : prochandle, &newhandle, 0,
1009 : TRUE, DUPLICATE_SAME_ACCESS ))
1010 : {
1011 : log_error ("failed to duplicate the handle\n");
1012 : close (fd);
1013 : CloseHandle (prochandle);
1014 : return;
1015 : }
1016 : CloseHandle (prochandle);
1017 : open_fd_table[fd].handle = newhandle;
1018 : }
1019 : if (opt.verbose)
1020 : log_info ("file '%s' opened in \"%s\" mode, fd=%d (libc=%d)\n",
1021 : name, mode, (int)open_fd_table[fd].handle, fd);
1022 : set_int_var (varname, (int)open_fd_table[fd].handle);
1023 : #else
1024 0 : if (opt.verbose)
1025 0 : log_info ("file '%s' opened in \"%s\" mode, fd=%d\n",
1026 : name, mode, fd);
1027 0 : set_int_var (varname, fd);
1028 : #endif
1029 : }
1030 : else
1031 : {
1032 0 : log_error ("can't put fd %d into table\n", fd);
1033 0 : close (fd);
1034 : }
1035 : }
1036 :
1037 :
1038 : static void
1039 0 : do_close (char *line)
1040 : {
1041 0 : int fd = atoi (line);
1042 :
1043 : #ifdef HAVE_W32_SYSTEM
1044 : int i;
1045 :
1046 : for (i=0; i < DIM (open_fd_table); i++)
1047 : if ( open_fd_table[i].inuse && open_fd_table[i].handle == (void*)fd)
1048 : break;
1049 : if (i < DIM (open_fd_table))
1050 : fd = i;
1051 : else
1052 : {
1053 : log_error ("given fd (system handle) has not been opened\n");
1054 : return;
1055 : }
1056 : #endif
1057 :
1058 0 : if (fd < 0 || fd >= DIM (open_fd_table))
1059 : {
1060 0 : log_error ("invalid fd\n");
1061 0 : return;
1062 : }
1063 :
1064 0 : if (!open_fd_table[fd].inuse)
1065 : {
1066 0 : log_error ("given fd has not been opened\n");
1067 0 : return;
1068 : }
1069 : #ifdef HAVE_W32_SYSTEM
1070 : CloseHandle (open_fd_table[fd].handle); /* Close duped handle. */
1071 : #endif
1072 0 : close (fd);
1073 0 : open_fd_table[fd].inuse = 0;
1074 : }
1075 :
1076 :
1077 : static void
1078 0 : do_showopen (void)
1079 : {
1080 : int i;
1081 :
1082 0 : for (i=0; i < DIM (open_fd_table); i++)
1083 0 : if (open_fd_table[i].inuse)
1084 : {
1085 : #ifdef HAVE_W32_SYSTEM
1086 : printf ("%-15d (libc=%d)\n", (int)open_fd_table[i].handle, i);
1087 : #else
1088 0 : printf ("%-15d\n", i);
1089 : #endif
1090 : }
1091 0 : }
1092 :
1093 :
1094 :
1095 : static gpg_error_t
1096 0 : getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
1097 : {
1098 0 : membuf_t *mb = opaque;
1099 0 : put_membuf (mb, buffer, length);
1100 0 : return 0;
1101 : }
1102 :
1103 : /* Get the pid of the server and store it locally. */
1104 : static void
1105 0 : do_serverpid (assuan_context_t ctx)
1106 : {
1107 : int rc;
1108 : membuf_t mb;
1109 : char *buffer;
1110 :
1111 0 : init_membuf (&mb, 100);
1112 0 : rc = assuan_transact (ctx, "GETINFO pid", getinfo_pid_cb, &mb,
1113 : NULL, NULL, NULL, NULL);
1114 0 : put_membuf (&mb, "", 1);
1115 0 : buffer = get_membuf (&mb, NULL);
1116 0 : if (rc || !buffer)
1117 0 : log_error ("command \"%s\" failed: %s\n",
1118 : "GETINFO pid", gpg_strerror (rc));
1119 : else
1120 : {
1121 0 : server_pid = (pid_t)strtoul (buffer, NULL, 10);
1122 0 : if (opt.verbose)
1123 0 : log_info ("server's PID is %lu\n", (unsigned long)server_pid);
1124 : }
1125 0 : xfree (buffer);
1126 0 : }
1127 :
1128 :
1129 : /* Return true if the command is either "HELP" or "SCD HELP". */
1130 : static int
1131 1 : help_cmd_p (const char *line)
1132 : {
1133 1 : if (!ascii_strncasecmp (line, "SCD", 3)
1134 0 : && (spacep (line+3) || !line[3]))
1135 : {
1136 0 : for (line += 3; spacep (line); line++)
1137 : ;
1138 : }
1139 :
1140 2 : return (!ascii_strncasecmp (line, "HELP", 4)
1141 1 : && (spacep (line+4) || !line[4]));
1142 : }
1143 :
1144 :
1145 : /* gpg-connect-agent's entry point. */
1146 : int
1147 2 : main (int argc, char **argv)
1148 : {
1149 : ARGPARSE_ARGS pargs;
1150 2 : int no_more_options = 0;
1151 : assuan_context_t ctx;
1152 : char *line, *p;
1153 : char *tmpline;
1154 : size_t linesize;
1155 : int rc;
1156 : int cmderr;
1157 2 : const char *opt_run = NULL;
1158 2 : FILE *script_fp = NULL;
1159 : int use_tty, keep_line;
1160 : struct {
1161 : int collecting;
1162 : loopline_t head;
1163 : loopline_t *tail;
1164 : loopline_t current;
1165 : unsigned int nestlevel;
1166 : int oneshot;
1167 : char *condition;
1168 : } loopstack[20];
1169 : int loopidx;
1170 2 : char **cmdline_commands = NULL;
1171 :
1172 2 : early_system_init ();
1173 2 : gnupg_rl_initialize ();
1174 2 : set_strusage (my_strusage);
1175 2 : log_set_prefix ("gpg-connect-agent", 1);
1176 :
1177 : /* Make sure that our subsystems are ready. */
1178 2 : i18n_init();
1179 2 : init_common_subsystems (&argc, &argv);
1180 :
1181 2 : assuan_set_gpg_err_source (0);
1182 :
1183 :
1184 2 : opt.homedir = default_homedir ();
1185 2 : opt.autostart = 1;
1186 2 : opt.connect_flags = 1;
1187 :
1188 : /* Parse the command line. */
1189 2 : pargs.argc = &argc;
1190 2 : pargs.argv = &argv;
1191 2 : pargs.flags = 1; /* Do not remove the args. */
1192 6 : while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
1193 : {
1194 2 : switch (pargs.r_opt)
1195 : {
1196 0 : case oQuiet: opt.quiet = 1; break;
1197 1 : case oVerbose: opt.verbose++; break;
1198 0 : case oNoVerbose: opt.verbose = 0; break;
1199 0 : case oHomedir: opt.homedir = pargs.r.ret_str; break;
1200 1 : case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
1201 0 : case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break;
1202 0 : case oNoAutostart: opt.autostart = 0; break;
1203 0 : case oHex: opt.hex = 1; break;
1204 0 : case oDecode: opt.decode = 1; break;
1205 0 : case oDirmngr: opt.use_dirmngr = 1; break;
1206 0 : case oUIServer: opt.use_uiserver = 1; break;
1207 0 : case oRawSocket: opt.raw_socket = pargs.r.ret_str; break;
1208 0 : case oTcpSocket: opt.tcp_socket = pargs.r.ret_str; break;
1209 0 : case oExec: opt.exec = 1; break;
1210 0 : case oNoExtConnect: opt.connect_flags &= ~(1); break;
1211 0 : case oRun: opt_run = pargs.r.ret_str; break;
1212 : case oSubst:
1213 0 : opt.enable_varsubst = 1;
1214 0 : opt.trim_leading_spaces = 1;
1215 0 : break;
1216 :
1217 0 : default: pargs.err = 2; break;
1218 : }
1219 : }
1220 :
1221 2 : if (log_get_errorcount (0))
1222 0 : exit (2);
1223 :
1224 : /* --uiserver is a shortcut for a specific raw socket. This comes
1225 : in particular handy on Windows. */
1226 2 : if (opt.use_uiserver)
1227 : {
1228 0 : opt.raw_socket = make_absfilename (opt.homedir, "S.uiserver", NULL);
1229 : }
1230 :
1231 : /* Print a warning if an argument looks like an option. */
1232 2 : if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
1233 : {
1234 : int i;
1235 :
1236 5 : for (i=0; i < argc; i++)
1237 3 : if (argv[i][0] == '-' && argv[i][1] == '-')
1238 0 : log_info (_("Note: '%s' is not considered an option\n"), argv[i]);
1239 : }
1240 :
1241 :
1242 2 : use_tty = (gnupg_isatty (fileno (stdin)) && gnupg_isatty (fileno (stdout)));
1243 :
1244 2 : if (opt.exec)
1245 : {
1246 0 : if (!argc)
1247 : {
1248 0 : log_error (_("option \"%s\" requires a program "
1249 : "and optional arguments\n"), "--exec" );
1250 0 : exit (1);
1251 : }
1252 : }
1253 2 : else if (argc)
1254 2 : cmdline_commands = argv;
1255 :
1256 2 : if (opt.exec && opt.raw_socket)
1257 : {
1258 0 : opt.raw_socket = NULL;
1259 0 : log_info (_("option \"%s\" ignored due to \"%s\"\n"),
1260 : "--raw-socket", "--exec");
1261 : }
1262 2 : if (opt.exec && opt.tcp_socket)
1263 : {
1264 0 : opt.tcp_socket = NULL;
1265 0 : log_info (_("option \"%s\" ignored due to \"%s\"\n"),
1266 : "--tcp-socket", "--exec");
1267 : }
1268 2 : if (opt.tcp_socket && opt.raw_socket)
1269 : {
1270 0 : opt.tcp_socket = NULL;
1271 0 : log_info (_("option \"%s\" ignored due to \"%s\"\n"),
1272 : "--tcp-socket", "--raw-socket");
1273 : }
1274 :
1275 2 : if (opt_run && !(script_fp = fopen (opt_run, "r")))
1276 : {
1277 0 : log_error ("cannot open run file '%s': %s\n",
1278 0 : opt_run, strerror (errno));
1279 0 : exit (1);
1280 : }
1281 :
1282 :
1283 2 : if (opt.exec)
1284 : {
1285 : assuan_fd_t no_close[3];
1286 :
1287 0 : no_close[0] = assuan_fd_from_posix_fd (es_fileno (es_stderr));
1288 0 : no_close[1] = assuan_fd_from_posix_fd (log_get_fd ());
1289 0 : no_close[2] = ASSUAN_INVALID_FD;
1290 :
1291 0 : rc = assuan_new (&ctx);
1292 0 : if (rc)
1293 : {
1294 0 : log_error ("assuan_new failed: %s\n", gpg_strerror (rc));
1295 0 : exit (1);
1296 : }
1297 :
1298 0 : rc = assuan_pipe_connect
1299 : (ctx, *argv, (const char **)argv, no_close, NULL, NULL,
1300 0 : (opt.connect_flags & 1) ? ASSUAN_PIPE_CONNECT_FDPASSING : 0);
1301 0 : if (rc)
1302 : {
1303 0 : log_error ("assuan_pipe_connect_ext failed: %s\n",
1304 : gpg_strerror (rc));
1305 0 : exit (1);
1306 : }
1307 :
1308 0 : if (opt.verbose)
1309 0 : log_info ("server '%s' started\n", *argv);
1310 :
1311 : }
1312 2 : else if (opt.raw_socket)
1313 : {
1314 0 : rc = assuan_new (&ctx);
1315 0 : if (rc)
1316 : {
1317 0 : log_error ("assuan_new failed: %s\n", gpg_strerror (rc));
1318 0 : exit (1);
1319 : }
1320 :
1321 0 : rc = assuan_socket_connect
1322 : (ctx, opt.raw_socket, 0,
1323 0 : (opt.connect_flags & 1) ? ASSUAN_SOCKET_CONNECT_FDPASSING : 0);
1324 0 : if (rc)
1325 : {
1326 0 : log_error ("can't connect to socket '%s': %s\n",
1327 : opt.raw_socket, gpg_strerror (rc));
1328 0 : exit (1);
1329 : }
1330 :
1331 0 : if (opt.verbose)
1332 0 : log_info ("connection to socket '%s' established\n", opt.raw_socket);
1333 : }
1334 2 : else if (opt.tcp_socket)
1335 : {
1336 : char *url;
1337 :
1338 0 : url = xstrconcat ("assuan://", opt.tcp_socket, NULL);
1339 :
1340 0 : rc = assuan_new (&ctx);
1341 0 : if (rc)
1342 : {
1343 0 : log_error ("assuan_new failed: %s\n", gpg_strerror (rc));
1344 0 : exit (1);
1345 : }
1346 :
1347 0 : rc = assuan_socket_connect (ctx, opt.tcp_socket, 0, 0);
1348 0 : if (rc)
1349 : {
1350 0 : log_error ("can't connect to server '%s': %s\n",
1351 : opt.tcp_socket, gpg_strerror (rc));
1352 0 : exit (1);
1353 : }
1354 :
1355 0 : if (opt.verbose)
1356 0 : log_info ("connection to socket '%s' established\n", url);
1357 :
1358 0 : xfree (url);
1359 : }
1360 : else
1361 2 : ctx = start_agent ();
1362 :
1363 : /* See whether there is a line pending from the server (in case
1364 : assuan did not run the initial handshaking). */
1365 2 : if (assuan_pending_line (ctx))
1366 : {
1367 0 : rc = read_and_print_response (ctx, 0, &cmderr);
1368 0 : if (rc)
1369 0 : log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
1370 : }
1371 :
1372 :
1373 42 : for (loopidx=0; loopidx < DIM (loopstack); loopidx++)
1374 40 : loopstack[loopidx].collecting = 0;
1375 2 : loopidx = -1;
1376 2 : line = NULL;
1377 2 : linesize = 0;
1378 2 : keep_line = 1;
1379 : for (;;)
1380 : {
1381 : int n;
1382 3 : size_t maxlength = 2048;
1383 :
1384 3 : assert (loopidx < (int)DIM (loopstack));
1385 3 : if (loopidx >= 0 && loopstack[loopidx].current)
1386 : {
1387 0 : keep_line = 0;
1388 0 : xfree (line);
1389 0 : line = xstrdup (loopstack[loopidx].current->line);
1390 0 : n = strlen (line);
1391 : /* Never go beyond of the final /end. */
1392 0 : if (loopstack[loopidx].current->next)
1393 0 : loopstack[loopidx].current = loopstack[loopidx].current->next;
1394 0 : else if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
1395 : ;
1396 : else
1397 0 : log_fatal ("/end command vanished\n");
1398 : }
1399 3 : else if (cmdline_commands && *cmdline_commands && !script_fp)
1400 : {
1401 3 : keep_line = 0;
1402 3 : xfree (line);
1403 3 : line = xstrdup (*cmdline_commands);
1404 3 : cmdline_commands++;
1405 3 : n = strlen (line);
1406 6 : if (n >= maxlength)
1407 0 : maxlength = 0;
1408 : }
1409 0 : else if (use_tty && !script_fp)
1410 : {
1411 0 : keep_line = 0;
1412 0 : xfree (line);
1413 0 : line = tty_get ("> ");
1414 0 : n = strlen (line);
1415 0 : if (n==1 && *line == CONTROL_D)
1416 0 : n = 0;
1417 0 : if (n >= maxlength)
1418 0 : maxlength = 0;
1419 : }
1420 : else
1421 : {
1422 0 : if (!keep_line)
1423 : {
1424 0 : xfree (line);
1425 0 : line = NULL;
1426 0 : linesize = 0;
1427 0 : keep_line = 1;
1428 : }
1429 0 : n = read_line (script_fp? script_fp:stdin,
1430 : &line, &linesize, &maxlength);
1431 : }
1432 3 : if (n < 0)
1433 : {
1434 0 : log_error (_("error reading input: %s\n"), strerror (errno));
1435 0 : if (script_fp)
1436 : {
1437 0 : fclose (script_fp);
1438 0 : script_fp = NULL;
1439 0 : log_error ("stopping script execution\n");
1440 0 : continue;
1441 : }
1442 0 : exit (1);
1443 : }
1444 3 : if (!n)
1445 : {
1446 : /* EOF */
1447 0 : if (script_fp)
1448 : {
1449 0 : fclose (script_fp);
1450 0 : script_fp = NULL;
1451 0 : if (opt.verbose)
1452 0 : log_info ("end of script\n");
1453 0 : continue;
1454 : }
1455 2 : break;
1456 : }
1457 3 : if (!maxlength)
1458 : {
1459 0 : log_error (_("line too long - skipped\n"));
1460 0 : continue;
1461 : }
1462 3 : if (memchr (line, 0, n))
1463 0 : log_info (_("line shortened due to embedded Nul character\n"));
1464 3 : if (line[n-1] == '\n')
1465 0 : line[n-1] = 0;
1466 :
1467 3 : if (opt.trim_leading_spaces)
1468 : {
1469 0 : const char *s = line;
1470 :
1471 0 : while (spacep (s))
1472 0 : s++;
1473 0 : if (s != line)
1474 : {
1475 0 : for (p=line; *s;)
1476 0 : *p++ = *s++;
1477 0 : *p = 0;
1478 0 : n = p - line;
1479 : }
1480 : }
1481 :
1482 3 : if (loopidx+1 >= 0 && loopstack[loopidx+1].collecting)
1483 : {
1484 : loopline_t ll;
1485 :
1486 0 : ll = xmalloc (sizeof *ll + strlen (line));
1487 0 : ll->next = NULL;
1488 0 : strcpy (ll->line, line);
1489 0 : *loopstack[loopidx+1].tail = ll;
1490 0 : loopstack[loopidx+1].tail = &ll->next;
1491 :
1492 0 : if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
1493 0 : loopstack[loopidx+1].nestlevel--;
1494 0 : else if (!strncmp (line, "/while", 6) && (!line[6]||spacep(line+6)))
1495 0 : loopstack[loopidx+1].nestlevel++;
1496 :
1497 0 : if (loopstack[loopidx+1].nestlevel)
1498 0 : continue;
1499 : /* We reached the corresponding /end. */
1500 0 : loopstack[loopidx+1].collecting = 0;
1501 0 : loopidx++;
1502 : }
1503 :
1504 3 : if (*line == '/')
1505 : {
1506 : /* Handle control commands. */
1507 2 : char *cmd = line+1;
1508 :
1509 2 : for (p=cmd; *p && !spacep (p); p++)
1510 : ;
1511 2 : if (*p)
1512 0 : *p++ = 0;
1513 4 : while (spacep (p))
1514 0 : p++;
1515 2 : if (!strcmp (cmd, "let"))
1516 : {
1517 0 : assign_variable (p, 0);
1518 : }
1519 2 : else if (!strcmp (cmd, "slet"))
1520 : {
1521 : /* Deprecated - never used in a released version. */
1522 0 : assign_variable (p, 1);
1523 : }
1524 2 : else if (!strcmp (cmd, "showvar"))
1525 : {
1526 0 : show_variables ();
1527 : }
1528 2 : else if (!strcmp (cmd, "definq"))
1529 : {
1530 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1531 0 : if (tmpline)
1532 : {
1533 0 : add_definq (tmpline, 1, 0);
1534 0 : xfree (tmpline);
1535 : }
1536 : else
1537 0 : add_definq (p, 1, 0);
1538 : }
1539 2 : else if (!strcmp (cmd, "definqfile"))
1540 : {
1541 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1542 0 : if (tmpline)
1543 : {
1544 0 : add_definq (tmpline, 0, 0);
1545 0 : xfree (tmpline);
1546 : }
1547 : else
1548 0 : add_definq (p, 0, 0);
1549 : }
1550 2 : else if (!strcmp (cmd, "definqprog"))
1551 : {
1552 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1553 0 : if (tmpline)
1554 : {
1555 0 : add_definq (tmpline, 0, 1);
1556 0 : xfree (tmpline);
1557 : }
1558 : else
1559 0 : add_definq (p, 0, 1);
1560 : }
1561 2 : else if (!strcmp (cmd, "datafile"))
1562 : {
1563 : const char *fname;
1564 :
1565 0 : if (current_datasink)
1566 : {
1567 0 : if (current_datasink != stdout)
1568 0 : fclose (current_datasink);
1569 0 : current_datasink = NULL;
1570 : }
1571 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1572 0 : fname = tmpline? tmpline : p;
1573 0 : if (fname && !strcmp (fname, "-"))
1574 0 : current_datasink = stdout;
1575 0 : else if (fname && *fname)
1576 : {
1577 0 : current_datasink = fopen (fname, "wb");
1578 0 : if (!current_datasink)
1579 0 : log_error ("can't open '%s': %s\n",
1580 0 : fname, strerror (errno));
1581 : }
1582 0 : xfree (tmpline);
1583 : }
1584 2 : else if (!strcmp (cmd, "showdef"))
1585 : {
1586 0 : show_definq ();
1587 : }
1588 2 : else if (!strcmp (cmd, "cleardef"))
1589 : {
1590 0 : clear_definq ();
1591 : }
1592 2 : else if (!strcmp (cmd, "echo"))
1593 : {
1594 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1595 0 : if (tmpline)
1596 : {
1597 0 : puts (tmpline);
1598 0 : xfree (tmpline);
1599 : }
1600 : else
1601 0 : puts (p);
1602 : }
1603 2 : else if (!strcmp (cmd, "sendfd"))
1604 : {
1605 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1606 0 : if (tmpline)
1607 : {
1608 0 : do_sendfd (ctx, tmpline);
1609 0 : xfree (tmpline);
1610 : }
1611 : else
1612 0 : do_sendfd (ctx, p);
1613 0 : continue;
1614 : }
1615 2 : else if (!strcmp (cmd, "recvfd"))
1616 : {
1617 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1618 0 : if (tmpline)
1619 : {
1620 0 : do_recvfd (ctx, tmpline);
1621 0 : xfree (tmpline);
1622 : }
1623 : else
1624 0 : do_recvfd (ctx, p);
1625 0 : continue;
1626 : }
1627 2 : else if (!strcmp (cmd, "open"))
1628 : {
1629 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1630 0 : if (tmpline)
1631 : {
1632 0 : do_open (tmpline);
1633 0 : xfree (tmpline);
1634 : }
1635 : else
1636 0 : do_open (p);
1637 : }
1638 2 : else if (!strcmp (cmd, "close"))
1639 : {
1640 0 : tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1641 0 : if (tmpline)
1642 : {
1643 0 : do_close (tmpline);
1644 0 : xfree (tmpline);
1645 : }
1646 : else
1647 0 : do_close (p);
1648 : }
1649 2 : else if (!strcmp (cmd, "showopen"))
1650 : {
1651 0 : do_showopen ();
1652 : }
1653 2 : else if (!strcmp (cmd, "serverpid"))
1654 : {
1655 0 : do_serverpid (ctx);
1656 : }
1657 2 : else if (!strcmp (cmd, "hex"))
1658 0 : opt.hex = 1;
1659 2 : else if (!strcmp (cmd, "nohex"))
1660 0 : opt.hex = 0;
1661 2 : else if (!strcmp (cmd, "decode"))
1662 0 : opt.decode = 1;
1663 2 : else if (!strcmp (cmd, "nodecode"))
1664 0 : opt.decode = 0;
1665 2 : else if (!strcmp (cmd, "subst"))
1666 : {
1667 0 : opt.enable_varsubst = 1;
1668 0 : opt.trim_leading_spaces = 1;
1669 : }
1670 2 : else if (!strcmp (cmd, "nosubst"))
1671 0 : opt.enable_varsubst = 0;
1672 2 : else if (!strcmp (cmd, "run"))
1673 : {
1674 : char *p2;
1675 :
1676 0 : for (p2=p; *p2 && !spacep (p2); p2++)
1677 : ;
1678 0 : if (*p2)
1679 0 : *p2++ = 0;
1680 0 : while (spacep (p2))
1681 0 : p++;
1682 0 : if (*p2)
1683 : {
1684 0 : log_error ("syntax error in run command\n");
1685 0 : if (script_fp)
1686 : {
1687 0 : fclose (script_fp);
1688 0 : script_fp = NULL;
1689 : }
1690 : }
1691 0 : else if (script_fp)
1692 : {
1693 0 : log_error ("cannot nest run commands - stop\n");
1694 0 : fclose (script_fp);
1695 0 : script_fp = NULL;
1696 : }
1697 0 : else if (!(script_fp = fopen (p, "r")))
1698 : {
1699 0 : log_error ("cannot open run file '%s': %s\n",
1700 0 : p, strerror (errno));
1701 : }
1702 0 : else if (opt.verbose)
1703 0 : log_info ("running commands from '%s'\n", p);
1704 : }
1705 2 : else if (!strcmp (cmd, "while"))
1706 : {
1707 0 : if (loopidx+2 >= (int)DIM(loopstack))
1708 : {
1709 0 : log_error ("blocks are nested too deep\n");
1710 : /* We should better die or break all loop in this
1711 : case as recovering from this error won't be
1712 : easy. */
1713 : }
1714 : else
1715 : {
1716 0 : loopstack[loopidx+1].head = NULL;
1717 0 : loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
1718 0 : loopstack[loopidx+1].current = NULL;
1719 0 : loopstack[loopidx+1].nestlevel = 1;
1720 0 : loopstack[loopidx+1].oneshot = 0;
1721 0 : loopstack[loopidx+1].condition = xstrdup (p);
1722 0 : loopstack[loopidx+1].collecting = 1;
1723 : }
1724 : }
1725 2 : else if (!strcmp (cmd, "if"))
1726 : {
1727 0 : if (loopidx+2 >= (int)DIM(loopstack))
1728 : {
1729 0 : log_error ("blocks are nested too deep\n");
1730 : }
1731 : else
1732 : {
1733 : /* Note that we need to evaluate the condition right
1734 : away and not just at the end of the block as we
1735 : do with a WHILE. */
1736 0 : loopstack[loopidx+1].head = NULL;
1737 0 : loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
1738 0 : loopstack[loopidx+1].current = NULL;
1739 0 : loopstack[loopidx+1].nestlevel = 1;
1740 0 : loopstack[loopidx+1].oneshot = 1;
1741 0 : loopstack[loopidx+1].condition = substitute_line_copy (p);
1742 0 : loopstack[loopidx+1].collecting = 1;
1743 : }
1744 : }
1745 2 : else if (!strcmp (cmd, "end"))
1746 : {
1747 0 : if (loopidx < 0)
1748 0 : log_error ("stray /end command encountered - ignored\n");
1749 : else
1750 : {
1751 : char *tmpcond;
1752 : const char *value;
1753 : long condition;
1754 :
1755 : /* Evaluate the condition. */
1756 0 : tmpcond = xstrdup (loopstack[loopidx].condition);
1757 0 : if (loopstack[loopidx].oneshot)
1758 : {
1759 0 : xfree (loopstack[loopidx].condition);
1760 0 : loopstack[loopidx].condition = xstrdup ("0");
1761 : }
1762 0 : tmpline = substitute_line (tmpcond);
1763 0 : value = tmpline? tmpline : tmpcond;
1764 : /* "true" or "yes" are commonly used to mean TRUE;
1765 : all other strings will evaluate to FALSE due to
1766 : the strtoul. */
1767 0 : if (!ascii_strcasecmp (value, "true")
1768 0 : || !ascii_strcasecmp (value, "yes"))
1769 0 : condition = 1;
1770 : else
1771 0 : condition = strtol (value, NULL, 0);
1772 0 : xfree (tmpline);
1773 0 : xfree (tmpcond);
1774 :
1775 0 : if (condition)
1776 : {
1777 : /* Run loop. */
1778 0 : loopstack[loopidx].current = loopstack[loopidx].head;
1779 : }
1780 : else
1781 : {
1782 : /* Cleanup. */
1783 0 : while (loopstack[loopidx].head)
1784 : {
1785 0 : loopline_t tmp = loopstack[loopidx].head->next;
1786 0 : xfree (loopstack[loopidx].head);
1787 0 : loopstack[loopidx].head = tmp;
1788 : }
1789 0 : loopstack[loopidx].tail = NULL;
1790 0 : loopstack[loopidx].current = NULL;
1791 0 : loopstack[loopidx].nestlevel = 0;
1792 0 : loopstack[loopidx].collecting = 0;
1793 0 : loopstack[loopidx].oneshot = 0;
1794 0 : xfree (loopstack[loopidx].condition);
1795 0 : loopstack[loopidx].condition = NULL;
1796 0 : loopidx--;
1797 : }
1798 : }
1799 : }
1800 2 : else if (!strcmp (cmd, "bye"))
1801 : {
1802 2 : break;
1803 : }
1804 0 : else if (!strcmp (cmd, "sleep"))
1805 : {
1806 0 : gnupg_sleep (1);
1807 : }
1808 0 : else if (!strcmp (cmd, "help"))
1809 : {
1810 0 : puts (
1811 : "Available commands:\n"
1812 : "/echo ARGS Echo ARGS.\n"
1813 : "/let NAME VALUE Set variable NAME to VALUE.\n"
1814 : "/showvar Show all variables.\n"
1815 : "/definq NAME VAR Use content of VAR for inquiries with NAME.\n"
1816 : "/definqfile NAME FILE Use content of FILE for inquiries with NAME.\n"
1817 : "/definqprog NAME PGM Run PGM for inquiries with NAME.\n"
1818 : "/datafile [NAME] Write all D line content to file NAME.\n"
1819 : "/showdef Print all definitions.\n"
1820 : "/cleardef Delete all definitions.\n"
1821 : "/sendfd FILE MODE Open FILE and pass descriptor to server.\n"
1822 : "/recvfd Receive FD from server and print.\n"
1823 : "/open VAR FILE MODE Open FILE and assign the file descriptor to VAR.\n"
1824 : "/close FD Close file with descriptor FD.\n"
1825 : "/showopen Show descriptors of all open files.\n"
1826 : "/serverpid Retrieve the pid of the server.\n"
1827 : "/[no]hex Enable hex dumping of received data lines.\n"
1828 : "/[no]decode Enable decoding of received data lines.\n"
1829 : "/[no]subst Enable variable substitution.\n"
1830 : "/run FILE Run commands from FILE.\n"
1831 : "/if VAR Begin conditional block controlled by VAR.\n"
1832 : "/while VAR Begin loop controlled by VAR.\n"
1833 : "/end End loop or condition\n"
1834 : "/bye Terminate gpg-connect-agent.\n"
1835 : "/help Print this help.");
1836 : }
1837 : else
1838 0 : log_error (_("unknown command '%s'\n"), cmd );
1839 :
1840 0 : continue;
1841 : }
1842 :
1843 1 : if (opt.verbose && script_fp)
1844 0 : puts (line);
1845 :
1846 1 : tmpline = opt.enable_varsubst? substitute_line (line) : NULL;
1847 1 : if (tmpline)
1848 : {
1849 0 : rc = assuan_write_line (ctx, tmpline);
1850 0 : xfree (tmpline);
1851 : }
1852 : else
1853 1 : rc = assuan_write_line (ctx, line);
1854 1 : if (rc)
1855 : {
1856 0 : log_info (_("sending line failed: %s\n"), gpg_strerror (rc) );
1857 0 : break;
1858 : }
1859 1 : if (*line == '#' || !*line)
1860 0 : continue; /* Don't expect a response for a comment line. */
1861 :
1862 1 : rc = read_and_print_response (ctx, help_cmd_p (line), &cmderr);
1863 1 : if (rc)
1864 0 : log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
1865 1 : if ((rc || cmderr) && script_fp)
1866 : {
1867 0 : log_error ("stopping script execution\n");
1868 0 : fclose (script_fp);
1869 0 : script_fp = NULL;
1870 : }
1871 :
1872 :
1873 : /* FIXME: If the last command was BYE or the server died for
1874 : some other reason, we won't notice until we get the next
1875 : input command. Probing the connection with a non-blocking
1876 : read could help to notice termination or other problems
1877 : early. */
1878 1 : }
1879 :
1880 2 : if (opt.verbose)
1881 1 : log_info ("closing connection to agent\n");
1882 :
1883 2 : return 0;
1884 : }
1885 :
1886 :
1887 : /* Handle an Inquire from the server. Return False if it could not be
1888 : handled; in this case the caller shll complete the operation. LINE
1889 : is the complete line as received from the server. This function
1890 : may change the content of LINE. */
1891 : static int
1892 0 : handle_inquire (assuan_context_t ctx, char *line)
1893 : {
1894 : const char *name;
1895 : definq_t d;
1896 0 : FILE *fp = NULL;
1897 : char buffer[1024];
1898 : int rc, n;
1899 :
1900 : /* Skip the command and trailing spaces. */
1901 0 : for (; *line && !spacep (line); line++)
1902 : ;
1903 0 : while (spacep (line))
1904 0 : line++;
1905 : /* Get the name. */
1906 0 : name = line;
1907 0 : for (; *line && !spacep (line); line++)
1908 : ;
1909 0 : if (*line)
1910 0 : *line++ = 0;
1911 :
1912 : /* Now match it against our list. The second loop is there to
1913 : detect the match-all entry. */
1914 0 : for (d=definq_list; d; d = d->next)
1915 0 : if (d->name && !strcmp (d->name, name))
1916 0 : break;
1917 0 : if (!d)
1918 0 : for (d=definq_list; d; d = d->next)
1919 0 : if (!d->name)
1920 0 : break;
1921 0 : if (!d)
1922 : {
1923 0 : if (opt.verbose)
1924 0 : log_info ("no handler for inquiry '%s' found\n", name);
1925 0 : return 0;
1926 : }
1927 :
1928 0 : if (d->is_var)
1929 : {
1930 0 : char *tmpvalue = get_var_ext (d->file);
1931 0 : if (tmpvalue)
1932 0 : rc = assuan_send_data (ctx, tmpvalue, strlen (tmpvalue));
1933 : else
1934 0 : rc = assuan_send_data (ctx, "", 0);
1935 0 : xfree (tmpvalue);
1936 0 : if (rc)
1937 0 : log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1938 : }
1939 : else
1940 : {
1941 0 : if (d->is_prog)
1942 : {
1943 : #ifdef HAVE_W32CE_SYSTEM
1944 : fp = NULL;
1945 : #else
1946 0 : fp = popen (d->file, "r");
1947 : #endif
1948 0 : if (!fp)
1949 0 : log_error ("error executing '%s': %s\n",
1950 0 : d->file, strerror (errno));
1951 0 : else if (opt.verbose)
1952 0 : log_error ("handling inquiry '%s' by running '%s'\n",
1953 0 : name, d->file);
1954 : }
1955 : else
1956 : {
1957 0 : fp = fopen (d->file, "rb");
1958 0 : if (!fp)
1959 0 : log_error ("error opening '%s': %s\n", d->file, strerror (errno));
1960 0 : else if (opt.verbose)
1961 0 : log_error ("handling inquiry '%s' by returning content of '%s'\n",
1962 0 : name, d->file);
1963 : }
1964 0 : if (!fp)
1965 0 : return 0;
1966 :
1967 0 : while ( (n = fread (buffer, 1, sizeof buffer, fp)) )
1968 : {
1969 0 : rc = assuan_send_data (ctx, buffer, n);
1970 0 : if (rc)
1971 : {
1972 0 : log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1973 0 : break;
1974 : }
1975 : }
1976 0 : if (ferror (fp))
1977 0 : log_error ("error reading from '%s': %s\n", d->file, strerror (errno));
1978 : }
1979 :
1980 0 : rc = assuan_send_data (ctx, NULL, 0);
1981 0 : if (rc)
1982 0 : log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1983 :
1984 0 : if (d->is_var)
1985 : ;
1986 0 : else if (d->is_prog)
1987 : {
1988 : #ifndef HAVE_W32CE_SYSTEM
1989 0 : if (pclose (fp))
1990 0 : log_error ("error running '%s': %s\n", d->file, strerror (errno));
1991 : #endif
1992 : }
1993 : else
1994 0 : fclose (fp);
1995 0 : return 1;
1996 : }
1997 :
1998 :
1999 : /* Read all response lines from server and print them. Returns 0 on
2000 : success or an assuan error code. If WITHHASH istrue, comment lines
2001 : are printed. Sets R_GOTERR to true if the command did not returned
2002 : OK. */
2003 : static int
2004 1 : read_and_print_response (assuan_context_t ctx, int withhash, int *r_goterr)
2005 : {
2006 : char *line;
2007 : size_t linelen;
2008 : gpg_error_t rc;
2009 : int i, j;
2010 1 : int need_lf = 0;
2011 :
2012 1 : *r_goterr = 0;
2013 : for (;;)
2014 : {
2015 : do
2016 : {
2017 1 : rc = assuan_read_line (ctx, &line, &linelen);
2018 1 : if (rc)
2019 0 : return rc;
2020 :
2021 1 : if ((withhash || opt.verbose > 1) && *line == '#')
2022 : {
2023 0 : fwrite (line, linelen, 1, stdout);
2024 0 : putchar ('\n');
2025 : }
2026 : }
2027 1 : while (*line == '#' || !linelen);
2028 :
2029 1 : if (linelen >= 1
2030 1 : && line[0] == 'D' && line[1] == ' ')
2031 : {
2032 0 : if (current_datasink)
2033 : {
2034 : const unsigned char *s;
2035 0 : int c = 0;
2036 :
2037 0 : for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
2038 : {
2039 0 : if (*s == '%' && j+2 < linelen)
2040 : {
2041 0 : s++; j++;
2042 0 : c = xtoi_2 ( s );
2043 0 : s++; j++;
2044 : }
2045 : else
2046 0 : c = *s;
2047 0 : putc (c, current_datasink);
2048 : }
2049 : }
2050 0 : else if (opt.hex)
2051 : {
2052 0 : for (i=2; i < linelen; )
2053 : {
2054 0 : int save_i = i;
2055 :
2056 0 : printf ("D[%04X] ", i-2);
2057 0 : for (j=0; j < 16 ; j++, i++)
2058 : {
2059 0 : if (j == 8)
2060 0 : putchar (' ');
2061 0 : if (i < linelen)
2062 0 : printf (" %02X", ((unsigned char*)line)[i]);
2063 : else
2064 0 : fputs (" ", stdout);
2065 : }
2066 0 : fputs (" ", stdout);
2067 0 : i= save_i;
2068 0 : for (j=0; j < 16; j++, i++)
2069 : {
2070 0 : unsigned int c = ((unsigned char*)line)[i];
2071 0 : if ( i >= linelen )
2072 0 : putchar (' ');
2073 0 : else if (isascii (c) && isprint (c) && !iscntrl (c))
2074 0 : putchar (c);
2075 : else
2076 0 : putchar ('.');
2077 : }
2078 0 : putchar ('\n');
2079 : }
2080 : }
2081 0 : else if (opt.decode)
2082 : {
2083 : const unsigned char *s;
2084 0 : int need_d = 1;
2085 0 : int c = 0;
2086 :
2087 0 : for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
2088 : {
2089 0 : if (need_d)
2090 : {
2091 0 : fputs ("D ", stdout);
2092 0 : need_d = 0;
2093 : }
2094 0 : if (*s == '%' && j+2 < linelen)
2095 : {
2096 0 : s++; j++;
2097 0 : c = xtoi_2 ( s );
2098 0 : s++; j++;
2099 : }
2100 : else
2101 0 : c = *s;
2102 0 : if (c == '\n')
2103 0 : need_d = 1;
2104 0 : putchar (c);
2105 : }
2106 0 : need_lf = (c != '\n');
2107 : }
2108 : else
2109 : {
2110 0 : fwrite (line, linelen, 1, stdout);
2111 0 : putchar ('\n');
2112 : }
2113 : }
2114 : else
2115 : {
2116 1 : if (need_lf)
2117 : {
2118 0 : if (!current_datasink || current_datasink != stdout)
2119 0 : putchar ('\n');
2120 0 : need_lf = 0;
2121 : }
2122 :
2123 1 : if (linelen >= 1
2124 1 : && line[0] == 'S'
2125 0 : && (line[1] == '\0' || line[1] == ' '))
2126 : {
2127 0 : if (!current_datasink || current_datasink != stdout)
2128 : {
2129 0 : fwrite (line, linelen, 1, stdout);
2130 0 : putchar ('\n');
2131 : }
2132 : }
2133 1 : else if (linelen >= 2
2134 1 : && line[0] == 'O' && line[1] == 'K'
2135 1 : && (line[2] == '\0' || line[2] == ' '))
2136 : {
2137 1 : if (!current_datasink || current_datasink != stdout)
2138 : {
2139 1 : fwrite (line, linelen, 1, stdout);
2140 1 : putchar ('\n');
2141 : }
2142 1 : set_int_var ("?", 0);
2143 1 : return 0;
2144 : }
2145 0 : else if (linelen >= 3
2146 0 : && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
2147 0 : && (line[3] == '\0' || line[3] == ' '))
2148 : {
2149 : int errval;
2150 :
2151 0 : errval = strtol (line+3, NULL, 10);
2152 0 : if (!errval)
2153 0 : errval = -1;
2154 0 : set_int_var ("?", errval);
2155 0 : if (!current_datasink || current_datasink != stdout)
2156 : {
2157 0 : fwrite (line, linelen, 1, stdout);
2158 0 : putchar ('\n');
2159 : }
2160 0 : *r_goterr = 1;
2161 0 : return 0;
2162 : }
2163 0 : else if (linelen >= 7
2164 0 : && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
2165 0 : && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
2166 0 : && line[6] == 'E'
2167 0 : && (line[7] == '\0' || line[7] == ' '))
2168 : {
2169 0 : if (!current_datasink || current_datasink != stdout)
2170 : {
2171 0 : fwrite (line, linelen, 1, stdout);
2172 0 : putchar ('\n');
2173 : }
2174 0 : if (!handle_inquire (ctx, line))
2175 0 : assuan_write_line (ctx, "CANCEL");
2176 : }
2177 0 : else if (linelen >= 3
2178 0 : && line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
2179 0 : && (line[3] == '\0' || line[3] == ' '))
2180 : {
2181 0 : if (!current_datasink || current_datasink != stdout)
2182 : {
2183 0 : fwrite (line, linelen, 1, stdout);
2184 0 : putchar ('\n');
2185 : }
2186 : /* Received from server, thus more responses are expected. */
2187 : }
2188 : else
2189 0 : return gpg_error (GPG_ERR_ASS_INV_RESPONSE);
2190 : }
2191 0 : }
2192 : }
2193 :
2194 :
2195 :
2196 :
2197 : /* Connect to the agent and send the standard options. */
2198 : static assuan_context_t
2199 2 : start_agent (void)
2200 : {
2201 : gpg_error_t err;
2202 : assuan_context_t ctx;
2203 : session_env_t session_env;
2204 :
2205 2 : session_env = session_env_new ();
2206 2 : if (!session_env)
2207 0 : log_fatal ("error allocating session environment block: %s\n",
2208 0 : strerror (errno));
2209 2 : if (opt.use_dirmngr)
2210 0 : err = start_new_dirmngr (&ctx,
2211 : GPG_ERR_SOURCE_DEFAULT,
2212 : opt.homedir,
2213 : opt.dirmngr_program,
2214 : opt.autostart,
2215 0 : !opt.quiet, 0,
2216 : NULL, NULL);
2217 : else
2218 2 : err = start_new_gpg_agent (&ctx,
2219 : GPG_ERR_SOURCE_DEFAULT,
2220 : opt.homedir,
2221 : opt.agent_program,
2222 : NULL, NULL,
2223 : session_env,
2224 : opt.autostart,
2225 2 : !opt.quiet, 0,
2226 : NULL, NULL);
2227 :
2228 2 : session_env_release (session_env);
2229 2 : if (err)
2230 : {
2231 0 : if (!opt.autostart
2232 0 : && (gpg_err_code (err)
2233 : == opt.use_dirmngr? GPG_ERR_NO_DIRMNGR : GPG_ERR_NO_AGENT))
2234 : {
2235 : /* In the no-autostart case we don't make gpg-connect-agent
2236 : fail on a missing server. */
2237 0 : log_info (opt.use_dirmngr?
2238 : _("no dirmngr running in this session\n"):
2239 : _("no gpg-agent running in this session\n"));
2240 0 : exit (0);
2241 : }
2242 : else
2243 : {
2244 0 : log_error (_("error sending standard options: %s\n"),
2245 : gpg_strerror (err));
2246 0 : exit (1);
2247 : }
2248 : }
2249 :
2250 2 : return ctx;
2251 : }
|