1 /* gpg-connect-agent.c - Tool to connect to the agent.
2 * Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
32 #include "../common/util.h"
33 #include "../common/asshelp.h"
34 #include "../common/sysutils.h"
35 #include "../common/membuf.h"
36 #include "../common/ttyio.h"
37 #ifdef HAVE_W32_SYSTEM
38 # include "../common/exechelp.h"
42 #define CONTROL_D ('D' - 'A' + 1)
43 #define octdigitp(p) (*(p) >= '0' && *(p) <= '7')
45 /* Constants to identify the commands and options. */
46 enum cmd_and_opt_values
65 /* The list of commands and options. */
66 static ARGPARSE_OPTS opts
[] = {
67 ARGPARSE_group (301, N_("@\nOptions:\n ")),
69 ARGPARSE_s_n (oVerbose
, "verbose", N_("verbose")),
70 ARGPARSE_s_n (oQuiet
, "quiet", N_("quiet")),
71 ARGPARSE_s_n (oHex
, "hex", N_("print data out hex encoded")),
72 ARGPARSE_s_n (oDecode
,"decode", N_("decode received data lines")),
73 ARGPARSE_s_s (oRawSocket
, "raw-socket",
74 N_("|NAME|connect to Assuan socket NAME")),
75 ARGPARSE_s_n (oExec
, "exec",
76 N_("run the Assuan server given on the command line")),
77 ARGPARSE_s_n (oNoExtConnect
, "no-ext-connect",
78 N_("do not use extended connect mode")),
79 ARGPARSE_s_s (oRun
, "run",
80 N_("|FILE|run commands from FILE on startup")),
81 ARGPARSE_s_n (oSubst
, "subst", N_("run /subst on startup")),
83 ARGPARSE_s_n (oNoVerbose
, "no-verbose", "@"),
84 ARGPARSE_s_s (oHomedir
, "homedir", "@" ),
90 /* We keep all global options in the structure OPT. */
93 int verbose
; /* Verbosity level. */
94 int quiet
; /* Be extra quiet. */
95 const char *homedir
; /* Configuration directory name */
96 int hex
; /* Print data lines in hex format. */
97 int decode
; /* Decode received data lines. */
98 const char *raw_socket
; /* Name of socket to connect in raw mode. */
99 int exec
; /* Run the pgm given on the command line. */
100 unsigned int connect_flags
; /* Flags used for connecting. */
101 int enable_varsubst
; /* Set if variable substitution is enabled. */
102 int trim_leading_spaces
;
107 /* Definitions for /definq commands and a global linked list with all
111 struct definq_s
*next
;
112 char *name
; /* Name of inquiry or NULL for any name. */
113 int is_var
; /* True if FILE is a variable name. */
114 int is_prog
; /* True if FILE is a program to run. */
115 char file
[1]; /* Name of file or program. */
117 typedef struct definq_s
*definq_t
;
119 static definq_t definq_list
;
120 static definq_t
*definq_list_tail
= &definq_list
;
123 /* Variable definitions and glovbal table. */
126 struct variable_s
*next
;
127 char *value
; /* Malloced value - always a string. */
128 char name
[1]; /* Name of the variable. */
130 typedef struct variable_s
*variable_t
;
132 static variable_t variable_table
;
135 /* To implement loops we store entire lines in a linked list. */
138 struct loopline_s
*next
;
141 typedef struct loopline_s
*loopline_t
;
144 /* This is used to store the pid of the server. */
145 static pid_t server_pid
= (pid_t
)(-1);
147 /* The current datasink file or NULL. */
148 static FILE *current_datasink
;
150 /* A list of open file descriptors. */
154 #ifdef HAVE_W32_SYSTEM
157 } open_fd_table
[256];
160 /*-- local prototypes --*/
161 static char *substitute_line_copy (const char *buffer
);
162 static int read_and_print_response (assuan_context_t ctx
, int *r_goterr
);
163 static assuan_context_t
start_agent (void);
168 /* Print usage information and and provide strings for help. */
170 my_strusage( int level
)
176 case 11: p
= "gpg-connect-agent (GnuPG)";
178 case 13: p
= VERSION
; break;
179 case 17: p
= PRINTABLE_OS_NAME
; break;
180 case 19: p
= _("Please report bugs to <" PACKAGE_BUGREPORT
">.\n");
183 case 40: p
= _("Usage: gpg-connect-agent [options] (-h for help)");
186 p
= _("Syntax: gpg-connect-agent [options]\n"
187 "Connect to a running agent and send commands\n");
189 case 31: p
= "\nHome: "; break;
190 case 32: p
= opt
.homedir
; break;
191 case 33: p
= "\n"; break;
193 default: p
= NULL
; break;
207 buffer
= xmalloc (size
+1);
208 if (getcwd (buffer
, size
) == buffer
)
218 /* Unescape STRING and returned the malloced result. The surrounding
219 quotes must already be removed from STRING. */
221 unescape_string (const char *string
)
223 const unsigned char *s
;
230 for (s
= (const unsigned char*)string
, esc
=0; *s
; s
++)
244 case '\\': n
++; break;
246 if (s
[1] && s
[2] && hexdigitp (s
+1) && hexdigitp (s
+2))
252 && octdigitp (s
) && octdigitp (s
+1) && octdigitp (s
+2))
264 buffer
= xmalloc (n
+1);
265 d
= (unsigned char*)buffer
;
266 for (s
= (const unsigned char*)string
, esc
=0; *s
; s
++)
272 case 'b': *d
++ = '\b'; break;
273 case 't': *d
++ = '\t'; break;
274 case 'v': *d
++ = '\v'; break;
275 case 'n': *d
++ = '\n'; break;
276 case 'f': *d
++ = '\f'; break;
277 case 'r': *d
++ = '\r'; break;
278 case '"': *d
++ = '\"'; break;
279 case '\'': *d
++ = '\''; break;
280 case '\\': *d
++ = '\\'; break;
282 if (s
[1] && s
[2] && hexdigitp (s
+1) && hexdigitp (s
+2))
292 && octdigitp (s
) && octdigitp (s
+1) && octdigitp (s
+2))
294 *d
++ = (atoi_1 (s
)*64) + (atoi_1 (s
+1)*8) + atoi_1 (s
+2);
311 /* Do the percent unescaping and return a newly malloced string.
312 If WITH_PLUS is set '+' characters will be changed to space. */
314 unpercent_string (const char *string
, int with_plus
)
316 const unsigned char *s
;
317 unsigned char *buffer
, *p
;
321 for (s
=(const unsigned char *)string
; *s
; s
++)
323 if (*s
== '%' && s
[1] && s
[2])
329 else if (with_plus
&& *s
== '+')
335 buffer
= xmalloc (n
+1);
337 for (s
=(const unsigned char *)string
; *s
; s
++)
339 if (*s
== '%' && s
[1] && s
[2])
345 else if (with_plus
&& *s
== '+')
351 return (char*)buffer
;
359 set_var (const char *name
, const char *value
)
363 for (var
= variable_table
; var
; var
= var
->next
)
364 if (!strcmp (var
->name
, name
))
368 var
= xmalloc (sizeof *var
+ strlen (name
));
370 strcpy (var
->name
, name
);
371 var
->next
= variable_table
;
372 variable_table
= var
;
375 var
->value
= value
? xstrdup (value
) : NULL
;
381 set_int_var (const char *name
, int value
)
385 snprintf (numbuf
, sizeof numbuf
, "%d", value
);
386 set_var (name
, numbuf
);
390 /* Return the value of a variable. That value is valid until a
391 variable of the name is changed. Return NULL if not found. Note
392 that envvars are copied to our variable list at the first access
393 and not at oprogram start. */
395 get_var (const char *name
)
402 for (var
= variable_table
; var
; var
= var
->next
)
403 if (!strcmp (var
->name
, name
))
405 if (!var
&& (s
= getenv (name
)))
406 return set_var (name
, s
);
407 if (!var
|| !var
->value
)
413 /* Perform some simple arithmentic operations. Caller must release
414 the return value. On error the return value is NULL. */
416 arithmetic_op (int operator, const char *operands
)
421 while ( spacep (operands
) )
425 result
= strtol (operands
, NULL
, 0);
426 while (*operands
&& !spacep (operands
) )
433 while ( spacep (operands
) )
437 value
= strtol (operands
, NULL
, 0);
438 while (*operands
&& !spacep (operands
) )
442 case '+': result
+= value
; break;
443 case '-': result
-= value
; break;
444 case '*': result
*= value
; break;
455 case '!': result
= !value
; break;
456 case '|': result
= result
|| value
; break;
457 case '&': result
= result
&& value
; break;
459 log_error ("unknown arithmetic operator `%c'\n", operator);
463 snprintf (numbuf
, sizeof numbuf
, "%ld", result
);
464 return xstrdup (numbuf
);
469 /* Extended version of get_var. This returns a malloced string and
470 understand the function syntax: "func args".
472 Defined functions are
474 get - Return a value described by the next argument:
475 cwd - The current working directory.
476 homedir - The gnupg homedir.
477 sysconfdir - GnuPG's system configuration directory.
478 bindir - GnuPG's binary directory.
479 libdir - GnuPG's library directory.
480 libexecdir - GnuPG's library directory for executable files.
481 datadir - GnuPG's data directory.
482 serverpid - The PID of the current server.
485 Remove C-style escapes from string. Note that "\0" and
486 "\x00" terminate the string implictly. Use "\x7d" to
487 represent the closing brace. The args start right after
488 the first space after the function name.
492 Remove percent style ecaping from string. Note that "%00
493 terminates the string implicitly. Use "%7d" to represetn
494 the closing brace. The args start right after the first
495 space after the function name. "unpercent+" also maps '+'
500 Escape the args using the percent style. Tabs, formfeeds,
501 linefeeds and carriage returns are also escaped.
502 "percent+" also maps spaces to plus characters.
505 Assuming ARG is an integer, return the gpg-error code.
508 Assuming ARG is an integer, return the gpg-error source.
511 Assuming ARG is an integer return a formatted fpf error string.
514 Example: get_var_ext ("get sysconfdir") -> "/etc/gnupg"
518 get_var_ext (const char *name
)
520 static int recursion_count
;
524 char *free_me
= NULL
;
527 if (recursion_count
> 50)
529 log_error ("variables nested too deeply\n");
534 free_me
= opt
.enable_varsubst
? substitute_line_copy (name
) : NULL
;
537 for (s
=name
; *s
&& !spacep (s
); s
++)
542 result
= s
? xstrdup (s
): NULL
;
544 else if ( (s
- name
) == 3 && !strncmp (name
, "get", 3))
548 if (!strcmp (s
, "cwd"))
550 result
= gnu_getcwd ();
552 log_error ("getcwd failed: %s\n", strerror (errno
));
554 else if (!strcmp (s
, "homedir"))
555 result
= make_filename (opt
.homedir
, NULL
);
556 else if (!strcmp (s
, "sysconfdir"))
557 result
= xstrdup (gnupg_sysconfdir ());
558 else if (!strcmp (s
, "bindir"))
559 result
= xstrdup (gnupg_bindir ());
560 else if (!strcmp (s
, "libdir"))
561 result
= xstrdup (gnupg_libdir ());
562 else if (!strcmp (s
, "libexecdir"))
563 result
= xstrdup (gnupg_libexecdir ());
564 else if (!strcmp (s
, "datadir"))
565 result
= xstrdup (gnupg_datadir ());
566 else if (!strcmp (s
, "serverpid"))
567 result
= xasprintf ("%d", (int)server_pid
);
570 log_error ("invalid argument `%s' for variable function `get'\n", s
);
571 log_info ("valid are: cwd, "
572 "{home,bin,lib,libexec,data}dir, serverpid\n");
576 else if ( (s
- name
) == 8 && !strncmp (name
, "unescape", 8))
579 result
= unescape_string (s
);
581 else if ( (s
- name
) == 9 && !strncmp (name
, "unpercent", 9))
584 result
= unpercent_string (s
, 0);
586 else if ( (s
- name
) == 10 && !strncmp (name
, "unpercent+", 10))
589 result
= unpercent_string (s
, 1);
591 else if ( (s
- name
) == 7 && !strncmp (name
, "percent", 7))
594 result
= percent_escape (s
, "\t\r\n\f\v");
596 else if ( (s
- name
) == 8 && !strncmp (name
, "percent+", 8))
599 result
= percent_escape (s
, "\t\r\n\f\v");
600 for (p
=result
; *p
; p
++)
604 else if ( (s
- name
) == 7 && !strncmp (name
, "errcode", 7))
607 intvalue
= (int)strtol (s
, NULL
, 0);
608 result
= xasprintf ("%d", gpg_err_code (intvalue
));
610 else if ( (s
- name
) == 9 && !strncmp (name
, "errsource", 9))
613 intvalue
= (int)strtol (s
, NULL
, 0);
614 result
= xasprintf ("%d", gpg_err_source (intvalue
));
616 else if ( (s
- name
) == 9 && !strncmp (name
, "errstring", 9))
619 intvalue
= (int)strtol (s
, NULL
, 0);
620 result
= xasprintf ("%s <%s>",
621 gpg_strerror (intvalue
), gpg_strsource (intvalue
));
623 else if ( (s
- name
) == 1 && strchr ("+-*/%!|&", *name
))
625 result
= arithmetic_op (*name
, s
+1);
629 log_error ("unknown variable function `%.*s'\n", (int)(s
-name
), name
);
639 /* Substitute variables in LINE and return a new allocated buffer if
640 required. The function might modify LINE if the expanded version
643 substitute_line (char *buffer
)
654 p
= strchr (line
, '$');
656 return result
; /* No more variables. */
658 if (p
[1] == '$') /* Escaped dollar sign. */
660 memmove (p
, p
+1, strlen (p
+1)+1);
668 for (pend
=p
+2; *pend
; pend
++)
672 else if (*pend
== '}')
679 return result
; /* Unclosed - don't substitute. */
683 for (pend
=p
+1; *pend
&& !spacep (pend
) && *pend
!= '$' ; pend
++)
686 if (p
[1] == '{' && *pend
== '}')
690 freeme
= get_var_ext (p
+2);
698 value
= get_var (p
+1);
702 value
= get_var (p
+1);
705 valuelen
= strlen (value
);
706 if (valuelen
<= pend
- p
)
708 memcpy (p
, value
, valuelen
);
712 memmove (p
, p
+n
, strlen (p
+n
)+1);
717 char *src
= result
? result
: buffer
;
720 dst
= xmalloc (strlen (src
) + valuelen
+ 1);
722 memcpy (dst
, src
, n
);
723 memcpy (dst
+ n
, value
, valuelen
);
725 strcpy (dst
+ n
, pend
);
736 /* Same as substitute_line but do not modify BUFFER. */
738 substitute_line_copy (const char *buffer
)
742 p
= xstrdup (buffer
?buffer
:"");
743 result
= substitute_line (p
);
753 assign_variable (char *line
, int syslet
)
755 char *name
, *p
, *tmp
, *free_me
, *buffer
;
759 for (p
=name
; *p
&& !spacep (p
); p
++)
767 set_var (name
, NULL
); /* Remove variable. */
770 free_me
= opt
.enable_varsubst
? substitute_line_copy (p
) : NULL
;
773 buffer
= xmalloc (4 + strlen (p
) + 1);
774 strcpy (stpcpy (buffer
, "get "), p
);
775 tmp
= get_var_ext (buffer
);
783 tmp
= opt
.enable_varsubst
? substitute_line_copy (p
) : NULL
;
796 show_variables (void)
800 for (var
= variable_table
; var
; var
= var
->next
)
802 printf ("%-20s %s\n", var
->name
, var
->value
);
806 /* Store an inquire response pattern. Note, that this function may
807 change the content of LINE. We assume that leading white spaces
808 are already removed. */
810 add_definq (char *line
, int is_var
, int is_prog
)
817 for (p
=name
; *p
&& !spacep (p
); p
++)
824 d
= xmalloc (sizeof *d
+ strlen (p
) );
827 d
->is_prog
= is_prog
;
828 if ( !strcmp (name
, "*"))
831 d
->name
= xstrdup (name
);
834 *definq_list_tail
= d
;
835 definq_list_tail
= &d
->next
;
839 /* Show all inquiry defintions. */
845 for (d
=definq_list
; d
; d
= d
->next
)
847 printf ("%-20s %c %s\n",
848 d
->name
, d
->is_var
? 'v' : d
->is_prog
? 'p':'f', d
->file
);
849 for (d
=definq_list
; d
; d
= d
->next
)
851 printf ("%-20s %c %s\n", "*",
852 d
->is_var
? 'v': d
->is_prog
? 'p':'f', d
->file
);
856 /* Clear all inquiry definitions. */
862 definq_t tmp
= definq_list
->next
;
863 xfree (definq_list
->name
);
867 definq_list_tail
= &definq_list
;
872 do_sendfd (assuan_context_t ctx
, char *line
)
875 char *name
, *mode
, *p
;
880 for (p
=name
; *p
&& !spacep (p
); p
++)
893 for (p
=mode
; *p
&& !spacep (p
); p
++)
900 fp
= fopen (name
, mode
);
903 log_error ("can't open `%s' in \"%s\" mode: %s\n",
904 name
, mode
, strerror (errno
));
910 log_error ("file `%s' opened in \"%s\" mode, fd=%d\n",
913 rc
= assuan_sendfd (ctx
, INT2FD (fd
) );
915 log_error ("sending descriptor %d failed: %s\n", fd
, gpg_strerror (rc
));
921 do_recvfd (assuan_context_t ctx
, char *line
)
925 log_info ("This command has not yet been implemented\n");
933 char *varname
, *name
, *mode
, *p
;
936 #ifdef HAVE_W32_SYSTEM
937 if (server_pid
== (pid_t
)(-1))
939 log_error ("the pid of the server is unknown\n");
940 log_info ("use command \"/serverpid\" first\n");
945 /* Get variable name. */
947 for (p
=varname
; *p
&& !spacep (p
); p
++)
956 for (p
=name
; *p
&& !spacep (p
); p
++)
969 for (p
=mode
; *p
&& !spacep (p
); p
++)
976 fp
= fopen (name
, mode
);
979 log_error ("can't open `%s' in \"%s\" mode: %s\n",
980 name
, mode
, strerror (errno
));
984 if (fd
>= 0 && fd
< DIM (open_fd_table
))
986 open_fd_table
[fd
].inuse
= 1;
987 #ifdef HAVE_W32_SYSTEM
989 HANDLE prochandle
, handle
, newhandle
;
991 handle
= (void*)_get_osfhandle (fd
);
993 prochandle
= OpenProcess (PROCESS_DUP_HANDLE
, FALSE
, server_pid
);
996 log_error ("failed to open the server process\n");
1001 if (!DuplicateHandle (GetCurrentProcess(), handle
,
1002 prochandle
, &newhandle
, 0,
1003 TRUE
, DUPLICATE_SAME_ACCESS
))
1005 log_error ("failed to duplicate the handle\n");
1007 CloseHandle (prochandle
);
1010 CloseHandle (prochandle
);
1011 open_fd_table
[fd
].handle
= newhandle
;
1014 log_info ("file `%s' opened in \"%s\" mode, fd=%d (libc=%d)\n",
1015 name
, mode
, (int)open_fd_table
[fd
].handle
, fd
);
1016 set_int_var (varname
, (int)open_fd_table
[fd
].handle
);
1019 log_info ("file `%s' opened in \"%s\" mode, fd=%d\n",
1021 set_int_var (varname
, fd
);
1026 log_error ("can't put fd %d into table\n", fd
);
1033 do_close (char *line
)
1035 int fd
= atoi (line
);
1037 #ifdef HAVE_W32_SYSTEM
1040 for (i
=0; i
< DIM (open_fd_table
); i
++)
1041 if ( open_fd_table
[i
].inuse
&& open_fd_table
[i
].handle
== (void*)fd
)
1043 if (i
< DIM (open_fd_table
))
1047 log_error ("given fd (system handle) has not been opened\n");
1052 if (fd
< 0 || fd
>= DIM (open_fd_table
))
1054 log_error ("invalid fd\n");
1058 if (!open_fd_table
[fd
].inuse
)
1060 log_error ("given fd has not been opened\n");
1063 #ifdef HAVE_W32_SYSTEM
1064 CloseHandle (open_fd_table
[fd
].handle
); /* Close duped handle. */
1067 open_fd_table
[fd
].inuse
= 0;
1076 for (i
=0; i
< DIM (open_fd_table
); i
++)
1077 if (open_fd_table
[i
].inuse
)
1079 #ifdef HAVE_W32_SYSTEM
1080 printf ("%-15d (libc=%d)\n", (int)open_fd_table
[i
].handle
, i
);
1082 printf ("%-15d\n", i
);
1090 getinfo_pid_cb (void *opaque
, const void *buffer
, size_t length
)
1092 membuf_t
*mb
= opaque
;
1093 put_membuf (mb
, buffer
, length
);
1097 /* Get the pid of the server and store it locally. */
1099 do_serverpid (assuan_context_t ctx
)
1105 init_membuf (&mb
, 100);
1106 rc
= assuan_transact (ctx
, "GETINFO pid", getinfo_pid_cb
, &mb
,
1107 NULL
, NULL
, NULL
, NULL
);
1108 put_membuf (&mb
, "", 1);
1109 buffer
= get_membuf (&mb
, NULL
);
1111 log_error ("command \"%s\" failed: %s\n",
1112 "GETINFO pid", gpg_strerror (rc
));
1115 server_pid
= (pid_t
)strtoul (buffer
, NULL
, 10);
1117 log_info ("server's PID is %lu\n", (unsigned long)server_pid
);
1123 /* gpg-connect-agent's entry point. */
1125 main (int argc
, char **argv
)
1127 ARGPARSE_ARGS pargs
;
1128 int no_more_options
= 0;
1129 assuan_context_t ctx
;
1135 const char *opt_run
= NULL
;
1136 FILE *script_fp
= NULL
;
1137 int use_tty
, keep_line
;
1143 unsigned int nestlevel
;
1148 char **cmdline_commands
= NULL
;
1150 gnupg_rl_initialize ();
1151 set_strusage (my_strusage
);
1152 log_set_prefix ("gpg-connect-agent", 1);
1154 /* Make sure that our subsystems are ready. */
1156 init_common_subsystems ();
1158 assuan_set_assuan_err_source (0);
1161 opt
.homedir
= default_homedir ();
1162 opt
.connect_flags
= 1; /* Use extended connect mode. */
1164 /* Parse the command line. */
1167 pargs
.flags
= 1; /* Do not remove the args. */
1168 while (!no_more_options
&& optfile_parse (NULL
, NULL
, NULL
, &pargs
, opts
))
1170 switch (pargs
.r_opt
)
1172 case oQuiet
: opt
.quiet
= 1; break;
1173 case oVerbose
: opt
.verbose
++; break;
1174 case oNoVerbose
: opt
.verbose
= 0; break;
1175 case oHomedir
: opt
.homedir
= pargs
.r
.ret_str
; break;
1176 case oHex
: opt
.hex
= 1; break;
1177 case oDecode
: opt
.decode
= 1; break;
1178 case oRawSocket
: opt
.raw_socket
= pargs
.r
.ret_str
; break;
1179 case oExec
: opt
.exec
= 1; break;
1180 case oNoExtConnect
: opt
.connect_flags
&= ~(1); break;
1181 case oRun
: opt_run
= pargs
.r
.ret_str
; break;
1183 opt
.enable_varsubst
= 1;
1184 opt
.trim_leading_spaces
= 1;
1187 default: pargs
.err
= 2; break;
1191 if (log_get_errorcount (0))
1194 use_tty
= (isatty ( fileno (stdin
)) && isatty (fileno (stdout
)));
1200 log_error (_("option \"%s\" requires a program "
1201 "and optional arguments\n"), "--exec" );
1206 cmdline_commands
= argv
;
1208 if (opt
.exec
&& opt
.raw_socket
)
1209 log_info (_("option \"%s\" ignored due to \"%s\"\n"),
1210 "--raw-socket", "--exec");
1212 if (opt_run
&& !(script_fp
= fopen (opt_run
, "r")))
1214 log_error ("cannot open run file `%s': %s\n",
1215 opt_run
, strerror (errno
));
1224 no_close
[0] = fileno (stderr
);
1225 no_close
[1] = log_get_fd ();
1227 rc
= assuan_pipe_connect_ext (&ctx
, *argv
, (const char **)argv
,
1228 no_close
, NULL
, NULL
,
1232 log_error ("assuan_pipe_connect_ext failed: %s\n",
1238 log_info ("server `%s' started\n", *argv
);
1241 else if (opt
.raw_socket
)
1243 rc
= assuan_socket_connect_ext (&ctx
, opt
.raw_socket
, 0,
1247 log_error ("can't connect to socket `%s': %s\n",
1248 opt
.raw_socket
, gpg_strerror (rc
));
1253 log_info ("connection to socket `%s' established\n", opt
.raw_socket
);
1256 ctx
= start_agent ();
1258 /* See whether there is a line pending from the server (in case
1259 assuan did not run the initial handshaking). */
1260 if (assuan_pending_line (ctx
))
1262 rc
= read_and_print_response (ctx
, &cmderr
);
1264 log_info (_("receiving line failed: %s\n"), gpg_strerror (rc
) );
1268 for (loopidx
=0; loopidx
< DIM (loopstack
); loopidx
++)
1269 loopstack
[loopidx
].collecting
= 0;
1277 size_t maxlength
= 2048;
1279 assert (loopidx
< (int)DIM (loopstack
));
1280 if (loopidx
>= 0 && loopstack
[loopidx
].current
)
1284 line
= xstrdup (loopstack
[loopidx
].current
->line
);
1286 /* Never go beyond of the final /end. */
1287 if (loopstack
[loopidx
].current
->next
)
1288 loopstack
[loopidx
].current
= loopstack
[loopidx
].current
->next
;
1289 else if (!strncmp (line
, "/end", 4) && (!line
[4]||spacep(line
+4)))
1292 log_fatal ("/end command vanished\n");
1294 else if (cmdline_commands
&& *cmdline_commands
&& !script_fp
)
1298 line
= xstrdup (*cmdline_commands
);
1304 else if (use_tty
&& !script_fp
)
1308 line
= tty_get ("> ");
1310 if (n
==1 && *line
== CONTROL_D
)
1324 n
= read_line (script_fp
? script_fp
:stdin
,
1325 &line
, &linesize
, &maxlength
);
1329 log_error (_("error reading input: %s\n"), strerror (errno
));
1334 log_error ("stopping script execution\n");
1347 log_info ("end of script\n");
1354 log_error (_("line too long - skipped\n"));
1357 if (memchr (line
, 0, n
))
1358 log_info (_("line shortened due to embedded Nul character\n"));
1359 if (line
[n
-1] == '\n')
1362 if (opt
.trim_leading_spaces
)
1364 const char *s
= line
;
1377 if (loopidx
+1 >= 0 && loopstack
[loopidx
+1].collecting
)
1381 ll
= xmalloc (sizeof *ll
+ strlen (line
));
1383 strcpy (ll
->line
, line
);
1384 *loopstack
[loopidx
+1].tail
= ll
;
1385 loopstack
[loopidx
+1].tail
= &ll
->next
;
1387 if (!strncmp (line
, "/end", 4) && (!line
[4]||spacep(line
+4)))
1388 loopstack
[loopidx
+1].nestlevel
--;
1389 else if (!strncmp (line
, "/while", 6) && (!line
[6]||spacep(line
+6)))
1390 loopstack
[loopidx
+1].nestlevel
++;
1392 if (loopstack
[loopidx
+1].nestlevel
)
1394 /* We reached the corresponding /end. */
1395 loopstack
[loopidx
+1].collecting
= 0;
1401 /* Handle control commands. */
1404 for (p
=cmd
; *p
&& !spacep (p
); p
++)
1410 if (!strcmp (cmd
, "let"))
1412 assign_variable (p
, 0);
1414 else if (!strcmp (cmd
, "slet"))
1416 /* Deprecated - never used in a released version. */
1417 assign_variable (p
, 1);
1419 else if (!strcmp (cmd
, "showvar"))
1423 else if (!strcmp (cmd
, "definq"))
1425 tmpline
= opt
.enable_varsubst
? substitute_line (p
) : NULL
;
1428 add_definq (tmpline
, 1, 0);
1432 add_definq (p
, 1, 0);
1434 else if (!strcmp (cmd
, "definqfile"))
1436 tmpline
= opt
.enable_varsubst
? substitute_line (p
) : NULL
;
1439 add_definq (tmpline
, 0, 0);
1443 add_definq (p
, 0, 0);
1445 else if (!strcmp (cmd
, "definqprog"))
1447 tmpline
= opt
.enable_varsubst
? substitute_line (p
) : NULL
;
1450 add_definq (tmpline
, 0, 1);
1454 add_definq (p
, 0, 1);
1456 else if (!strcmp (cmd
, "datafile"))
1460 if (current_datasink
)
1462 if (current_datasink
!= stdout
)
1463 fclose (current_datasink
);
1464 current_datasink
= NULL
;
1466 tmpline
= opt
.enable_varsubst
? substitute_line (p
) : NULL
;
1467 fname
= tmpline
? tmpline
: p
;
1468 if (fname
&& !strcmp (fname
, "-"))
1469 current_datasink
= stdout
;
1470 else if (fname
&& *fname
)
1472 current_datasink
= fopen (fname
, "wb");
1473 if (!current_datasink
)
1474 log_error ("can't open `%s': %s\n",
1475 fname
, strerror (errno
));
1479 else if (!strcmp (cmd
, "showdef"))
1483 else if (!strcmp (cmd
, "cleardef"))
1487 else if (!strcmp (cmd
, "echo"))
1489 tmpline
= opt
.enable_varsubst
? substitute_line (p
) : NULL
;
1498 else if (!strcmp (cmd
, "sendfd"))
1500 tmpline
= opt
.enable_varsubst
? substitute_line (p
) : NULL
;
1503 do_sendfd (ctx
, tmpline
);
1510 else if (!strcmp (cmd
, "recvfd"))
1512 tmpline
= opt
.enable_varsubst
? substitute_line (p
) : NULL
;
1515 do_recvfd (ctx
, tmpline
);
1522 else if (!strcmp (cmd
, "open"))
1524 tmpline
= opt
.enable_varsubst
? substitute_line (p
) : NULL
;
1533 else if (!strcmp (cmd
, "close"))
1535 tmpline
= opt
.enable_varsubst
? substitute_line (p
) : NULL
;
1544 else if (!strcmp (cmd
, "showopen"))
1548 else if (!strcmp (cmd
, "serverpid"))
1552 else if (!strcmp (cmd
, "hex"))
1554 else if (!strcmp (cmd
, "nohex"))
1556 else if (!strcmp (cmd
, "decode"))
1558 else if (!strcmp (cmd
, "nodecode"))
1560 else if (!strcmp (cmd
, "subst"))
1562 opt
.enable_varsubst
= 1;
1563 opt
.trim_leading_spaces
= 1;
1565 else if (!strcmp (cmd
, "nosubst"))
1566 opt
.enable_varsubst
= 0;
1567 else if (!strcmp (cmd
, "run"))
1571 for (p2
=p
; *p2
&& !spacep (p2
); p2
++)
1579 log_error ("syntax error in run command\n");
1588 log_error ("cannot nest run commands - stop\n");
1592 else if (!(script_fp
= fopen (p
, "r")))
1594 log_error ("cannot open run file `%s': %s\n",
1595 p
, strerror (errno
));
1597 else if (opt
.verbose
)
1598 log_info ("running commands from `%s'\n", p
);
1600 else if (!strcmp (cmd
, "while"))
1602 if (loopidx
+2 >= (int)DIM(loopstack
))
1604 log_error ("blocks are nested too deep\n");
1605 /* We should better die or break all loop in this
1606 case as recovering from this error won't be
1611 loopstack
[loopidx
+1].head
= NULL
;
1612 loopstack
[loopidx
+1].tail
= &loopstack
[loopidx
+1].head
;
1613 loopstack
[loopidx
+1].current
= NULL
;
1614 loopstack
[loopidx
+1].nestlevel
= 1;
1615 loopstack
[loopidx
+1].oneshot
= 0;
1616 loopstack
[loopidx
+1].condition
= xstrdup (p
);
1617 loopstack
[loopidx
+1].collecting
= 1;
1620 else if (!strcmp (cmd
, "if"))
1622 if (loopidx
+2 >= (int)DIM(loopstack
))
1624 log_error ("blocks are nested too deep\n");
1628 /* Note that we need to evaluate the condition right
1629 away and not just at the end of the block as we
1631 loopstack
[loopidx
+1].head
= NULL
;
1632 loopstack
[loopidx
+1].tail
= &loopstack
[loopidx
+1].head
;
1633 loopstack
[loopidx
+1].current
= NULL
;
1634 loopstack
[loopidx
+1].nestlevel
= 1;
1635 loopstack
[loopidx
+1].oneshot
= 1;
1636 loopstack
[loopidx
+1].condition
= substitute_line_copy (p
);
1637 loopstack
[loopidx
+1].collecting
= 1;
1640 else if (!strcmp (cmd
, "end"))
1643 log_error ("stray /end command encountered - ignored\n");
1650 /* Evaluate the condition. */
1651 tmpcond
= xstrdup (loopstack
[loopidx
].condition
);
1652 if (loopstack
[loopidx
].oneshot
)
1654 xfree (loopstack
[loopidx
].condition
);
1655 loopstack
[loopidx
].condition
= xstrdup ("0");
1657 tmpline
= substitute_line (tmpcond
);
1658 value
= tmpline
? tmpline
: tmpcond
;
1659 condition
= strtol (value
, NULL
, 0);
1666 loopstack
[loopidx
].current
= loopstack
[loopidx
].head
;
1671 while (loopstack
[loopidx
].head
)
1673 loopline_t tmp
= loopstack
[loopidx
].head
->next
;
1674 xfree (loopstack
[loopidx
].head
);
1675 loopstack
[loopidx
].head
= tmp
;
1677 loopstack
[loopidx
].tail
= NULL
;
1678 loopstack
[loopidx
].current
= NULL
;
1679 loopstack
[loopidx
].nestlevel
= 0;
1680 loopstack
[loopidx
].collecting
= 0;
1681 loopstack
[loopidx
].oneshot
= 0;
1682 xfree (loopstack
[loopidx
].condition
);
1683 loopstack
[loopidx
].condition
= NULL
;
1688 else if (!strcmp (cmd
, "bye"))
1692 else if (!strcmp (cmd
, "sleep"))
1696 else if (!strcmp (cmd
, "help"))
1699 "Available commands:\n"
1700 "/echo ARGS Echo ARGS.\n"
1701 "/let NAME VALUE Set variable NAME to VALUE.\n"
1702 "/showvar Show all variables.\n"
1703 "/definq NAME VAR Use content of VAR for inquiries with NAME.\n"
1704 "/definqfile NAME FILE Use content of FILE for inquiries with NAME.\n"
1705 "/definqprog NAME PGM Run PGM for inquiries with NAME.\n"
1706 "/datafile [NAME] Write all D line content to file NAME.\n"
1707 "/showdef Print all definitions.\n"
1708 "/cleardef Delete all definitions.\n"
1709 "/sendfd FILE MODE Open FILE and pass descriptor to server.\n"
1710 "/recvfd Receive FD from server and print.\n"
1711 "/open VAR FILE MODE Open FILE and assign the file descriptor to VAR.\n"
1712 "/close FD Close file with descriptor FD.\n"
1713 "/showopen Show descriptors of all open files.\n"
1714 "/serverpid Retrieve the pid of the server.\n"
1715 "/[no]hex Enable hex dumping of received data lines.\n"
1716 "/[no]decode Enable decoding of received data lines.\n"
1717 "/[no]subst Enable variable substitution.\n"
1718 "/run FILE Run commands from FILE.\n"
1719 "/if VAR Begin conditional block controlled by VAR.\n"
1720 "/while VAR Begin loop controlled by VAR.\n"
1721 "/end End loop or condition\n"
1722 "/bye Terminate gpg-connect-agent.\n"
1723 "/help Print this help.");
1726 log_error (_("unknown command `%s'\n"), cmd
);
1731 if (opt
.verbose
&& script_fp
)
1734 tmpline
= opt
.enable_varsubst
? substitute_line (line
) : NULL
;
1737 rc
= assuan_write_line (ctx
, tmpline
);
1741 rc
= assuan_write_line (ctx
, line
);
1744 log_info (_("sending line failed: %s\n"), gpg_strerror (rc
) );
1747 if (*line
== '#' || !*line
)
1748 continue; /* Don't expect a response for a comment line. */
1750 rc
= read_and_print_response (ctx
, &cmderr
);
1752 log_info (_("receiving line failed: %s\n"), gpg_strerror (rc
) );
1753 if ((rc
|| cmderr
) && script_fp
)
1755 log_error ("stopping script execution\n");
1761 /* FIXME: If the last command was BYE or the server died for
1762 some other reason, we won't notice until we get the next
1763 input command. Probing the connection with a non-blocking
1764 read could help to notice termination or other problems
1769 log_info ("closing connection to agent\n");
1775 /* Handle an Inquire from the server. Return False if it could not be
1776 handled; in this case the caller shll complete the operation. LINE
1777 is the complete line as received from the server. This function
1778 may change the content of LINE. */
1780 handle_inquire (assuan_context_t ctx
, char *line
)
1788 /* Skip the command and trailing spaces. */
1789 for (; *line
&& !spacep (line
); line
++)
1791 while (spacep (line
))
1795 for (; *line
&& !spacep (line
); line
++)
1800 /* Now match it against our list. The second loop is there to
1801 detect the match-all entry. */
1802 for (d
=definq_list
; d
; d
= d
->next
)
1803 if (d
->name
&& !strcmp (d
->name
, name
))
1806 for (d
=definq_list
; d
; d
= d
->next
)
1812 log_info ("no handler for inquiry `%s' found\n", name
);
1818 char *tmpvalue
= get_var_ext (d
->file
);
1819 rc
= assuan_send_data (ctx
, tmpvalue
, strlen (tmpvalue
));
1822 log_error ("sending data back failed: %s\n", gpg_strerror (rc
) );
1828 fp
= popen (d
->file
, "r");
1830 log_error ("error executing `%s': %s\n",
1831 d
->file
, strerror (errno
));
1832 else if (opt
.verbose
)
1833 log_error ("handling inquiry `%s' by running `%s'\n",
1838 fp
= fopen (d
->file
, "rb");
1840 log_error ("error opening `%s': %s\n", d
->file
, strerror (errno
));
1841 else if (opt
.verbose
)
1842 log_error ("handling inquiry `%s' by returning content of `%s'\n",
1848 while ( (n
= fread (buffer
, 1, sizeof buffer
, fp
)) )
1850 rc
= assuan_send_data (ctx
, buffer
, n
);
1853 log_error ("sending data back failed: %s\n", gpg_strerror (rc
) );
1858 log_error ("error reading from `%s': %s\n", d
->file
, strerror (errno
));
1861 rc
= assuan_send_data (ctx
, NULL
, 0);
1863 log_error ("sending data back failed: %s\n", gpg_strerror (rc
) );
1867 else if (d
->is_prog
)
1870 log_error ("error running `%s': %s\n", d
->file
, strerror (errno
));
1878 /* Read all response lines from server and print them. Returns 0 on
1879 success or an assuan error code. Set R_GOTERR to true if the
1880 command did not returned OK. */
1882 read_and_print_response (assuan_context_t ctx
, int *r_goterr
)
1895 rc
= assuan_read_line (ctx
, &line
, &linelen
);
1899 if (opt
.verbose
> 1 && *line
== '#')
1901 fwrite (line
, linelen
, 1, stdout
);
1905 while (*line
== '#' || !linelen
);
1908 && line
[0] == 'D' && line
[1] == ' ')
1910 if (current_datasink
)
1912 const unsigned char *s
;
1915 for (j
=2, s
=(unsigned char*)line
+2; j
< linelen
; j
++, s
++ )
1917 if (*s
== '%' && j
+2 < linelen
)
1925 putc (c
, current_datasink
);
1930 for (i
=2; i
< linelen
; )
1934 printf ("D[%04X] ", i
-2);
1935 for (j
=0; j
< 16 ; j
++, i
++)
1940 printf (" %02X", ((unsigned char*)line
)[i
]);
1942 fputs (" ", stdout
);
1944 fputs (" ", stdout
);
1946 for (j
=0; j
< 16; j
++, i
++)
1948 unsigned int c
= ((unsigned char*)line
)[i
];
1951 else if (isascii (c
) && isprint (c
) && !iscntrl (c
))
1959 else if (opt
.decode
)
1961 const unsigned char *s
;
1965 for (j
=2, s
=(unsigned char*)line
+2; j
< linelen
; j
++, s
++ )
1969 fputs ("D ", stdout
);
1972 if (*s
== '%' && j
+2 < linelen
)
1984 need_lf
= (c
!= '\n');
1988 fwrite (line
, linelen
, 1, stdout
);
1996 if (!current_datasink
|| current_datasink
!= stdout
)
2003 && (line
[1] == '\0' || line
[1] == ' '))
2005 if (!current_datasink
|| current_datasink
!= stdout
)
2007 fwrite (line
, linelen
, 1, stdout
);
2011 else if (linelen
>= 2
2012 && line
[0] == 'O' && line
[1] == 'K'
2013 && (line
[2] == '\0' || line
[2] == ' '))
2015 if (!current_datasink
|| current_datasink
!= stdout
)
2017 fwrite (line
, linelen
, 1, stdout
);
2020 set_int_var ("?", 0);
2023 else if (linelen
>= 3
2024 && line
[0] == 'E' && line
[1] == 'R' && line
[2] == 'R'
2025 && (line
[3] == '\0' || line
[3] == ' '))
2029 errval
= strtol (line
+3, NULL
, 10);
2032 set_int_var ("?", errval
);
2033 if (!current_datasink
|| current_datasink
!= stdout
)
2035 fwrite (line
, linelen
, 1, stdout
);
2041 else if (linelen
>= 7
2042 && line
[0] == 'I' && line
[1] == 'N' && line
[2] == 'Q'
2043 && line
[3] == 'U' && line
[4] == 'I' && line
[5] == 'R'
2045 && (line
[7] == '\0' || line
[7] == ' '))
2047 if (!current_datasink
|| current_datasink
!= stdout
)
2049 fwrite (line
, linelen
, 1, stdout
);
2052 if (!handle_inquire (ctx
, line
))
2053 assuan_write_line (ctx
, "CANCEL");
2055 else if (linelen
>= 3
2056 && line
[0] == 'E' && line
[1] == 'N' && line
[2] == 'D'
2057 && (line
[3] == '\0' || line
[3] == ' '))
2059 if (!current_datasink
|| current_datasink
!= stdout
)
2061 fwrite (line
, linelen
, 1, stdout
);
2064 /* Received from server, thus more responses are expected. */
2067 return gpg_error (GPG_ERR_ASS_INV_RESPONSE
);
2075 /* Connect to the agent and send the standard options. */
2076 static assuan_context_t
2081 assuan_context_t ctx
;
2082 session_env_t session_env
;
2084 session_env
= session_env_new ();
2086 log_fatal ("error allocating session environment block: %s\n",
2089 infostr
= getenv ("GPG_AGENT_INFO");
2090 if (!infostr
|| !*infostr
)
2094 /* Check whether we can connect at the standard socket. */
2095 sockname
= make_filename (opt
.homedir
, "S.gpg-agent", NULL
);
2096 rc
= assuan_socket_connect (&ctx
, sockname
, 0);
2098 #ifdef HAVE_W32_SYSTEM
2099 /* If we failed to connect under Windows, we fire up the agent. */
2100 if (gpg_err_code (rc
) == GPG_ERR_ASS_CONNECT_FAILED
)
2102 const char *agent_program
;
2103 const char *argv
[3];
2107 log_info (_("no running gpg-agent - starting one\n"));
2108 agent_program
= gnupg_module_name (GNUPG_MODULE_NAME_AGENT
);
2110 argv
[0] = "--daemon";
2111 argv
[1] = "--use-standard-socket";
2114 rc
= gnupg_spawn_process_detached (agent_program
, argv
, NULL
);
2116 log_debug ("failed to start agent `%s': %s\n",
2117 agent_program
, gpg_strerror (rc
));
2120 /* Give the agent some time to prepare itself. */
2122 /* Now try again to connect the agent. */
2123 rc
= assuan_socket_connect (&ctx
, sockname
, 0);
2128 #endif /*HAVE_W32_SYSTEM*/
2136 infostr
= xstrdup (infostr
);
2137 if ( !(p
= strchr (infostr
, PATHSEP_C
)) || p
== infostr
)
2139 log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
2145 while (*p
&& *p
!= PATHSEP_C
)
2147 prot
= *p
? atoi (p
+1) : 0;
2150 log_error (_("gpg-agent protocol version %d is not supported\n"),
2156 rc
= assuan_socket_connect (&ctx
, infostr
, pid
);
2162 log_error ("can't connect to the agent: %s\n", gpg_strerror (rc
));
2167 log_info ("connection to agent established\n");
2169 rc
= assuan_transact (ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2172 log_error (_("error sending %s command: %s\n"), "RESET",
2177 rc
= send_pinentry_environment (ctx
, GPG_ERR_SOURCE_DEFAULT
,
2178 NULL
, NULL
, session_env
);
2181 log_error (_("error sending standard options: %s\n"), gpg_strerror (rc
));