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
)
136 int e
= pwmd_gnutls_error (pwm
, &tlsstr
);
139 fprintf(stderr
, "TLS: %s\n", tlsstr
);
141 fprintf (stderr
, "ERR %i: %s%s%s%s", rc
, gpg_strerror (rc
),
142 str
? ": " : "", str
? str
: "", str
? "" : "\n");
149 pwmd_free (new_keyfile
);
150 pwmd_free (sign_keyfile
);
151 keyfile
= new_keyfile
= sign_keyfile
= NULL
;
155 usage (const char *pn
, int status
)
157 fprintf (status
== EXIT_FAILURE
? stderr
: stdout
,
158 N_("Usage: pwmc [options] [file]\n"
160 " a url string to connect to (%s, see below)\n"
161 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
162 " --connect-timeout <seconds>\n"
163 " seconds before connecting to a remote host fails (0=disabled, 120)\n"
164 " --socket-timeout <seconds>\n"
165 " seconds before a remote command fails (0=disabled, 300)\n"
168 " --ca-cert <filename>\n"
169 " certificate authority (CA) used to sign the server cert\n"
170 " --client-cert <filename>\n"
171 " client certificate to use for authentication\n"
172 " --client-key <filename>\n"
173 " key file used to protect the client certificate\n"
174 " --tls-priority <string>\n"
175 " compression, cipher and hash algorithm string\n"
176 " (SECURE256:SECURE192:SECURE128:-VERS-SSL3.0)\n"
178 " verify the hostname against the server certificate\n"
179 " --tls-fingerprint <string>\n"
180 " a SHA-256 hash of the server fingerprint to verify against\n"
184 " disable SSH agent use (enabled when SSH_AUTH_SOCK is set)\n"
185 " --identity, -i <filename>\n"
186 " the ssh identity file to use for authentication\n"
187 " --knownhosts, -k <filename>\n"
188 " the ssh knownhosts file to use (~/.ssh/knownhosts)\n"
189 " --ssh-needs-passphrase\n"
190 " prompt for a passphrase for the SSH identity file\n"
193 " do not lock the data file upon opening it\n"
194 " --lock-timeout <N>\n"
195 " time in tenths of a second to wait for a locked data file (50)\n"
196 " --name, -n <string>\n"
197 " set the client name\n"
198 " --pinentry <path>\n"
199 " the full path to the pinentry binary\n"
200 " --local-pinentry\n"
201 " force using a local pinentry\n"
203 " disable pinentry both remotely and locally\n"
204 " --ttyname, -y <path>\n"
205 " tty that pinentry will use\n"
206 " --ttytype, -t <string>\n"
207 " pinentry terminal type (default is $TERM)\n"
209 " pinentry display (default is $DISPLAY)\n"
210 " --lc-ctype <string>\n"
211 " locale setting for pinentry\n"
212 " --lc-messages <string>\n"
213 " locale setting for pinentry\n"
215 " number of pinentry tries before failing (3)\n"
216 " --timeout <seconds>\n"
217 " pinentry timeout\n"
218 " --inquire <COMMAND>\n"
219 " the specified command (with any options) uses a server inquire while\n"
220 " command data is read via the inquire file descriptor (stdin)\n"
221 " --inquire-line, -L <STRING>\n"
222 " the initial line to send (i.e., element path) before the inquire data\n"
223 " --inquire-fd <FD>\n"
224 " read inquire data from the specified file descriptor (stdin)\n"
225 " --inquire-file <filename>\n"
226 " read inquire data from the specified filename\n"
227 " --output-fd <FD>\n"
228 " redirect command output to the specified file descriptor\n"
230 " send the SAVE command before exiting\n"
231 " --passphrase-file <filename>\n"
232 " obtain the passphrase from the specified filename\n"
233 " --new-passphrase-file <filename>\n"
234 " obtain the passphrase to save with from the specified filename\n"
235 " --sign-passphrase-file <filename>\n"
236 " obtain the passphrase to sign with (symmetric) from the specified filename\n"
237 " --key-params <filename>\n"
238 " key parameters to use for key generation (pwmd default)\n"
239 " --keyid <recipient>[,<recipient>]\n"
240 " the public key ID to u\n"
241 " --sign-keyid <string>\n"
242 " the key ID to sign the data file with\n"
244 " use conventional encryption with optional signer(s) for new files\n"
246 " disable showing of status messages from the server\n"
247 " --status-fd <FD>\n"
248 " redirect status messages to the specified file descriptor\n"
249 " --status-ignore <string[,...]>\n"
250 " prevent parsing of the specified status message keywords\n"
252 " disable showing of extra messages (implies --no-status)\n"
253 #ifdef HAVE_LIBREADLINE
255 " use a shell like interface to pwmd (allows more than one command)\n"
259 #ifdef DEFAULT_PWMD_SOCKET
265 fprintf (status
== EXIT_FAILURE
? stderr
: stdout
,
267 "An optional url may be in the form of:\n"
268 " --url /path/to/socket\n"
269 " --url file://[path/to/socket]\n"
272 " --url ssh[46]://[username@]hostname[:port]\n"
273 " --no-ssh-agent -i identity_file --url ssh[46]://[username@]hostname[:port]\n"
277 " --url tls[46]://hostname[:port] --ca-cert filename --client-cert filename\n"
278 " --client-key filename\n"
280 #ifdef HAVE_LIBREADLINE
282 "Interactive mode is used when input is from a terminal.\n"
289 inquire_cb (void *user
, const char *keyword
, gpg_error_t rc
,
290 char **data
, size_t * size
)
292 struct inquire_s
*inq
= user
;
294 int is_newpassword
= 0;
304 if (!strcmp (keyword
, "PASSPHRASE"))
306 else if (!strcmp (keyword
, "SIGN_PASSPHRASE"))
308 else if (!strcmp (keyword
, "NEW_PASSPHRASE"))
310 #ifdef HAVE_LIBREADLINE
311 else if (!strcmp (keyword
, "KEYPARAM") && !interactive
)
314 else if (!strcmp (keyword
, "KEYPARAM"))
318 if (!keyparams
|| !*keyparams
)
319 return gpg_error (GPG_ERR_INV_PARAMETER
);
321 fd
= open (keyparams
, O_RDONLY
);
324 fprintf (stderr
, "%s: %s\n", keyparams
, strerror (errno
));
325 return gpg_error_from_syserror ();
328 rc
= set_inquire (fd
, NULL
, &inq
);
336 fprintf (stderr
, N_("Using file '%s' as %s.\n"), keyparams
, keyword
);
341 if ((is_password
&& !keyfile
) || (is_newpassword
&& !new_keyfile
)
342 || (sign
&& !sign_keyfile
))
347 /* Try to use the local pinentry between inquires (new/sign/passphrase).
348 * If --no-pinentry was specified then the passphrase is read from the
349 * terminal as usual. */
350 pwmd_getopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, &local
);
351 pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, 1);
352 rc
= pwmd_password (pwm
, keyword
, &tmp
, &inq
->len
);
353 pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, local
);
354 if (rc
&& gpg_err_code (rc
) != GPG_ERR_EOF
)
357 pwmd_free (inq
->line
);
361 return gpg_error (GPG_ERR_EOF
);
363 else if ((is_newpassword
&& new_keyfile
) || (is_password
&& keyfile
)
364 || (sign
&& sign_keyfile
))
369 fd
= open (sign_keyfile
, O_RDONLY
);
371 fd
= open (is_password
|| sign
? keyfile
: new_keyfile
, O_RDONLY
);
376 fprintf (stderr
, "%s: %s\n", sign_keyfile
, strerror (errno
));
378 fprintf (stderr
, "%s: %s\n", is_newpassword
? new_keyfile
379 : keyfile
, strerror (errno
));
380 return gpg_error_from_syserror ();
383 rc
= set_inquire (fd
, NULL
, &inq
);
391 fprintf (stderr
, N_("Using keyfile '%s' as %s.\n"),
392 sign
? sign_keyfile
: is_newpassword
? new_keyfile
395 #ifdef HAVE_LIBREADLINE
396 else if ((!inq
->last_keyword
|| strcmp (keyword
, inq
->last_keyword
))
401 ("%sPress CTRL-D to send the current line. Press twice to end. %s:\n"),
402 inq
->last_keyword
? "\n" : "", keyword
);
403 pwmd_free (inq
->last_keyword
);
404 inq
->last_keyword
= pwmd_strdup (keyword
);
408 /* The first part of the command data. */
414 return inq
->fd
== -1 ? gpg_error (GPG_ERR_EOF
) : 0;
417 *size
= read (inq
->fd
, inq
->line
, ASSUAN_LINELENGTH
);
421 return gpg_error (gpg_error_from_syserror ());
425 else if (inq
->fd
!= STDIN_FILENO
&&
426 (is_newpassword
|| is_password
|| sign
|| is_keyparam
))
434 if (((is_newpassword
&& new_keyfile
) || (is_password
&& keyfile
)
435 || (sign
&& sign_keyfile
) || (keyparams
&& is_keyparam
))
436 && *size
== inq
->size
)
437 return gpg_error (GPG_ERR_EOF
);
439 return *size
? 0 : gpg_error (GPG_ERR_EOF
);
443 status_msg_cb (void *data
, const char *line
)
445 char *p
= strchr (line
, ' ');
448 /* Ignore status messages specified by the client via --status-ignore. */
449 for (s
= status_ignore
; s
&& *s
; s
++)
451 char *tmp
= strchr (line
, ' ');
452 size_t len
= tmp
? strlen (line
) - strlen (tmp
) : strlen (line
);
454 if (!strncmp (line
, *s
, len
) && len
== strlen (*s
))
458 if (interactive
&& !strncmp (line
, "XFER ", 5) && *line
!= '#' && p
459 && strchr (p
, ' ') && *++p
)
461 char *p1
= strchr (p
, ' ');
462 int a
= strtol (p
, NULL
, 10);
464 if (isdigit (*p
) && p1
)
466 int b
= strtol (p1
, NULL
, 10);
468 int t
= a
&& b
? a
* 100 / b
: 0;
470 strncpy (l
, line
, strlen (line
) - strlen (p
) - 1);
471 fprintf (statusfp
, "\rS:%s %i/%i %i%%%s", l
, a
, b
, t
,
478 fprintf (statusfp
, "S:%s\n", line
);
480 #ifdef HAVE_LIBREADLINE
489 return pwmd_process (pwm
);
494 get_password (char **result
, pwmd_pinentry_t w
, int echo
)
496 char buf
[LINE_MAX
] = { 0 }, *p
;
497 struct termios told
, tnew
;
502 if (!isatty (STDIN_FILENO
))
504 fprintf (stderr
, N_("Input is not from a terminal! Failing.\n"));
505 return GPG_ERR_ENOTTY
;
510 if (tcgetattr (STDIN_FILENO
, &told
) == -1)
511 return gpg_error_from_syserror ();
513 memcpy (&tnew
, &told
, sizeof (struct termios
));
514 tnew
.c_lflag
&= ~(ECHO
);
515 tnew
.c_lflag
|= ICANON
| ECHONL
;
517 if (tcsetattr (STDIN_FILENO
, TCSANOW
, &tnew
) == -1)
521 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
522 return gpg_error_from_errno (n
);
528 case PWMD_PINENTRY_OPEN
:
529 fprintf (stderr
, N_("Password for %s: "), filename
);
531 case PWMD_PINENTRY_OPEN_FAILED
:
532 fprintf (stderr
, N_("Invalid password. Password for %s: "), filename
);
534 case PWMD_PINENTRY_SAVE
:
535 fprintf (stderr
, N_("New password for %s: "), filename
);
537 case PWMD_PINENTRY_SAVE_CONFIRM
:
538 fprintf (stderr
, N_("Confirm password: "));
544 if ((p
= fgets (buf
, sizeof (buf
), stdin
)) == NULL
)
547 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
553 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
558 return GPG_ERR_CANCELED
;
561 p
[strlen (p
) - 1] = 0;
565 key
= pwmd_strdup_printf ("%s", p
);
566 memset (&buf
, 0, sizeof (buf
));
569 return GPG_ERR_ENOMEM
;
577 knownhost_cb (void *data
, const char *host
, const char *key
, size_t len
)
581 pwmd_strdup_printf (N_
582 ("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?"),
583 (char *) data
, host
, host
);
585 if (no_pinentry
&& !isatty (STDIN_FILENO
))
587 fprintf (stderr
, N_("Input is not from a terminal! Failing.\n"));
589 return GPG_ERR_ENOTTY
;
591 else if (no_pinentry
)
593 for (char *p
= buf
, len
= 0; *p
; p
++, len
++)
602 while (!isspace (*(--p
)));
609 fprintf (stderr
, "%s\n\n", buf
);
616 fprintf (stderr
, N_("Trust this connection [y/N]: "));
618 rc
= get_password (&result
, PWMD_PINENTRY_CONFIRM
, 1);
623 if (!result
|| !*result
|| *result
== 'n' || *result
== 'N')
625 if (result
&& *result
)
628 return GPG_ERR_NOT_CONFIRMED
;
631 if ((*result
== 'y' || *result
== 'Y') && *(result
+ 1) == 0)
640 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DESC
, buf
);
646 return pwmd_getpin (pwm
, NULL
, NULL
, NULL
, PWMD_PINENTRY_CONFIRM
);
650 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
652 is_remote_url (const char *str
)
655 return PWMD_SOCKET_LOCAL
;
658 if (strstr (str
, "ssh://") || strstr (str
, "ssh4://")
659 || strstr (str
, "ssh6://"))
660 return PWMD_SOCKET_SSH
;
664 if (strstr (str
, "tls://") || strstr (str
, "tls4://")
665 || strstr (str
, "tls6://"))
666 return PWMD_SOCKET_TLS
;
669 return PWMD_SOCKET_LOCAL
;
674 escape (const char *str
)
677 char *buf
= pwmd_malloc (ASSUAN_LINELENGTH
+ 1), *b
= buf
;
680 for (p
= str
; *p
; p
++, len
++)
682 if (len
== ASSUAN_LINELENGTH
)
726 free_inquire (struct inquire_s
*inq
)
731 pwmd_free (inq
->line
);
733 if (inq
->fd
!= -1 && inq
->fd
!= STDIN_FILENO
)
736 pwmd_free (inq
->last_keyword
);
740 /* When *result is not NULL it is updated to the new values and not
743 set_inquire (int fd
, const char *line
, struct inquire_s
**result
)
745 struct inquire_s inq
= { 0 };
746 struct stat st
= { 0 };
751 if (fstat (fd
, &st
) == -1)
752 return gpg_error_from_syserror ();
754 inq
.size
= st
.st_size
;
758 inq
.line
= pwmd_calloc (1, ASSUAN_LINELENGTH
);
760 return GPG_ERR_ENOMEM
;
764 char *s
= escape (line
);
768 pwmd_free (inq
.line
);
769 return GPG_ERR_ENOMEM
;
772 if (strlen (s
) >= ASSUAN_LINELENGTH
)
774 pwmd_free (inq
.line
);
776 return GPG_ERR_LINE_TOO_LONG
;
779 strncpy (inq
.line
, s
, ASSUAN_LINELENGTH
- 1);
780 inq
.len
= strlen (s
);
784 rc
= pwmd_setopt (pwm
, PWMD_OPTION_INQUIRE_TOTAL
,
785 st
.st_size
? st
.st_size
+ strlen (inq
.line
) : 0);
788 pwmd_free (inq
.line
);
793 *result
= pwmd_malloc (sizeof (struct inquire_s
));
796 if ((*result
)->fd
!= -1 && (*result
)->fd
!= STDIN_FILENO
)
797 close ((*result
)->fd
);
799 pwmd_free ((*result
)->line
);
800 (*result
)->line
= NULL
;
805 memcpy (*result
, &inq
, sizeof (struct inquire_s
));
806 memset (&inq
, 0, sizeof (struct inquire_s
));
810 #ifdef HAVE_LIBREADLINE
812 interactive_hook (void)
814 interactive_error
= process_cmd ();
816 if (interactive_error
)
817 rl_event_hook
= NULL
;
823 get_readline_char (FILE *fp
)
826 && (!strncmp (rl_line_buffer
, ".set passphrase-file ", 16)
827 || !strncmp (rl_line_buffer
, ".set new-passphrase-file ", 20)
828 || !strncmp (rl_line_buffer
, ".set sign-passphrase-file ", 21)))
829 rl_inhibit_completion
= 0;
830 else if (rl_line_buffer
831 && !strncmp (rl_line_buffer
, ".redir ", 7))
833 char *p
= strchr (rl_line_buffer
, ' ');
835 if (strchr (++p
, ' '))
836 rl_inhibit_completion
= 1;
838 rl_inhibit_completion
= 0;
840 else if (rl_line_buffer
841 && !strncmp (rl_line_buffer
, ".read ", 6))
843 char *p
= rl_line_buffer
+ 6;
845 if (strstr (p
, "--prefix "))
847 p
= strstr (p
, "--prefix ");
854 if (!p
|| strchr (p
, ' '))
855 rl_inhibit_completion
= 1;
857 rl_inhibit_completion
= 0;
860 rl_inhibit_completion
= 1;
870 ("------------------------------------------------------------\n"
871 "Elements are TAB delimited. Type HELP for protocol commands.\n"
872 "Type .help for pwmc commands. Press CTRL-D to quit.\n"
873 "------------------------------------------------------------\n"));
878 parse_arg (const char *src
, char *dst
, size_t len
)
884 for (; s
&& *s
&& *s
!= ' ' && n
< len
; s
++, n
++)
892 parse_opt (char **line
, const char *opt
, gpg_error_t
* rc
)
894 static char result
[ASSUAN_LINELENGTH
] = { 0 }, *r
= result
;
895 char *s
= strstr (*line
, opt
);
905 size_t rlen
= strlen (opt
);
909 while (*p
&& *p
== ' ')
915 for (; *p
&& len
< sizeof (result
) - 1; p
++, rlen
++)
917 if (isspace (*p
) && !quote
)
920 if (*p
== '\"' && lastc
!= '\\')
933 if (len
>= sizeof (result
) - 1)
934 *rc
= GPG_ERR_LINE_TOO_LONG
;
939 while (*p
&& *p
== ' ')
950 read_command (const char *line
, char **result
, size_t * len
)
955 struct inquire_s
*inq
= NULL
;
956 char *p
= (char *) line
;
957 const char *prefix
= parse_opt (&p
, "--prefix", &rc
);
958 char filebuf
[ASSUAN_LINELENGTH
];
967 while (*p
&& isspace (*p
))
970 file
= parse_arg (p
, filebuf
, sizeof (filebuf
));
973 p
+= strlen (file
) + 1;
975 while (*p
&& isspace (*p
))
987 ("Usage: .read [--prefix <string>] <filename> <command> [args]\n"));
990 ("Use '\\' to escape special characters in the --prefix (\\t = TAB, \\\\ = \\)\n"));
994 fd
= open (file
, O_RDONLY
);
996 return gpg_error_from_syserror ();
998 rc
= set_inquire (fd
, prefix
&& *prefix
? prefix
: NULL
, &inq
);
1005 rc
= pwmd_command (pwm
, result
, len
, inquire_cb
, inq
, "%s", p
);
1011 redir_command (const char *line
)
1013 const char *p
= line
;
1015 gpg_error_t rc
= GPG_ERR_SYNTAX
;
1017 struct inquire_s
*inq
= NULL
;
1018 char *result
= NULL
;
1020 char filebuf
[ASSUAN_LINELENGTH
];
1022 if (p
&& *p
&& *++p
)
1024 file
= parse_arg (p
, filebuf
, sizeof (filebuf
));
1027 p
+= strlen (file
) + 1;
1029 while (*p
&& isspace (*p
))
1039 fprintf (stderr
, N_("Usage: .redir <filename> <command> [args]\n"));
1043 fd
= open (file
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0600);
1045 return gpg_error_from_syserror ();
1047 #ifdef HAVE_LIBREADLINE
1048 rc
= set_inquire (interactive
? STDIN_FILENO
: inquirefd
, NULL
, &inq
);
1050 rc
= set_inquire (inquirefd
, NULL
, &inq
);
1058 rc
= parse_dotcommand (p
, &result
, &len
, inq
);
1059 if (!rc
&& result
&& len
--)
1060 { // null byte which is always appended
1061 if (write (fd
, result
, len
) != len
)
1062 rc
= GPG_ERR_TOO_SHORT
;
1072 help_command (const char *line
)
1075 N_("Type HELP for protocol commands. Available pwmc commands:\n\n"
1076 " .redir <filename> <command>\n"
1077 " redirect the output of a command to the specified file\n"
1079 " .open <filename>\n"
1080 " open the specified filename losing any changes to the current one\n"
1082 " .read [--prefix <string>] <filename> <command> [args]\n"
1083 " obtain data from the specified filename for an inquire command\n"
1085 " .set help | <name> [<value>]\n"
1086 " set option <name> to <value>\n"
1089 " write changes of the file to disk\n"
1092 " change the passphrase of a data file\n"
1095 " this help text\n"));
1100 open_command (char *line
)
1102 struct inquire_s
*inq
= NULL
;
1103 const char *file
= line
;
1107 while (file
&& isspace (*file
))
1110 if (!file
|| !*file
)
1112 fprintf (stderr
, N_("Usage: .open <filename>\n"));
1113 return GPG_ERR_SYNTAX
;
1116 #ifdef HAVE_LIBREADLINE
1117 if (interactive
|| !quiet
)
1121 fprintf (stderr
, N_("Opening data file \"%s\" ...\n"), file
);
1123 #ifdef HAVE_LIBREADLINE
1124 rc
= set_inquire (interactive
? STDIN_FILENO
: -1, NULL
, &inq
);
1126 rc
= set_inquire (-1, NULL
, &inq
);
1131 pwmd_getopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, &local
);
1135 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 1);
1137 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, 1);
1140 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
1143 rc
= pwmd_open (pwm
, file
, inquire_cb
, inq
);
1145 pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, local
);
1147 #ifdef HAVE_LIBREADLINE
1153 if (!rc
&& file
!= filename
)
1155 pwmd_free (filename
);
1156 filename
= pwmd_strdup (file
);
1163 set_command (const char *line
)
1166 char name
[256] = { 0 };
1167 char value
[512] = { 0 };
1170 const char *p
= line
;
1172 while (p
&& *p
&& isspace (*p
))
1175 namep
= parse_arg (p
, name
, sizeof (name
));
1176 if (!namep
|| !*namep
)
1178 fprintf (stderr
, N_("Usage: .set help | <name> [<value>]\n"));
1179 return GPG_ERR_SYNTAX
;
1182 p
+= strlen (namep
);
1183 while (p
&& *p
&& isspace (*p
))
1186 valuep
= parse_arg (p
, value
, sizeof (value
));
1188 if (!strcmp (name
, "passphrase-file") || !strcmp (name
, "new-passphrase-file")
1189 || !strcmp (name
, "sign-passphrase-file"))
1191 int is_newkeyfile
= 1;
1192 int sign
= !strcmp (name
, "sign-passphrase-file");
1194 if (!strcmp (name
, "passphrase-file") || sign
)
1199 pwmd_free (new_keyfile
);
1204 pwmd_free (sign_keyfile
);
1205 sign_keyfile
= NULL
;
1209 pwmd_free (keyfile
);
1216 new_keyfile
= pwmd_strdup (value
);
1218 sign_keyfile
= pwmd_strdup (value
);
1220 keyfile
= pwmd_strdup (value
);
1222 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 1);
1224 else if (!local_pin
&& !no_pinentry
)
1228 pwmd_socket_type (pwm
, &t
);
1229 if (t
== PWMD_SOCKET_LOCAL
)
1230 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
1233 else if (!strcmp(name
, "pinentry-timeout"))
1236 int n
= strtol(valuep
, &e
, 10);
1239 return gpg_error (GPG_ERR_INV_VALUE
);
1242 n
= DEFAULT_PIN_TIMEOUT
;
1244 rc
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TIMEOUT
, n
);
1246 else if (!strcmp (name
, "help"))
1250 ("Set a libpwmd or pwmc option. The option name and optional value is space\n"
1251 "delimited. When no value is specified the option is unset.\n\n"
1252 "passphrase-file [<filename>]\n"
1253 " set or unset the file to be used when a passphrase is required (*)\n"
1255 "new-passphrase-file [<filename>]\n"
1256 " set or unset the file to be used when a new passphrase is required (*)\n"
1258 "sign-passphrase-file [<filename>]\n"
1259 " set or unset the file to be used when a passphrase is required for\n"
1260 " signing (symmetric) (*)\n"
1262 "pinentry-timeout <seconds>\n"
1263 " the amount of seconds before pinentry gives up waiting for input\n"
1265 "* = the next protocol command will unset this value\n"
1269 rc
= GPG_ERR_UNKNOWN_OPTION
;
1275 do_save_passwd_command (const char *line
, int save
)
1277 struct inquire_s
*inq
= NULL
;
1281 #ifdef HAVE_LIBREADLINE
1282 rc
= set_inquire (interactive
? STDIN_FILENO
: -1, NULL
, &inq
);
1284 rc
= set_inquire (-1, NULL
, &inq
);
1289 pwmd_getopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, &local
);
1291 if (new_keyfile
|| keyfile
|| sign_keyfile
)
1293 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 1);
1295 pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, 1);
1298 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
1303 rc
= pwmd_save (pwm
, line
, inquire_cb
, inq
);
1305 rc
= pwmd_passwd (pwm
, line
, inquire_cb
, inq
);
1308 pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, local
);
1310 #ifdef HAVE_LIBREADLINE
1320 save_command (const char *line
)
1322 return do_save_passwd_command (line
, 1);
1326 parse_dotcommand (const char *line
, char **result
,
1327 size_t * len
, struct inquire_s
*inq
)
1329 const char *p
= line
;
1332 if (!strncmp (p
, ".read", 5))
1333 rc
= read_command (p
+ 5, result
, len
);
1334 else if (!strncmp (p
, ".redir", 6))
1335 rc
= redir_command (p
+ 6);
1336 else if (!strncmp (p
, ".help", 5))
1337 rc
= help_command (p
+ 5);
1338 else if (!strncmp (p
, ".open", 5))
1339 rc
= open_command ((char *)p
+ 5);
1340 else if (!strncmp (p
, ".set", 4))
1341 rc
= set_command (p
+ 4);
1342 else if (!strncmp (p
, ".save", 5))
1343 rc
= do_save_passwd_command (p
+ 5, 1);
1344 else if (!strncmp (p
, ".passwd", 7))
1345 rc
= do_save_passwd_command (p
+ 7, 0);
1348 rc
= pwmd_command (pwm
, result
, len
, inquire_cb
, inq
, "%s", line
);
1349 #ifdef HAVE_LIBREADLINE
1354 #ifdef HAVE_LIBREADLINE
1362 #ifdef HAVE_LIBREADLINE
1367 struct inquire_s
*inq
= NULL
;
1370 rc
= process_cmd ();
1374 rc
= set_inquire (STDIN_FILENO
, NULL
, &inq
);
1379 N_("WARNING: interactive mode doesn't use secure memory!\n"));
1381 rl_event_hook
= &interactive_hook
;
1382 rl_getc_function
= get_readline_char
;
1383 rl_set_keyboard_input_timeout (100000);
1388 char *result
= NULL
;
1392 line
= readline ("pwmc> ");
1393 if (interactive_error
)
1396 rc
= interactive_error
;
1406 if (gpg_err_code (rc
) != GPG_ERR_CANCELED
&&
1407 gpg_err_code (rc
) != GPG_ERR_EOF
)
1408 fprintf (stderr
, "ERR %i: %s\n", rc
, gpg_strerror (rc
));
1418 #ifdef HAVE_READLINE_HISTORY
1421 rc
= parse_dotcommand (line
, &result
, &len
, inq
);
1427 if (gpg_err_code (rc
) == GPG_ERR_BAD_DATA
)
1428 (void) pwmd_command (pwm
, &tmp
, NULL
, NULL
, NULL
,
1429 "GETINFO last_error");
1431 show_error (pwm
, rc
, tmp
);
1434 else if (result
&& len
)
1435 printf ("%s%s", result
, result
[len
- 1] != '\n' ? "\n" : "");
1449 #ifdef HAVE_LIBREADLINE
1456 fprintf (stderr
, "\n");
1464 ("(c)ancel/(f)orget password/(s)ave/(Q)uit/(S)ave and quit/(h)elp?: "));
1465 p
= fgets (buf
, sizeof (buf
), stdin
);
1479 return GPG_ERR_CANCELED
;
1483 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
,
1484 "CLEARCACHE %s", filename
);
1488 interactive_hook ();
1504 if (save
&& !filename
)
1508 ("No filename was specified on the command line. Aborting.\n"));
1509 return GPG_ERR_CANCELED
;
1512 if (save
&& filename
)
1515 pwmd_strdup_printf ("%s %s%s %s%s %s",
1516 symmetric
? "--symmetric" : "",
1517 keyid
? "--keyid=" : "",
1519 sign_keyid
? "--sign-keyid=" : "",
1520 sign_keyid
? sign_keyid
: "",
1521 keyparams
? "--inquire-keyparam" : "");
1523 #ifdef HAVE_LIBREADLINE
1524 if (!quiet
|| interactive
)
1530 fprintf (stderr
, "\n");
1531 fprintf (stderr
, N_("Saving changes ...\n"));
1534 rc
= save_command (args
);
1538 #ifdef HAVE_LIBREADLINE
1540 return rc
? rc
: quit
? 0 : GPG_ERR_CANCELED
;
1547 parse_status_ignore (char *str
)
1552 for (p
= status_ignore
; p
&& *p
; p
++)
1555 pwmd_free (status_ignore
);
1556 status_ignore
= NULL
;
1560 while ((s
= strsep (&str
, ",")))
1562 p
= pwmd_realloc (status_ignore
, (n
+ 2) * sizeof (char *));
1563 p
[n
++] = pwmd_strdup (s
);
1570 main (int argc
, char *argv
[])
1575 char command
[ASSUAN_LINELENGTH
], *p
= NULL
;
1576 char *result
= NULL
;
1578 char *pinentry_path
= NULL
;
1579 char *display
= NULL
, *tty
= NULL
, *ttytype
= NULL
;
1580 char *lcctype
= NULL
, *lcmessages
= NULL
;
1581 int outfd
= STDOUT_FILENO
;
1582 FILE *outfp
= stdout
;
1583 FILE *inquirefp
= stdin
;
1584 int show_status
= 1;
1585 char *clientname
= "pwmc";
1586 char *inquire
= NULL
;
1587 char *inquire_line
= NULL
;
1590 int use_ssh_agent
= 1;
1591 char *knownhosts
= NULL
;
1592 char *identity
= NULL
;
1595 char *cacert
= NULL
;
1596 char *clientcert
= NULL
;
1597 char *clientkey
= NULL
;
1600 char *tls_fingerprint
= NULL
;
1602 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1603 pwmd_socket_t socktype
;
1604 long socket_timeout
= 300;
1605 int connect_timeout
= 120;
1606 int needs_passphrase
= 0;
1608 int lock_on_open
= 1;
1609 long lock_timeout
= 50;
1612 /* The order is important. */
1615 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1616 OPT_SOCKET_TIMEOUT
, OPT_CONNECT_TIMEOUT
,
1619 OPT_USE_SSH_AGENT
, OPT_IDENTITY
, OPT_KNOWNHOSTS
, OPT_SSH_NEEDS_PASSPHRASE
,
1622 OPT_CACERT
, OPT_CLIENTCERT
, OPT_CLIENTKEY
, OPT_PRIORITY
, OPT_VERIFY
,
1625 OPT_URL
, OPT_LOCAL
, OPT_TTYNAME
, OPT_TTYTYPE
, OPT_DISPLAY
, OPT_LC_CTYPE
,
1626 OPT_LC_MESSAGES
, OPT_TIMEOUT
, OPT_TRIES
, OPT_PINENTRY
, OPT_KEYFILE
,
1627 OPT_PASSPHRASE_FILE
, OPT_NEW_KEYFILE
, OPT_NEW_PASSPHRASE_FILE
,
1628 OPT_SIGN_KEYFILE
, OPT_SIGN_PASSPHRASE_FILE
, OPT_NOLOCK
, OPT_LOCK_TIMEOUT
,
1629 OPT_SAVE
, OPT_OUTPUT_FD
, OPT_INQUIRE
, OPT_INQUIRE_FD
, OPT_INQUIRE_FILE
,
1630 OPT_INQUIRE_LINE
, OPT_NO_STATUS
, OPT_STATUS_IGNORE
, OPT_STATUSFD
, OPT_NAME
,
1631 OPT_VERSION
, OPT_HELP
, OPT_KEYID
, OPT_SIGN_KEYID
, OPT_SYMMETRIC
,
1632 OPT_KEYPARAMS
, OPT_NO_PINENTRY
, OPT_QUIET
,
1633 #ifdef HAVE_LIBREADLINE
1637 const struct option long_opts
[] = {
1638 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1639 {"socket-timeout", 1, 0, 0},
1640 {"connect-timeout", 1, 0, 0},
1644 {"no-ssh-agent", 0, 0, 0},
1645 {"identity", 1, 0, 'i'},
1646 {"knownhosts", 1, 0, 'k'},
1647 {"ssh-needs-passphrase", 0, 0, 0},
1650 {"ca-cert", 1, 0, 0},
1651 {"client-cert", 1, 0, 0},
1652 {"client-key", 1, 0, 0},
1653 {"tls-priority", 1, 0, 0},
1654 {"tls-verify", 0, 0, 0},
1655 {"tls-fingerprint", 1, 0, 0},
1658 {"local-pinentry", 0, 0},
1659 {"ttyname", 1, 0, 'y'},
1660 {"ttytype", 1, 0, 't'},
1661 {"display", 1, 0, 'd'},
1662 {"lc-ctype", 1, 0, 0},
1663 {"lc-messages", 1, 0, 0},
1664 {"timeout", 1, 0, 0},
1666 {"pinentry", 1, 0, 0},
1667 {"key-file", 1, 0, 0},
1668 {"passphrase-file", 1, 0, 0},
1669 {"new-key-file", 1, 0, 0},
1670 {"new-passphrase-file", 1, 0, 0},
1671 {"sign-key-file", 1, 0, 0},
1672 {"sign-passphrase-file", 1, 0, 0},
1673 {"no-lock", 0, 0, 0},
1674 {"lock-timeout", 1, 0, 0},
1675 {"save", 0, 0, 'S'},
1676 {"output-fd", 1, 0, 0},
1677 {"inquire", 1, 0, 0},
1678 {"inquire-fd", 1, 0, 0},
1679 {"inquire-file", 1, 0, 0},
1680 {"inquire-line", 1, 0, 'L'},
1681 {"no-status", 0, 0, 0},
1682 {"status-ignore", 1, 0, 0},
1683 {"status-fd", 1, 0, 0},
1684 {"name", 1, 0, 'n'},
1685 {"version", 0, 0, 0},
1688 {"sign-keyid", 1, 0, 0},
1689 {"symmetric", 0, 0, 0},
1690 {"key-params", 1, 0, 0},
1691 {"no-pinentry", 0, 0, 0},
1693 #ifdef HAVE_LIBREADLINE
1694 {"interactive", 0, 0},
1699 const char *optstring
= "L:y:t:d:P:I:Sn:i:k:s";
1701 const char *optstring
= "L:y:t:d:P:I:Sn:s";
1706 setlocale (LC_ALL
, "");
1707 bindtextdomain ("libpwmd", LOCALEDIR
);
1710 tries
= DEFAULT_PIN_TRIES
;
1711 inquirefd
= STDIN_FILENO
;
1712 statusfd
= STDERR_FILENO
;
1713 statusfp
= fdopen (statusfd
, "w");
1714 tmp
= pwmd_strdup (DEFAULT_STATUS_IGNORE
);
1715 parse_status_ignore (tmp
);
1719 getopt_long (argc
, argv
, optstring
, long_opts
, &opt_index
)) != -1)
1723 /* Handle long options without a short option part. */
1727 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1728 case OPT_SOCKET_TIMEOUT
:
1729 socket_timeout
= strtol (optarg
, &p
, 10);
1731 case OPT_CONNECT_TIMEOUT
:
1732 connect_timeout
= strtol (optarg
, &p
, 10);
1736 case OPT_USE_SSH_AGENT
:
1739 case OPT_SSH_NEEDS_PASSPHRASE
:
1740 needs_passphrase
= 1;
1747 case OPT_CLIENTCERT
:
1748 clientcert
= optarg
;
1760 tls_fingerprint
= optarg
;
1770 case OPT_PASSPHRASE_FILE
:
1771 keyfile
= pwmd_strdup (optarg
);
1773 case OPT_NEW_KEYFILE
:
1774 case OPT_NEW_PASSPHRASE_FILE
:
1775 new_keyfile
= pwmd_strdup (optarg
);
1777 case OPT_SIGN_KEYFILE
:
1778 case OPT_SIGN_PASSPHRASE_FILE
:
1779 sign_keyfile
= pwmd_strdup (optarg
);
1784 case OPT_LOCK_TIMEOUT
:
1785 lock_timeout
= strtol (optarg
, &p
, 10);
1794 lcctype
= pwmd_strdup (optarg
);
1796 case OPT_LC_MESSAGES
:
1797 lcmessages
= pwmd_strdup (optarg
);
1800 timeout
= strtol (optarg
, &p
, 10);
1803 tries
= strtol (optarg
, &p
, 10);
1806 inquire
= escape (optarg
);
1808 case OPT_INQUIRE_FD
:
1809 inquirefd
= strtol (optarg
, &p
, 10);
1812 inquirefp
= fdopen (inquirefd
, "r");
1814 err (EXIT_FAILURE
, "%i", inquirefd
);
1817 case OPT_INQUIRE_FILE
:
1818 inquirefd
= open (optarg
, O_RDONLY
);
1819 if (inquirefd
== -1)
1820 err (EXIT_FAILURE
, "%s", optarg
);
1821 inquirefp
= fdopen (inquirefd
, "r");
1824 outfd
= strtol (optarg
, &p
, 10);
1827 outfp
= fdopen (outfd
, "w");
1829 err (EXIT_FAILURE
, "%i", outfd
);
1836 statusfd
= strtol (optarg
, &p
, 10);
1839 statusfp
= fdopen (statusfd
, "w");
1841 err (EXIT_FAILURE
, "%i", statusfd
);
1844 case OPT_STATUS_IGNORE
:
1845 parse_status_ignore (optarg
);
1848 printf ("%s (pwmc)\n\n"
1849 "Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016\n"
1851 "Released under the terms of the GPL v2. Use at your own risk.\n\n"
1852 "Compile-time features:\n"
1853 #ifdef HAVE_LIBREADLINE
1868 #ifdef WITH_PINENTRY
1883 "\n", PACKAGE_STRING
, PACKAGE_BUGREPORT
);
1884 exit (EXIT_SUCCESS
);
1886 pinentry_path
= optarg
;
1889 usage (argv
[0], EXIT_SUCCESS
);
1893 case OPT_SIGN_KEYID
:
1894 sign_keyid
= optarg
;
1900 case OPT_NO_PINENTRY
:
1903 #ifdef HAVE_LIBREADLINE
1904 case OPT_INTERACTIVE
:
1909 usage (argv
[0], EXIT_FAILURE
);
1914 fprintf (stderr
, N_("%s: invalid argument for option '--%s'\n"),
1915 argv
[0], long_opts
[opt_index
].name
);
1916 usage (argv
[0], EXIT_FAILURE
);
1925 knownhosts
= optarg
;
1929 inquire_line
= optarg
;
1944 clientname
= optarg
;
1947 usage (argv
[0], EXIT_FAILURE
);
1951 #ifdef HAVE_LIBREADLINE
1952 if (interactive
&& !isatty (STDIN_FILENO
))
1953 usage (argv
[0], EXIT_FAILURE
);
1954 else if (isatty (STDIN_FILENO
) && !inquire
&& !inquire_line
)
1959 rc
= pwmd_new (clientname
, &pwm
);
1963 filename
= argv
[optind
] ? pwmd_strdup (argv
[optind
]) : NULL
;
1964 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, no_pinentry
);
1968 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, local_pin
);
1972 pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TRIES
, tries
);
1974 fprintf (stderr
, N_("Connecting ...\n"));
1976 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1977 socktype
= is_remote_url (url
);
1978 if (socktype
!= PWMD_SOCKET_LOCAL
)
1981 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1982 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SOCKET_TIMEOUT
, connect_timeout
);
1987 if (socktype
== PWMD_SOCKET_SSH
)
1990 rc
= pwmd_setopt (pwm
, PWMD_OPTION_KNOWNHOST_CB
, knownhost_cb
);
1994 rc
= pwmd_setopt (pwm
, PWMD_OPTION_KNOWNHOST_DATA
, clientname
);
1998 if (!getenv ("SSH_AUTH_SOCK") || identity
)
2001 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SSH_AGENT
, use_ssh_agent
);
2005 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SSH_NEEDS_PASSPHRASE
,
2010 rc
= pwmd_connect (pwm
, url
, identity
, knownhosts
);
2016 rc
= pwmd_setopt (pwm
, PWMD_OPTION_TLS_VERIFY
, tls_verify
);
2020 rc
= pwmd_connect (pwm
, url
, clientcert
, clientkey
, cacert
, prio
,
2026 rc
= pwmd_connect (pwm
, url
);
2028 rc
= pwmd_connect (pwm
, url
);
2034 fprintf (stderr
, N_("Connected.\n"));
2037 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
2038 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SOCKET_TIMEOUT
, socket_timeout
);
2045 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
,
2046 "OPTION LOCK-TIMEOUT=%li", lock_timeout
);
2053 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCK_ON_OPEN
, 1);
2058 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DESC
, NULL
, NULL
);
2064 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TIMEOUT
, timeout
);
2071 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_PATH
, pinentry_path
);
2078 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DISPLAY
, display
);
2085 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TTY
, tty
);
2092 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TERM
, ttytype
);
2099 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_LC_CTYPE
, lcctype
);
2106 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_LC_MESSAGES
, lcmessages
);
2113 rc
= pwmd_setopt (pwm
, PWMD_OPTION_STATUS_CB
, status_msg_cb
);
2120 rc
= open_command (filename
);
2125 #ifdef HAVE_LIBREADLINE
2128 rc
= do_interactive ();
2136 struct inquire_s
*inq
= NULL
;
2138 rc
= set_inquire (inquirefd
, inquire_line
, &inq
);
2140 rc
= pwmd_command (pwm
, &result
, &len
, inquire_cb
, inq
, "%s", inquire
);
2146 if (fcntl (STDIN_FILENO
, F_SETFL
, O_NONBLOCK
) == -1)
2148 rc
= gpg_error_from_errno (errno
);
2156 rc
= process_cmd ();
2161 n
= read (STDIN_FILENO
, command
, sizeof (command
)-1);
2164 if (errno
== EAGAIN
)
2170 rc
= gpg_error_from_errno (errno
);
2181 if (!p
|| !*p
|| !strcasecmp (p
, "BYE"))
2185 struct inquire_s
*inq
= NULL
;
2186 rc
= set_inquire (inquirefd
, inquire_line
, &inq
);
2189 rc
= parse_dotcommand (command
, &result
, &len
, inq
);
2199 fwrite (result
, 1, result
[len
- 1] == 0 ? len
- 1 : len
, outfp
);
2207 else if (gpg_err_code (rc
) == GPG_ERR_BAD_DATA
)
2208 (void) pwmd_command (pwm
, &result
, NULL
, NULL
, NULL
,
2209 "GETINFO last_error");
2211 #ifdef HAVE_LIBREADLINE
2214 memset (command
, 0, sizeof (command
));
2217 show_error (pwm
, rc
, result
);
2223 pwmd_free (filename
);
2224 parse_status_ignore (NULL
);
2225 if (connected
&& !quiet
)
2226 fprintf (stderr
, N_("Connection closed.\n"));
2228 exit (rc
? EXIT_FAILURE
: EXIT_SUCCESS
);