2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of libpwmd.
8 Libpwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Libpwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Libpwmd. If not, see <http://www.gnu.org/licenses/>.
34 #include <sys/select.h>
36 #include <sys/types.h>
44 #include <gnutls/gnutls.h>
51 #ifdef HAVE_GETOPT_LONG
56 #include "getopt_long.h"
59 #ifdef HAVE_LIBREADLINE
60 #if defined(HAVE_READLINE_READLINE_H)
61 #include <readline/readline.h>
62 #elif defined(HAVE_READLINE_H)
64 #endif /* !defined(HAVE_READLINE_H) */
65 static int interactive_error
;
66 static int interactive
;
67 #endif /* HAVE_LIBREADLINE */
69 #ifdef HAVE_READLINE_HISTORY
70 #if defined(HAVE_READLINE_HISTORY_H)
71 #include <readline/history.h>
72 #elif defined(HAVE_HISTORY_H)
75 #endif /* HAVE_READLINE_HISTORY */
82 #define N_(msgid) gettext(msgid)
87 #define DEFAULT_STATUS_IGNORE "KEEPALIVE,STATE,GPGME,PASSPHRASE_INFO,PASSPHRASE_HINT"
88 #define DEFAULT_PIN_TIMEOUT 30
89 #define DEFAULT_PIN_TRIES 3
90 #define FINISH(rc) (gpg_err_source(rc) == GPG_ERR_SOURCE_UNKNOWN) \
93 static int no_pinentry
;
95 static char *filename
;
98 static char *sign_keyid
;
100 static char *keyparams
;
101 static char *keyfile
;
102 static char *new_keyfile
;
103 static char *sign_keyfile
;
105 static int local_pin
;
106 static int inquirefd
;
110 static char **status_ignore
;
117 size_t size
; // from stat(2).
121 static gpg_error_t
finalize ();
122 static gpg_error_t
set_inquire (int fd
, const char *line
,
123 struct inquire_s
**result
);
124 static gpg_error_t
parse_dotcommand (const char *line
, char **result
,
125 size_t * len
, struct inquire_s
*inq
);
126 static gpg_error_t
open_command (char *line
);
128 static gpg_error_t
get_password (char **result
, pwmd_pinentry_t w
, int echo
);
132 show_error (pwm_t
*pwm
, gpg_error_t rc
, const char *str
)
135 if (pwmd_tls_error (pwm
))
136 fprintf(stderr
, "TLS: %s\n", gnutls_strerror(pwmd_tls_error(pwm
)));
138 fprintf (stderr
, "ERR %i: %s%s%s%s", rc
, gpg_strerror (rc
),
139 str
? ": " : "", str
? str
: "", str
? "" : "\n");
146 pwmd_free (new_keyfile
);
147 pwmd_free (sign_keyfile
);
148 keyfile
= new_keyfile
= sign_keyfile
= NULL
;
152 usage (const char *pn
, int status
)
154 fprintf (status
== EXIT_FAILURE
? stderr
: stdout
,
155 N_("Usage: pwmc [options] [file]\n"
157 " a url string to connect to (%s, see below)\n"
158 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
159 " --connect-timeout <seconds>\n"
160 " seconds before connecting to a remote host fails (0=disabled, 120)\n"
161 " --socket-timeout <seconds>\n"
162 " seconds before a remote command fails (0=disabled, 300)\n"
165 " --ca-cert <filename>\n"
166 " certificate authority (CA) used to sign the server cert\n"
167 " --client-cert <filename>\n"
168 " client certificate to use for authentication\n"
169 " --client-key <filename>\n"
170 " key file used to protect the client certificate\n"
171 " --tls-priority <string>\n"
172 " compression, cipher and hash algorithm string\n"
173 " (SECURE256:SECURE192:SECURE128:-VERS-SSL3.0)\n"
175 " verify the hostname against the server certificate\n"
176 " --tls-fingerprint <string>\n"
177 " a SHA-256 hash of the server fingerprint to verify against\n"
181 " disable SSH agent use (enabled when SSH_AUTH_SOCK is set)\n"
182 " --identity, -i <filename>\n"
183 " the ssh identity file to use for authentication\n"
184 " --knownhosts, -k <filename>\n"
185 " the ssh knownhosts file to use (~/.ssh/knownhosts)\n"
186 " --ssh-needs-passphrase\n"
187 " prompt for a passphrase for the SSH identity file\n"
190 " do not lock the data file upon opening it\n"
191 " --lock-timeout <N>\n"
192 " time in tenths of a second to wait for a locked data file (50)\n"
193 " --name, -n <string>\n"
194 " set the client name\n"
195 " --pinentry <path>\n"
196 " the full path to the pinentry binary\n"
197 " --local-pinentry\n"
198 " force using a local pinentry\n"
200 " disable pinentry both remotely and locally\n"
201 " --ttyname, -y <path>\n"
202 " tty that pinentry will use\n"
203 " --ttytype, -t <string>\n"
204 " pinentry terminal type (default is $TERM)\n"
206 " pinentry display (default is $DISPLAY)\n"
207 " --lc-ctype <string>\n"
208 " locale setting for pinentry\n"
209 " --lc-messages <string>\n"
210 " locale setting for pinentry\n"
212 " number of pinentry tries before failing (3)\n"
213 " --timeout <seconds>\n"
214 " pinentry timeout\n"
215 " --inquire <COMMAND>\n"
216 " the specified command (with any options) uses a server inquire while\n"
217 " command data is read via the inquire file descriptor (stdin)\n"
218 " --inquire-line, -L <STRING>\n"
219 " the initial line to send (i.e., element path) before the inquire data\n"
220 " --inquire-fd <FD>\n"
221 " read inquire data from the specified file descriptor (stdin)\n"
222 " --inquire-file <filename>\n"
223 " read inquire data from the specified filename\n"
224 " --output-fd <FD>\n"
225 " redirect command output to the specified file descriptor\n"
227 " send the SAVE command before exiting\n"
228 " --passphrase-file <filename>\n"
229 " obtain the passphrase from the specified filename\n"
230 " --new-passphrase-file <filename>\n"
231 " obtain the passphrase to save with from the specified filename\n"
232 " --sign-passphrase-file <filename>\n"
233 " obtain the passphrase to sign with (symmetric) from the specified filename\n"
234 " --key-params <filename>\n"
235 " key parameters to use for key generation (pwmd default)\n"
236 " --keyid <recipient>[,<recipient>]\n"
237 " the public key ID to u\n"
238 " --sign-keyid <string>\n"
239 " the key ID to sign the data file with\n"
241 " use conventional encryption with optional signer(s) for new files\n"
243 " disable showing of status messages from the server\n"
244 " --status-fd <FD>\n"
245 " redirect status messages to the specified file descriptor\n"
246 " --status-ignore <string[,...]>\n"
247 " prevent parsing of the specified status message keywords\n"
249 " disable showing of extra messages (implies --no-status)\n"
250 #ifdef HAVE_LIBREADLINE
252 " use a shell like interface to pwmd (allows more than one command)\n"
256 #ifdef DEFAULT_PWMD_SOCKET
262 fprintf (status
== EXIT_FAILURE
? stderr
: stdout
,
264 "An optional url may be in the form of:\n"
265 " --url /path/to/socket\n"
266 " --url file://[path/to/socket]\n"
269 " --url ssh[46]://[username@]hostname[:port]\n"
270 " --no-ssh-agent -i identity_file --url ssh[46]://[username@]hostname[:port]\n"
274 " --url tls[46]://hostname[:port] --ca-cert filename --client-cert filename\n"
275 " --client-key filename\n"
277 #ifdef HAVE_LIBREADLINE
279 "Interactive mode is used when input is from a terminal.\n"
286 inquire_cb (void *user
, const char *keyword
, gpg_error_t rc
,
287 char **data
, size_t * size
)
289 struct inquire_s
*inq
= user
;
291 int is_newpassword
= 0;
301 if (!strcmp (keyword
, "PASSPHRASE"))
303 else if (!strcmp (keyword
, "SIGN_PASSPHRASE"))
305 else if (!strcmp (keyword
, "NEW_PASSPHRASE"))
307 #ifdef HAVE_LIBREADLINE
308 else if (!strcmp (keyword
, "KEYPARAM") && !interactive
)
311 else if (!strcmp (keyword
, "KEYPARAM"))
315 if (!keyparams
|| !*keyparams
)
316 return gpg_error (GPG_ERR_INV_PARAMETER
);
318 fd
= open (keyparams
, O_RDONLY
);
321 fprintf (stderr
, "%s: %s\n", keyparams
, strerror (errno
));
322 return gpg_error_from_syserror ();
325 rc
= set_inquire (fd
, NULL
, &inq
);
333 fprintf (stderr
, N_("Using file '%s' as %s.\n"), keyparams
, keyword
);
338 if ((is_password
&& !keyfile
) || (is_newpassword
&& !new_keyfile
)
339 || (sign
&& !sign_keyfile
))
343 rc
= pwmd_password (pwm
, keyword
, &tmp
, &inq
->len
);
344 if (rc
&& gpg_err_code (rc
) != GPG_ERR_EOF
)
347 pwmd_free (inq
->line
);
351 return gpg_error (GPG_ERR_EOF
);
353 else if ((is_newpassword
&& new_keyfile
) || (is_password
&& keyfile
)
354 || (sign
&& sign_keyfile
))
359 fd
= open (sign_keyfile
, O_RDONLY
);
361 fd
= open (is_password
|| sign
? keyfile
: new_keyfile
, O_RDONLY
);
366 fprintf (stderr
, "%s: %s\n", sign_keyfile
, strerror (errno
));
368 fprintf (stderr
, "%s: %s\n", is_newpassword
? new_keyfile
369 : keyfile
, strerror (errno
));
370 return gpg_error_from_syserror ();
373 rc
= set_inquire (fd
, NULL
, &inq
);
381 fprintf (stderr
, N_("Using keyfile '%s' as %s.\n"),
382 sign
? sign_keyfile
: is_newpassword
? new_keyfile
385 #ifdef HAVE_LIBREADLINE
386 else if ((!inq
->last_keyword
|| strcmp (keyword
, inq
->last_keyword
))
391 ("%sPress CTRL-D to send the current line. Press twice to end. %s:\n"),
392 inq
->last_keyword
? "\n" : "", keyword
);
393 pwmd_free (inq
->last_keyword
);
394 inq
->last_keyword
= pwmd_strdup (keyword
);
398 /* The first part of the command data. */
404 return inq
->fd
== -1 ? gpg_error (GPG_ERR_EOF
) : 0;
407 *size
= read (inq
->fd
, inq
->line
, ASSUAN_LINELENGTH
);
411 return gpg_error (gpg_error_from_syserror ());
415 else if (inq
->fd
!= STDIN_FILENO
&&
416 (is_newpassword
|| is_password
|| sign
|| is_keyparam
))
424 if (((is_newpassword
&& new_keyfile
) || (is_password
&& keyfile
)
425 || (sign
&& sign_keyfile
) || (keyparams
&& is_keyparam
))
426 && *size
== inq
->size
)
427 return gpg_error (GPG_ERR_EOF
);
429 return *size
? 0 : gpg_error (GPG_ERR_EOF
);
433 status_msg_cb (void *data
, const char *line
)
435 char *p
= strchr (line
, ' ');
438 /* Ignore status messages specified by the client via --status-ignore. */
439 for (s
= status_ignore
; s
&& *s
; s
++)
441 char *tmp
= strchr (line
, ' ');
442 size_t len
= tmp
? strlen (line
) - strlen (tmp
) : strlen (line
);
444 if (!strncmp (line
, *s
, len
) && len
== strlen (*s
))
448 if (interactive
&& !strncmp (line
, "XFER ", 5) && *line
!= '#' && p
449 && strchr (p
, ' ') && *++p
)
451 char *p1
= strchr (p
, ' ');
452 int a
= strtol (p
, NULL
, 10);
454 if (isdigit (*p
) && p1
)
456 int b
= strtol (p1
, NULL
, 10);
458 int t
= a
&& b
? a
* 100 / b
: 0;
460 strncpy (l
, line
, strlen (line
) - strlen (p
) - 1);
461 fprintf (statusfp
, "\rS:%s %i/%i %i%%%s", l
, a
, b
, t
,
468 fprintf (statusfp
, "S:%s\n", line
);
470 #ifdef HAVE_LIBREADLINE
479 return pwmd_process (pwm
);
484 get_password (char **result
, pwmd_pinentry_t w
, int echo
)
486 char buf
[LINE_MAX
] = { 0 }, *p
;
487 struct termios told
, tnew
;
492 if (!isatty (STDIN_FILENO
))
494 fprintf (stderr
, N_("Input is not from a terminal! Failing.\n"));
495 return GPG_ERR_ENOTTY
;
500 if (tcgetattr (STDIN_FILENO
, &told
) == -1)
501 return gpg_error_from_syserror ();
503 memcpy (&tnew
, &told
, sizeof (struct termios
));
504 tnew
.c_lflag
&= ~(ECHO
);
505 tnew
.c_lflag
|= ICANON
| ECHONL
;
507 if (tcsetattr (STDIN_FILENO
, TCSANOW
, &tnew
) == -1)
511 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
512 return gpg_error_from_errno (n
);
518 case PWMD_PINENTRY_OPEN
:
519 fprintf (stderr
, N_("Password for %s: "), filename
);
521 case PWMD_PINENTRY_OPEN_FAILED
:
522 fprintf (stderr
, N_("Invalid password. Password for %s: "), filename
);
524 case PWMD_PINENTRY_SAVE
:
525 fprintf (stderr
, N_("New password for %s: "), filename
);
527 case PWMD_PINENTRY_SAVE_CONFIRM
:
528 fprintf (stderr
, N_("Confirm password: "));
534 if ((p
= fgets (buf
, sizeof (buf
), stdin
)) == NULL
)
537 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
543 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
548 return GPG_ERR_CANCELED
;
551 p
[strlen (p
) - 1] = 0;
555 key
= pwmd_strdup_printf ("%s", p
);
556 memset (&buf
, 0, sizeof (buf
));
559 return GPG_ERR_ENOMEM
;
567 knownhost_cb (void *data
, const char *host
, const char *key
, size_t len
)
571 pwmd_strdup_printf (N_
572 ("Password Manager Daemon: %s\n\nWhile attempting an SSH connection to %s there was a problem verifying it's hostkey against the known and trusted hosts file because it's hostkey was not found.\n\nWould you like to treat this connection as trusted for this and future connections by adding %s's hostkey to the known hosts file?"),
573 (char *) data
, host
, host
);
575 if (no_pinentry
&& !isatty (STDIN_FILENO
))
577 fprintf (stderr
, N_("Input is not from a terminal! Failing.\n"));
579 return GPG_ERR_ENOTTY
;
581 else if (no_pinentry
)
583 for (char *p
= buf
, len
= 0; *p
; p
++, len
++)
592 while (!isspace (*(--p
)));
599 fprintf (stderr
, "%s\n\n", buf
);
606 fprintf (stderr
, N_("Trust this connection [y/N]: "));
608 rc
= get_password (&result
, PWMD_PINENTRY_CONFIRM
, 1);
613 if (!result
|| !*result
|| *result
== 'n' || *result
== 'N')
615 if (result
&& *result
)
618 return GPG_ERR_NOT_CONFIRMED
;
621 if ((*result
== 'y' || *result
== 'Y') && *(result
+ 1) == 0)
630 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DESC
, buf
);
636 return pwmd_getpin (pwm
, NULL
, NULL
, NULL
, PWMD_PINENTRY_CONFIRM
);
640 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
642 is_remote_url (const char *str
)
645 return PWMD_SOCKET_LOCAL
;
648 if (strstr (str
, "ssh://") || strstr (str
, "ssh4://")
649 || strstr (str
, "ssh6://"))
650 return PWMD_SOCKET_SSH
;
654 if (strstr (str
, "tls://") || strstr (str
, "tls4://")
655 || strstr (str
, "tls6://"))
656 return PWMD_SOCKET_TLS
;
659 return PWMD_SOCKET_LOCAL
;
664 escape (const char *str
)
667 char *buf
= pwmd_malloc (ASSUAN_LINELENGTH
+ 1), *b
= buf
;
670 for (p
= str
; *p
; p
++, len
++)
672 if (len
== ASSUAN_LINELENGTH
)
716 free_inquire (struct inquire_s
*inq
)
721 pwmd_free (inq
->line
);
723 if (inq
->fd
!= -1 && inq
->fd
!= STDIN_FILENO
)
726 pwmd_free (inq
->last_keyword
);
730 /* When *result is not NULL it is updated to the new values and not
733 set_inquire (int fd
, const char *line
, struct inquire_s
**result
)
735 struct inquire_s inq
= { 0 };
736 struct stat st
= { 0 };
741 if (fstat (fd
, &st
) == -1)
742 return gpg_error_from_syserror ();
744 inq
.size
= st
.st_size
;
748 inq
.line
= pwmd_calloc (1, ASSUAN_LINELENGTH
);
750 return GPG_ERR_ENOMEM
;
754 char *s
= escape (line
);
758 pwmd_free (inq
.line
);
759 return GPG_ERR_ENOMEM
;
762 if (strlen (s
) >= ASSUAN_LINELENGTH
)
764 pwmd_free (inq
.line
);
766 return GPG_ERR_LINE_TOO_LONG
;
769 strncpy (inq
.line
, s
, ASSUAN_LINELENGTH
- 1);
770 inq
.len
= strlen (s
);
774 rc
= pwmd_setopt (pwm
, PWMD_OPTION_INQUIRE_TOTAL
,
775 st
.st_size
? st
.st_size
+ strlen (inq
.line
) : 0);
778 pwmd_free (inq
.line
);
783 *result
= pwmd_malloc (sizeof (struct inquire_s
));
786 if ((*result
)->fd
!= -1 && (*result
)->fd
!= STDIN_FILENO
)
787 close ((*result
)->fd
);
789 pwmd_free ((*result
)->line
);
790 (*result
)->line
= NULL
;
795 memcpy (*result
, &inq
, sizeof (struct inquire_s
));
796 memset (&inq
, 0, sizeof (struct inquire_s
));
800 #ifdef HAVE_LIBREADLINE
802 interactive_hook (void)
804 interactive_error
= process_cmd ();
806 if (interactive_error
)
807 rl_event_hook
= NULL
;
813 get_readline_char (FILE *fp
)
816 && (!strncmp (rl_line_buffer
, ".set passphrase-file ", 16)
817 || !strncmp (rl_line_buffer
, ".set new-passphrase-file ", 20)
818 || !strncmp (rl_line_buffer
, ".set sign-passphrase-file ", 21)))
819 rl_inhibit_completion
= 0;
820 else if (rl_line_buffer
821 && !strncmp (rl_line_buffer
, ".redir ", 7))
823 char *p
= strchr (rl_line_buffer
, ' ');
825 if (strchr (++p
, ' '))
826 rl_inhibit_completion
= 1;
828 rl_inhibit_completion
= 0;
830 else if (rl_line_buffer
831 && !strncmp (rl_line_buffer
, ".read ", 6))
833 char *p
= rl_line_buffer
+ 6;
835 if (strstr (p
, "--prefix "))
837 p
= strstr (p
, "--prefix ");
844 if (!p
|| strchr (p
, ' '))
845 rl_inhibit_completion
= 1;
847 rl_inhibit_completion
= 0;
850 rl_inhibit_completion
= 1;
860 ("------------------------------------------------------------\n"
861 "Elements are TAB delimited. Type HELP for protocol commands.\n"
862 "Type .help for pwmc commands. Press CTRL-D to quit.\n"
863 "------------------------------------------------------------\n"));
868 parse_arg (const char *src
, char *dst
, size_t len
)
874 for (; s
&& *s
&& *s
!= ' ' && n
< len
; s
++, n
++)
882 parse_opt (char **line
, const char *opt
, gpg_error_t
* rc
)
884 static char result
[ASSUAN_LINELENGTH
] = { 0 }, *r
= result
;
885 char *s
= strstr (*line
, opt
);
895 size_t rlen
= strlen (opt
);
899 while (*p
&& *p
== ' ')
905 for (; *p
&& len
< sizeof (result
) - 1; p
++, rlen
++)
907 if (isspace (*p
) && !quote
)
910 if (*p
== '\"' && lastc
!= '\\')
923 if (len
>= sizeof (result
) - 1)
924 *rc
= GPG_ERR_LINE_TOO_LONG
;
929 while (*p
&& *p
== ' ')
940 read_command (const char *line
, char **result
, size_t * len
)
945 struct inquire_s
*inq
= NULL
;
946 char *p
= (char *) line
;
947 const char *prefix
= parse_opt (&p
, "--prefix", &rc
);
948 char filebuf
[ASSUAN_LINELENGTH
];
957 while (*p
&& isspace (*p
))
960 file
= parse_arg (p
, filebuf
, sizeof (filebuf
));
963 p
+= strlen (file
) + 1;
965 while (*p
&& isspace (*p
))
977 ("Usage: .read [--prefix <string>] <filename> <command> [args]\n"));
980 ("Use '\\' to escape special characters in the --prefix (\\t = TAB, \\\\ = \\)\n"));
984 fd
= open (file
, O_RDONLY
);
986 return gpg_error_from_syserror ();
988 rc
= set_inquire (fd
, prefix
&& *prefix
? prefix
: NULL
, &inq
);
995 rc
= pwmd_command (pwm
, result
, len
, inquire_cb
, inq
, "%s", p
);
1001 redir_command (const char *line
)
1003 const char *p
= line
;
1005 gpg_error_t rc
= GPG_ERR_SYNTAX
;
1007 struct inquire_s
*inq
= NULL
;
1008 char *result
= NULL
;
1010 char filebuf
[ASSUAN_LINELENGTH
];
1012 if (p
&& *p
&& *++p
)
1014 file
= parse_arg (p
, filebuf
, sizeof (filebuf
));
1017 p
+= strlen (file
) + 1;
1019 while (*p
&& isspace (*p
))
1029 fprintf (stderr
, N_("Usage: .redir <filename> <command> [args]\n"));
1033 fd
= open (file
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0600);
1035 return gpg_error_from_syserror ();
1037 #ifdef HAVE_LIBREADLINE
1038 rc
= set_inquire (interactive
? STDIN_FILENO
: inquirefd
, NULL
, &inq
);
1040 rc
= set_inquire (inquirefd
, NULL
, &inq
);
1048 rc
= parse_dotcommand (p
, &result
, &len
, inq
);
1049 if (!rc
&& result
&& len
--)
1050 { // null byte which is always appended
1051 if (write (fd
, result
, len
) != len
)
1052 rc
= GPG_ERR_TOO_SHORT
;
1062 help_command (const char *line
)
1065 N_("Type HELP for protocol commands. Available pwmc commands:\n\n"
1066 " .redir <filename> <command>\n"
1067 " redirect the output of a command to the specified file\n"
1069 " .open <filename>\n"
1070 " open the specified filename losing any changes to the current one\n"
1072 " .read [--prefix <string>] <filename> <command> [args]\n"
1073 " obtain data from the specified filename for an inquire command\n"
1075 " .set help | <name> [<value>]\n"
1076 " set option <name> to <value>\n"
1079 " write changes of the file to disk\n"
1082 " change the passphrase of a data file\n"
1085 " this help text\n"));
1090 open_command (char *line
)
1092 struct inquire_s
*inq
= NULL
;
1093 const char *file
= line
;
1096 while (file
&& isspace (*file
))
1099 if (!file
|| !*file
)
1101 fprintf (stderr
, N_("Usage: .open <filename>\n"));
1102 return GPG_ERR_SYNTAX
;
1105 #ifdef HAVE_LIBREADLINE
1106 if (interactive
|| !quiet
)
1110 fprintf (stderr
, N_("Opening data file \"%s\" ...\n"), file
);
1112 #ifdef HAVE_LIBREADLINE
1113 rc
= set_inquire (interactive
? STDIN_FILENO
: -1, NULL
, &inq
);
1115 rc
= set_inquire (-1, NULL
, &inq
);
1122 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 1);
1124 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, 1);
1128 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
1130 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, no_pinentry
);
1134 rc
= pwmd_open (pwm
, file
, inquire_cb
, inq
);
1136 #ifdef HAVE_LIBREADLINE
1142 if (!rc
&& file
!= filename
)
1144 pwmd_free (filename
);
1145 filename
= pwmd_strdup (file
);
1152 set_command (const char *line
)
1155 char name
[256] = { 0 };
1156 char value
[512] = { 0 };
1159 const char *p
= line
;
1161 while (p
&& *p
&& isspace (*p
))
1164 namep
= parse_arg (p
, name
, sizeof (name
));
1165 if (!namep
|| !*namep
)
1167 fprintf (stderr
, N_("Usage: .set help | <name> [<value>]\n"));
1168 return GPG_ERR_SYNTAX
;
1171 p
+= strlen (namep
);
1172 while (p
&& *p
&& isspace (*p
))
1175 valuep
= parse_arg (p
, value
, sizeof (value
));
1177 if (!strcmp (name
, "passphrase-file") || !strcmp (name
, "new-passphrase-file")
1178 || !strcmp (name
, "sign-passphrase-file"))
1180 int is_newkeyfile
= 1;
1181 int sign
= !strcmp (name
, "sign-passphrase-file");
1183 if (!strcmp (name
, "passphrase-file") || sign
)
1188 pwmd_free (new_keyfile
);
1193 pwmd_free (sign_keyfile
);
1194 sign_keyfile
= NULL
;
1198 pwmd_free (keyfile
);
1205 new_keyfile
= pwmd_strdup (value
);
1207 sign_keyfile
= pwmd_strdup (value
);
1209 keyfile
= pwmd_strdup (value
);
1213 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, 1);
1215 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 1);
1218 else if (!local_pin
&& !no_pinentry
)
1222 pwmd_socket_type (pwm
, &t
);
1223 if (t
== PWMD_SOCKET_LOCAL
)
1225 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, 0);
1227 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
1231 else if (!strcmp(name
, "pinentry-timeout"))
1234 int n
= strtol(valuep
, &e
, 10);
1237 return gpg_error (GPG_ERR_INV_VALUE
);
1240 n
= DEFAULT_PIN_TIMEOUT
;
1242 rc
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TIMEOUT
, n
);
1244 else if (!strcmp (name
, "help"))
1248 ("Set a libpwmd or pwmc option. The option name and optional value is space\n"
1249 "delimited. When no value is specified the option is unset.\n\n"
1250 "passphrase-file [<filename>]\n"
1251 " set or unset the file to be used when a passphrase is required (*)\n"
1253 "new-passphrase-file [<filename>]\n"
1254 " set or unset the file to be used when a new passphrase is required (*)\n"
1256 "sign-passphrase-file [<filename>]\n"
1257 " set or unset the file to be used when a passphrase is required for\n"
1258 " signing (symmetric) (*)\n"
1260 "pinentry-timeout <seconds>\n"
1261 " the amount of seconds before pinentry gives up waiting for input\n"
1263 "* = the next protocol command will unset this value\n"
1267 rc
= GPG_ERR_UNKNOWN_OPTION
;
1273 save_command (const char *line
)
1275 struct inquire_s
*inq
= NULL
;
1278 #ifdef HAVE_LIBREADLINE
1279 rc
= set_inquire (interactive
? STDIN_FILENO
: -1, NULL
, &inq
);
1281 rc
= set_inquire (-1, NULL
, &inq
);
1286 if (new_keyfile
|| keyfile
|| sign_keyfile
)
1288 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 1);
1290 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, 1);
1294 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
1296 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, no_pinentry
);
1300 rc
= pwmd_save (pwm
, line
, inquire_cb
, inq
);
1302 #ifdef HAVE_LIBREADLINE
1312 do_save_passwd_command (const char *line
, int save
)
1314 struct inquire_s
*inq
= NULL
;
1317 #ifdef HAVE_LIBREADLINE
1318 rc
= set_inquire (interactive
? STDIN_FILENO
: -1, NULL
, &inq
);
1320 rc
= set_inquire (-1, NULL
, &inq
);
1325 if (new_keyfile
|| keyfile
|| sign_keyfile
)
1327 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 1);
1329 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, 1);
1333 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
1335 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, no_pinentry
);
1341 rc
= pwmd_save (pwm
, line
, inquire_cb
, inq
);
1343 rc
= pwmd_passwd (pwm
, line
, inquire_cb
, inq
);
1346 #ifdef HAVE_LIBREADLINE
1356 parse_dotcommand (const char *line
, char **result
,
1357 size_t * len
, struct inquire_s
*inq
)
1359 const char *p
= line
;
1362 if (!strncmp (p
, ".read", 5))
1363 rc
= read_command (p
+ 5, result
, len
);
1364 else if (!strncmp (p
, ".redir", 6))
1365 rc
= redir_command (p
+ 6);
1366 else if (!strncmp (p
, ".help", 5))
1367 rc
= help_command (p
+ 5);
1368 else if (!strncmp (p
, ".open", 5))
1369 rc
= open_command ((char *)p
+ 5);
1370 else if (!strncmp (p
, ".set", 4))
1371 rc
= set_command (p
+ 4);
1372 else if (!strncmp (p
, ".save", 5))
1373 rc
= do_save_passwd_command (p
+ 5, 1);
1374 else if (!strncmp (p
, ".passwd", 7))
1375 rc
= do_save_passwd_command (p
+ 7, 0);
1378 rc
= pwmd_command (pwm
, result
, len
, inquire_cb
, inq
, "%s", line
);
1379 #ifdef HAVE_LIBREADLINE
1384 #ifdef HAVE_LIBREADLINE
1392 #ifdef HAVE_LIBREADLINE
1397 struct inquire_s
*inq
= NULL
;
1400 rc
= process_cmd ();
1404 rc
= set_inquire (STDIN_FILENO
, NULL
, &inq
);
1409 N_("WARNING: interactive mode doesn't use secure memory!\n"));
1411 rl_event_hook
= &interactive_hook
;
1412 rl_getc_function
= get_readline_char
;
1413 rl_set_keyboard_input_timeout (100000);
1418 char *result
= NULL
;
1422 line
= readline ("pwmc> ");
1423 if (interactive_error
)
1426 rc
= interactive_error
;
1436 if (gpg_err_code (rc
) != GPG_ERR_CANCELED
&&
1437 gpg_err_code (rc
) != GPG_ERR_EOF
)
1438 fprintf (stderr
, "ERR %i: %s\n", rc
, gpg_strerror (rc
));
1448 #ifdef HAVE_READLINE_HISTORY
1451 rc
= parse_dotcommand (line
, &result
, &len
, inq
);
1457 if (gpg_err_code (rc
) == GPG_ERR_BAD_DATA
)
1458 (void) pwmd_command (pwm
, &tmp
, NULL
, NULL
, NULL
,
1459 "GETINFO last_error");
1461 show_error (pwm
, rc
, tmp
);
1464 else if (result
&& len
)
1465 printf ("%s%s", result
, result
[len
- 1] != '\n' ? "\n" : "");
1479 #ifdef HAVE_LIBREADLINE
1486 fprintf (stderr
, "\n");
1494 ("(c)ancel/(f)orget password/(s)ave/(Q)uit/(S)ave and quit/(h)elp?: "));
1495 p
= fgets (buf
, sizeof (buf
), stdin
);
1509 return GPG_ERR_CANCELED
;
1513 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
,
1514 "CLEARCACHE %s", filename
);
1518 interactive_hook ();
1534 if (save
&& !filename
)
1538 ("No filename was specified on the command line. Aborting.\n"));
1539 return GPG_ERR_CANCELED
;
1542 if (save
&& filename
)
1545 pwmd_strdup_printf ("%s %s%s %s%s %s",
1546 symmetric
? "--symmetric" : "",
1547 keyid
? "--keyid=" : "",
1549 sign_keyid
? "--sign-keyid=" : "",
1550 sign_keyid
? sign_keyid
: "",
1551 keyparams
? "--inquire-keyparam" : "");
1553 #ifdef HAVE_LIBREADLINE
1554 if (!quiet
|| interactive
)
1560 fprintf (stderr
, "\n");
1561 fprintf (stderr
, N_("Saving changes ...\n"));
1564 rc
= save_command (args
);
1568 #ifdef HAVE_LIBREADLINE
1570 return rc
? rc
: quit
? 0 : GPG_ERR_CANCELED
;
1577 parse_status_ignore (char *str
)
1582 for (p
= status_ignore
; p
&& *p
; p
++)
1585 pwmd_free (status_ignore
);
1586 status_ignore
= NULL
;
1590 while ((s
= strsep (&str
, ",")))
1592 p
= pwmd_realloc (status_ignore
, (n
+ 2) * sizeof (char *));
1593 p
[n
++] = pwmd_strdup (s
);
1600 main (int argc
, char *argv
[])
1605 char command
[ASSUAN_LINELENGTH
], *p
= NULL
;
1606 char *result
= NULL
;
1608 char *pinentry_path
= NULL
;
1609 char *display
= NULL
, *tty
= NULL
, *ttytype
= NULL
;
1610 char *lcctype
= NULL
, *lcmessages
= NULL
;
1611 int outfd
= STDOUT_FILENO
;
1612 FILE *outfp
= stdout
;
1613 FILE *inquirefp
= stdin
;
1614 int show_status
= 1;
1615 char *clientname
= "pwmc";
1616 char *inquire
= NULL
;
1617 char *inquire_line
= NULL
;
1620 int use_ssh_agent
= 1;
1621 char *knownhosts
= NULL
;
1622 char *identity
= NULL
;
1625 char *cacert
= NULL
;
1626 char *clientcert
= NULL
;
1627 char *clientkey
= NULL
;
1630 char *tls_fingerprint
= NULL
;
1632 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1633 pwmd_socket_t socktype
;
1634 long socket_timeout
= 300;
1635 int connect_timeout
= 120;
1636 int needs_passphrase
= 0;
1638 int lock_on_open
= 1;
1639 long lock_timeout
= 50;
1642 /* The order is important. */
1645 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1646 OPT_SOCKET_TIMEOUT
, OPT_CONNECT_TIMEOUT
,
1649 OPT_USE_SSH_AGENT
, OPT_IDENTITY
, OPT_KNOWNHOSTS
, OPT_SSH_NEEDS_PASSPHRASE
,
1652 OPT_CACERT
, OPT_CLIENTCERT
, OPT_CLIENTKEY
, OPT_PRIORITY
, OPT_VERIFY
,
1655 OPT_URL
, OPT_LOCAL
, OPT_TTYNAME
, OPT_TTYTYPE
, OPT_DISPLAY
, OPT_LC_CTYPE
,
1656 OPT_LC_MESSAGES
, OPT_TIMEOUT
, OPT_TRIES
, OPT_PINENTRY
, OPT_KEYFILE
,
1657 OPT_PASSPHRASE_FILE
, OPT_NEW_KEYFILE
, OPT_NEW_PASSPHRASE_FILE
,
1658 OPT_SIGN_KEYFILE
, OPT_SIGN_PASSPHRASE_FILE
, OPT_NOLOCK
, OPT_LOCK_TIMEOUT
,
1659 OPT_SAVE
, OPT_OUTPUT_FD
, OPT_INQUIRE
, OPT_INQUIRE_FD
, OPT_INQUIRE_FILE
,
1660 OPT_INQUIRE_LINE
, OPT_NO_STATUS
, OPT_STATUS_IGNORE
, OPT_STATUSFD
, OPT_NAME
,
1661 OPT_VERSION
, OPT_HELP
, OPT_KEYID
, OPT_SIGN_KEYID
, OPT_SYMMETRIC
,
1662 OPT_KEYPARAMS
, OPT_NO_PINENTRY
, OPT_QUIET
,
1663 #ifdef HAVE_LIBREADLINE
1667 const struct option long_opts
[] = {
1668 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1669 {"socket-timeout", 1, 0, 0},
1670 {"connect-timeout", 1, 0, 0},
1674 {"no-ssh-agent", 0, 0, 0},
1675 {"identity", 1, 0, 'i'},
1676 {"knownhosts", 1, 0, 'k'},
1677 {"ssh-needs-passphrase", 0, 0, 0},
1680 {"ca-cert", 1, 0, 0},
1681 {"client-cert", 1, 0, 0},
1682 {"client-key", 1, 0, 0},
1683 {"tls-priority", 1, 0, 0},
1684 {"tls-verify", 0, 0, 0},
1685 {"tls-fingerprint", 1, 0, 0},
1688 {"local-pinentry", 0, 0},
1689 {"ttyname", 1, 0, 'y'},
1690 {"ttytype", 1, 0, 't'},
1691 {"display", 1, 0, 'd'},
1692 {"lc-ctype", 1, 0, 0},
1693 {"lc-messages", 1, 0, 0},
1694 {"timeout", 1, 0, 0},
1696 {"pinentry", 1, 0, 0},
1697 {"key-file", 1, 0, 0},
1698 {"passphrase-file", 1, 0, 0},
1699 {"new-key-file", 1, 0, 0},
1700 {"new-passphrase-file", 1, 0, 0},
1701 {"sign-key-file", 1, 0, 0},
1702 {"sign-passphrase-file", 1, 0, 0},
1703 {"no-lock", 0, 0, 0},
1704 {"lock-timeout", 1, 0, 0},
1705 {"save", 0, 0, 'S'},
1706 {"output-fd", 1, 0, 0},
1707 {"inquire", 1, 0, 0},
1708 {"inquire-fd", 1, 0, 0},
1709 {"inquire-file", 1, 0, 0},
1710 {"inquire-line", 1, 0, 'L'},
1711 {"no-status", 0, 0, 0},
1712 {"status-ignore", 1, 0, 0},
1713 {"status-fd", 1, 0, 0},
1714 {"name", 1, 0, 'n'},
1715 {"version", 0, 0, 0},
1718 {"sign-keyid", 1, 0, 0},
1719 {"symmetric", 0, 0, 0},
1720 {"key-params", 1, 0, 0},
1721 {"no-pinentry", 0, 0, 0},
1723 #ifdef HAVE_LIBREADLINE
1724 {"interactive", 0, 0},
1729 const char *optstring
= "L:y:t:d:P:I:Sn:i:k:s";
1731 const char *optstring
= "L:y:t:d:P:I:Sn:s";
1736 setlocale (LC_ALL
, "");
1737 bindtextdomain ("libpwmd", LOCALEDIR
);
1740 tries
= DEFAULT_PIN_TRIES
;
1741 inquirefd
= STDIN_FILENO
;
1742 statusfd
= STDERR_FILENO
;
1743 statusfp
= fdopen (statusfd
, "w");
1744 tmp
= pwmd_strdup (DEFAULT_STATUS_IGNORE
);
1745 parse_status_ignore (tmp
);
1749 getopt_long (argc
, argv
, optstring
, long_opts
, &opt_index
)) != -1)
1753 /* Handle long options without a short option part. */
1757 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1758 case OPT_SOCKET_TIMEOUT
:
1759 socket_timeout
= strtol (optarg
, &p
, 10);
1761 case OPT_CONNECT_TIMEOUT
:
1762 connect_timeout
= strtol (optarg
, &p
, 10);
1766 case OPT_USE_SSH_AGENT
:
1769 case OPT_SSH_NEEDS_PASSPHRASE
:
1770 needs_passphrase
= 1;
1777 case OPT_CLIENTCERT
:
1778 clientcert
= optarg
;
1790 tls_fingerprint
= optarg
;
1800 case OPT_PASSPHRASE_FILE
:
1801 keyfile
= pwmd_strdup (optarg
);
1803 case OPT_NEW_KEYFILE
:
1804 case OPT_NEW_PASSPHRASE_FILE
:
1805 new_keyfile
= pwmd_strdup (optarg
);
1807 case OPT_SIGN_KEYFILE
:
1808 case OPT_SIGN_PASSPHRASE_FILE
:
1809 sign_keyfile
= pwmd_strdup (optarg
);
1814 case OPT_LOCK_TIMEOUT
:
1815 lock_timeout
= strtol (optarg
, &p
, 10);
1824 lcctype
= pwmd_strdup (optarg
);
1826 case OPT_LC_MESSAGES
:
1827 lcmessages
= pwmd_strdup (optarg
);
1830 timeout
= strtol (optarg
, &p
, 10);
1833 tries
= strtol (optarg
, &p
, 10);
1836 inquire
= escape (optarg
);
1838 case OPT_INQUIRE_FD
:
1839 inquirefd
= strtol (optarg
, &p
, 10);
1842 inquirefp
= fdopen (inquirefd
, "r");
1844 err (EXIT_FAILURE
, "%i", inquirefd
);
1847 case OPT_INQUIRE_FILE
:
1848 inquirefd
= open (optarg
, O_RDONLY
);
1849 if (inquirefd
== -1)
1850 err (EXIT_FAILURE
, "%s", optarg
);
1851 inquirefp
= fdopen (inquirefd
, "r");
1854 outfd
= strtol (optarg
, &p
, 10);
1857 outfp
= fdopen (outfd
, "w");
1859 err (EXIT_FAILURE
, "%i", outfd
);
1866 statusfd
= strtol (optarg
, &p
, 10);
1869 statusfp
= fdopen (statusfd
, "w");
1871 err (EXIT_FAILURE
, "%i", statusfd
);
1874 case OPT_STATUS_IGNORE
:
1875 parse_status_ignore (optarg
);
1878 printf ("%s (pwmc)\n\n"
1879 "Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016\n"
1881 "Released under the terms of the GPL v2. Use at your own risk.\n\n"
1882 "Compile-time features:\n"
1883 #ifdef HAVE_LIBREADLINE
1898 #ifdef WITH_PINENTRY
1913 "\n", PACKAGE_STRING
, PACKAGE_BUGREPORT
);
1914 exit (EXIT_SUCCESS
);
1916 pinentry_path
= optarg
;
1919 usage (argv
[0], EXIT_SUCCESS
);
1923 case OPT_SIGN_KEYID
:
1924 sign_keyid
= optarg
;
1930 case OPT_NO_PINENTRY
:
1933 #ifdef HAVE_LIBREADLINE
1934 case OPT_INTERACTIVE
:
1939 usage (argv
[0], EXIT_FAILURE
);
1944 fprintf (stderr
, N_("%s: invalid argument for option '--%s'\n"),
1945 argv
[0], long_opts
[opt_index
].name
);
1946 usage (argv
[0], EXIT_FAILURE
);
1955 knownhosts
= optarg
;
1959 inquire_line
= optarg
;
1974 clientname
= optarg
;
1977 usage (argv
[0], EXIT_FAILURE
);
1981 #ifdef HAVE_LIBREADLINE
1982 if (interactive
&& !isatty (STDIN_FILENO
))
1983 usage (argv
[0], EXIT_FAILURE
);
1984 else if (isatty (STDIN_FILENO
) && !inquire
&& !inquire_line
)
1989 rc
= pwmd_new (clientname
, &pwm
);
1993 filename
= argv
[optind
] ? pwmd_strdup (argv
[optind
]) : NULL
;
1994 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, no_pinentry
);
1998 pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TRIES
, tries
);
2000 fprintf (stderr
, N_("Connecting ...\n"));
2002 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
2003 socktype
= is_remote_url (url
);
2004 if (socktype
!= PWMD_SOCKET_LOCAL
)
2007 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
2008 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SOCKET_TIMEOUT
, connect_timeout
);
2013 if (socktype
== PWMD_SOCKET_SSH
)
2016 rc
= pwmd_setopt (pwm
, PWMD_OPTION_KNOWNHOST_CB
, knownhost_cb
);
2020 rc
= pwmd_setopt (pwm
, PWMD_OPTION_KNOWNHOST_DATA
, clientname
);
2024 if (!getenv ("SSH_AUTH_SOCK") || identity
)
2027 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SSH_AGENT
, use_ssh_agent
);
2031 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SSH_NEEDS_PASSPHRASE
,
2036 rc
= pwmd_connect (pwm
, url
, identity
, knownhosts
);
2042 rc
= pwmd_setopt (pwm
, PWMD_OPTION_TLS_VERIFY
, tls_verify
);
2046 rc
= pwmd_connect (pwm
, url
, clientcert
, clientkey
, cacert
, prio
,
2052 rc
= pwmd_connect (pwm
, url
);
2054 rc
= pwmd_connect (pwm
, url
);
2060 fprintf (stderr
, N_("Connected.\n"));
2063 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
2064 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SOCKET_TIMEOUT
, socket_timeout
);
2071 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
,
2072 "OPTION LOCK-TIMEOUT=%li", lock_timeout
);
2079 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCK_ON_OPEN
, 1);
2084 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DESC
, NULL
, NULL
);
2090 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TIMEOUT
, timeout
);
2095 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
,
2096 (local_pin
|| keyfile
|| new_keyfile
|| sign_keyfile
));
2102 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_PATH
, pinentry_path
);
2109 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DISPLAY
, display
);
2116 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TTY
, tty
);
2123 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TERM
, ttytype
);
2130 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_LC_CTYPE
, lcctype
);
2137 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_LC_MESSAGES
, lcmessages
);
2144 rc
= pwmd_setopt (pwm
, PWMD_OPTION_STATUS_CB
, status_msg_cb
);
2151 rc
= open_command (filename
);
2156 #ifdef HAVE_LIBREADLINE
2159 rc
= do_interactive ();
2167 struct inquire_s
*inq
= NULL
;
2169 rc
= set_inquire (inquirefd
, inquire_line
, &inq
);
2171 rc
= pwmd_command (pwm
, &result
, &len
, inquire_cb
, inq
, "%s", inquire
);
2177 if (fcntl (STDIN_FILENO
, F_SETFL
, O_NONBLOCK
) == -1)
2179 rc
= gpg_error_from_errno (errno
);
2187 rc
= process_cmd ();
2192 n
= read (STDIN_FILENO
, command
, sizeof (command
)-1);
2195 if (errno
== EAGAIN
)
2201 rc
= gpg_error_from_errno (errno
);
2212 if (!p
|| !*p
|| !strcasecmp (p
, "BYE"))
2216 struct inquire_s
*inq
= NULL
;
2217 rc
= set_inquire (inquirefd
, inquire_line
, &inq
);
2220 rc
= parse_dotcommand (command
, &result
, &len
, inq
);
2230 fwrite (result
, 1, result
[len
- 1] == 0 ? len
- 1 : len
, outfp
);
2238 else if (gpg_err_code (rc
) == GPG_ERR_BAD_DATA
)
2239 (void) pwmd_command (pwm
, &result
, NULL
, NULL
, NULL
,
2240 "GETINFO last_error");
2242 #ifdef HAVE_LIBREADLINE
2245 memset (command
, 0, sizeof (command
));
2248 show_error (pwm
, rc
, result
);
2254 pwmd_free (filename
);
2255 parse_status_ignore (NULL
);
2256 if (connected
&& !quiet
)
2257 fprintf (stderr
, N_("Connection closed.\n"));
2259 exit (rc
? EXIT_FAILURE
: EXIT_SUCCESS
);