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>
45 #include <gnutls/gnutls.h>
52 #ifdef HAVE_GETOPT_LONG
57 #include "getopt_long.h"
60 #ifdef HAVE_LIBREADLINE
61 #if defined(HAVE_READLINE_READLINE_H)
62 #include <readline/readline.h>
63 #elif defined(HAVE_READLINE_H)
65 #endif /* !defined(HAVE_READLINE_H) */
66 static int interactive_error
;
67 static int interactive
;
68 #endif /* HAVE_LIBREADLINE */
70 #ifdef HAVE_READLINE_HISTORY
71 #if defined(HAVE_READLINE_HISTORY_H)
72 #include <readline/history.h>
73 #elif defined(HAVE_HISTORY_H)
76 #endif /* HAVE_READLINE_HISTORY */
83 #define N_(msgid) gettext(msgid)
88 #define DEFAULT_STATUS_IGNORE "KEEPALIVE,STATE,GPGME,PASSPHRASE_INFO,PASSPHRASE_HINT"
89 #define DEFAULT_PIN_TIMEOUT 30
90 #define DEFAULT_PIN_TRIES 3
91 #define FINISH(rc) (gpg_err_source(rc) == GPG_ERR_SOURCE_UNKNOWN) \
94 static int no_pinentry
;
96 static char *filename
;
99 static char *sign_keyid
;
100 static int symmetric
;
101 static char *keyparams
;
102 static char *keyfile
;
103 static char *new_keyfile
;
104 static char *sign_keyfile
;
106 static int local_pin
;
107 static int inquirefd
;
111 static char **status_ignore
;
118 size_t size
; // from stat(2).
122 static gpg_error_t
finalize ();
123 static gpg_error_t
set_inquire (int fd
, const char *line
,
124 struct inquire_s
**result
);
125 static gpg_error_t
parse_dotcommand (const char *line
, char **result
,
126 size_t * len
, struct inquire_s
*inq
);
127 static gpg_error_t
open_command (const char *line
);
129 static gpg_error_t
get_password (char **result
, pwmd_pinentry_t w
, int echo
);
133 show_error (pwm_t
*pwm
, gpg_error_t rc
, const char *str
)
136 if (pwmd_tls_error (pwm
))
137 fprintf(stderr
, "TLS: %s\n", gnutls_strerror(pwmd_tls_error(pwm
)));
139 fprintf (stderr
, "ERR %i: %s%s%s%s", rc
, gpg_strerror (rc
),
140 str
? ": " : "", str
? str
: "", str
? "" : "\n");
147 pwmd_free (new_keyfile
);
148 pwmd_free (sign_keyfile
);
149 keyfile
= new_keyfile
= sign_keyfile
= NULL
;
153 usage (const char *pn
, int status
)
155 fprintf (status
== EXIT_FAILURE
? stderr
: stdout
,
156 N_("Usage: pwmc [options] [file]\n"
158 " a url string to connect to (%s, see below)\n"
159 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
160 " --connect-timeout <seconds>\n"
161 " seconds before connecting to a remote host fails (0=disabled, 120)\n"
162 " --socket-timeout <seconds>\n"
163 " seconds before a remote command fails (0=disabled, 300)\n"
166 " --ca-cert <filename>\n"
167 " certificate authority (CA) used to sign the server cert\n"
168 " --client-cert <filename>\n"
169 " client certificate to use for authentication\n"
170 " --client-key <filename>\n"
171 " key file used to protect the client certificate\n"
172 " --tls-priority <string>\n"
173 " compression, cipher and hash algorithm string\n"
174 " (SECURE256:SECURE192:SECURE128:-VERS-SSL3.0)\n"
176 " verify the hostname against the server certificate\n"
177 " --tls-fingerprint <string>\n"
178 " a SHA-256 hash of the server fingerprint to verify against\n"
182 " disable SSH agent use (enabled when SSH_AUTH_SOCK is set)\n"
183 " --identity, -i <filename>\n"
184 " the ssh identity file to use for authentication\n"
185 " --knownhosts, -k <filename>\n"
186 " the ssh knownhosts file to use (~/.ssh/knownhosts)\n"
189 " do not lock the data file upon opening it\n"
190 " --lock-timeout <N>\n"
191 " time in tenths of a second to wait for a locked data file (50)\n"
192 " --name, -n <string>\n"
193 " set the client name\n"
194 " --pinentry <path>\n"
195 " the full path to the pinentry binary\n"
196 " --local-pinentry\n"
197 " force using a local pinentry\n"
199 " disable pinentry both remotely and locally\n"
200 " --ttyname, -y <path>\n"
201 " tty that pinentry will use\n"
202 " --ttytype, -t <string>\n"
203 " pinentry terminal type (default is $TERM)\n"
205 " pinentry display (default is $DISPLAY)\n"
206 " --lc-ctype <string>\n"
207 " locale setting for pinentry\n"
208 " --lc-messages <string>\n"
209 " locale setting for pinentry\n"
211 " number of pinentry tries before failing (3)\n"
212 " --timeout <seconds>\n"
213 " pinentry timeout\n"
214 " --inquire <COMMAND>\n"
215 " the specified command (with any options) uses a server inquire while\n"
216 " command data is read via the inquire file descriptor (stdin)\n"
217 " --inquire-line, -L <STRING>\n"
218 " the initial line to send (i.e., element path) before the inquire data\n"
219 " --inquire-fd <FD>\n"
220 " read inquire data from the specified file descriptor (stdin)\n"
221 " --inquire-file <filename>\n"
222 " read inquire data from the specified filename\n"
223 " --output-fd <FD>\n"
224 " redirect command output to the specified file descriptor\n"
226 " send the SAVE command before exiting\n"
227 " --passphrase-file <filename>\n"
228 " obtain the passphrase from the specified filename\n"
229 " --new-passphrase-file <filename>\n"
230 " obtain the passphrase to save with from the specified filename\n"
231 " --sign-passphrase-file <filename>\n"
232 " obtain the passphrase to sign with (symmetric) from the specified filename\n"
233 " --key-params <filename>\n"
234 " key parameters to use for key generation (pwmd default)\n"
235 " --keyid <recipient>[,<recipient>]\n"
236 " the public key ID to u\n"
237 " --sign-keyid <string>\n"
238 " the key ID to sign the data file with\n"
240 " use conventional encryption with optional signer(s) for new files\n"
242 " disable showing of status messages from the server\n"
243 " --status-ignore <string[,...]>\n"
244 " prevent parsing of the specified status message keywords\n"
246 " disable showing of extra messages (implies --no-status)\n"
247 " --status-fd <FD>\n"
248 " redirect status messages to the specified file descriptor\n"
249 #ifdef HAVE_LIBREADLINE
251 " use a shell like interface to pwmd (allows more than one command)\n"
255 #ifdef DEFAULT_PWMD_SOCKET
261 fprintf (status
== EXIT_FAILURE
? stderr
: stdout
,
263 "An optional url may be in the form of:\n"
264 " --url /path/to/socket\n"
265 " --url file://[path/to/socket]\n"
268 " --url ssh[46]://[username@]hostname[:port]\n"
269 " --no-ssh-agent -i identity_file --url ssh[46]://[username@]hostname[:port]\n"
273 " --url tls[46]://hostname[:port] --ca-cert filename --client-cert filename\n"
274 " --client-key filename\n"
276 #ifdef HAVE_LIBREADLINE
278 "Interactive mode is used when input is from a terminal.\n"
285 inquire_cb (void *user
, const char *keyword
, gpg_error_t rc
,
286 char **data
, size_t * size
)
288 struct inquire_s
*inq
= user
;
290 int is_newpassword
= 0;
300 if (!strcmp (keyword
, "PASSPHRASE"))
302 else if (!strcmp (keyword
, "SIGN_PASSPHRASE"))
303 is_password
= sign
= 1;
304 else if (!strcmp (keyword
, "NEW_PASSPHRASE"))
306 #ifdef HAVE_LIBREADLINE
307 else if (!strcmp (keyword
, "KEYPARAM") && !interactive
)
310 else if (!strcmp (keyword
, "KEYPARAM"))
314 if (!keyparams
|| !*keyparams
)
315 return gpg_error (GPG_ERR_INV_PARAMETER
);
317 fd
= open (keyparams
, O_RDONLY
);
320 fprintf (stderr
, "%s: %s\n", keyparams
, strerror (errno
));
321 return gpg_error_from_syserror ();
324 rc
= set_inquire (fd
, NULL
, &inq
);
332 fprintf (stderr
, N_("Using file '%s' as %s.\n"), keyparams
, keyword
);
337 if ((is_newpassword
&& new_keyfile
) || (is_password
&& keyfile
)
338 || (sign
&& sign_keyfile
))
343 fd
= open (sign_keyfile
, O_RDONLY
);
345 fd
= open (is_password
? keyfile
: new_keyfile
, O_RDONLY
);
350 fprintf (stderr
, "%s: %s\n", sign_keyfile
, strerror (errno
));
352 fprintf (stderr
, "%s: %s\n", is_newpassword
? new_keyfile
353 : keyfile
, strerror (errno
));
354 return gpg_error_from_syserror ();
357 rc
= set_inquire (fd
, NULL
, &inq
);
365 fprintf (stderr
, N_("Using keyfile '%s' as %s.\n"),
366 sign
? sign_keyfile
: is_newpassword
? new_keyfile
369 else if ((is_password
&& !keyfile
) || (is_newpassword
&& !new_keyfile
)
370 || (sign
&& !sign_keyfile
))
374 rc
= pwmd_password (pwm
, keyword
, &tmp
, &inq
->len
);
375 if (rc
&& gpg_err_code (rc
) != GPG_ERR_EOF
)
378 pwmd_free (inq
->line
);
382 return gpg_error (GPG_ERR_EOF
);
384 #ifdef HAVE_LIBREADLINE
385 else if ((!inq
->last_keyword
|| strcmp (keyword
, inq
->last_keyword
))
390 ("%sPress CTRL-D to send the current line. Press twice to end. %s:\n"),
391 inq
->last_keyword
? "\n" : "", keyword
);
392 pwmd_free (inq
->last_keyword
);
393 inq
->last_keyword
= pwmd_strdup (keyword
);
397 /* The first part of the command data. */
403 return inq
->fd
== -1 ? gpg_error (GPG_ERR_EOF
) : 0;
406 *size
= read (inq
->fd
, inq
->line
, ASSUAN_LINELENGTH
);
410 return gpg_error (gpg_error_from_syserror ());
414 else if (inq
->fd
!= STDIN_FILENO
&&
415 (is_newpassword
|| is_password
|| is_keyparam
))
423 if (((is_newpassword
&& new_keyfile
) || (is_password
&& keyfile
)
424 || (sign
&& sign_keyfile
) || (keyparams
&& is_keyparam
))
425 && *size
== inq
->size
)
426 return gpg_error (GPG_ERR_EOF
);
428 return *size
? 0 : gpg_error (GPG_ERR_EOF
);
432 status_msg_cb (void *data
, const char *line
)
434 char *p
= strchr (line
, ' ');
437 /* Ignore status messages specified by the client via --status-ignore. */
438 for (s
= status_ignore
; s
&& *s
; s
++)
440 char *tmp
= strchr (line
, ' ');
441 size_t len
= tmp
? strlen (line
) - strlen (tmp
) : strlen (line
);
443 if (!strncmp (line
, *s
, len
) && len
== strlen (*s
))
447 if (statusfd
!= STDERR_FILENO
&& strncmp (line
, "STATE ", 6) && *line
!= '#'
448 && p
&& strchr (p
, ' ') && *++p
)
450 char *p1
= strchr (p
, ' ');
451 int a
= strtol (p
, NULL
, 10);
453 if (isdigit (*p
) && p1
)
455 int b
= strtol (p1
, NULL
, 10);
457 int t
= a
&& b
? a
* 100 / b
: 0;
459 strncpy (l
, line
, strlen (line
) - strlen (p
) - 1);
460 fprintf (statusfp
, "\r%s %i/%i %i%%%s", l
, a
, b
, t
,
467 fprintf (statusfp
, "%s\n", line
);
469 #ifdef HAVE_LIBREADLINE
478 return pwmd_process (pwm
);
483 get_password (char **result
, pwmd_pinentry_t w
, int echo
)
485 char buf
[LINE_MAX
] = { 0 }, *p
;
486 struct termios told
, tnew
;
491 if (!isatty (STDIN_FILENO
))
493 fprintf (stderr
, N_("Input is not from a terminal! Failing.\n"));
494 return GPG_ERR_ENOTTY
;
499 if (tcgetattr (STDIN_FILENO
, &told
) == -1)
500 return gpg_error_from_syserror ();
502 memcpy (&tnew
, &told
, sizeof (struct termios
));
503 tnew
.c_lflag
&= ~(ECHO
);
504 tnew
.c_lflag
|= ICANON
| ECHONL
;
506 if (tcsetattr (STDIN_FILENO
, TCSANOW
, &tnew
) == -1)
510 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
511 return gpg_error_from_errno (n
);
517 case PWMD_PINENTRY_OPEN
:
518 fprintf (stderr
, N_("Password for %s: "), filename
);
520 case PWMD_PINENTRY_OPEN_FAILED
:
521 fprintf (stderr
, N_("Invalid password. Password for %s: "), filename
);
523 case PWMD_PINENTRY_SAVE
:
524 fprintf (stderr
, N_("New password for %s: "), filename
);
526 case PWMD_PINENTRY_SAVE_CONFIRM
:
527 fprintf (stderr
, N_("Confirm password: "));
533 if ((p
= fgets (buf
, sizeof (buf
), stdin
)) == NULL
)
536 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
542 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
547 return GPG_ERR_CANCELED
;
550 p
[strlen (p
) - 1] = 0;
554 key
= pwmd_strdup_printf ("%s", p
);
555 memset (&buf
, 0, sizeof (buf
));
558 return GPG_ERR_ENOMEM
;
566 knownhost_cb (void *data
, const char *host
, const char *key
, size_t len
)
570 pwmd_strdup_printf (N_
571 ("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?"),
572 (char *) data
, host
, host
);
574 if (no_pinentry
&& !isatty (STDIN_FILENO
))
576 fprintf (stderr
, N_("Input is not from a terminal! Failing.\n"));
578 return GPG_ERR_ENOTTY
;
580 else if (no_pinentry
)
582 for (char *p
= buf
, len
= 0; *p
; p
++, len
++)
591 while (!isspace (*(--p
)));
598 fprintf (stderr
, "%s\n\n", buf
);
605 fprintf (stderr
, N_("Trust this connection [y/N]: "));
607 rc
= get_password (&result
, PWMD_PINENTRY_CONFIRM
, 1);
612 if (!result
|| !*result
|| *result
== 'n' || *result
== 'N')
614 if (result
&& *result
)
617 return GPG_ERR_NOT_CONFIRMED
;
620 if ((*result
== 'y' || *result
== 'Y') && *(result
+ 1) == 0)
629 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DESC
, buf
);
635 return pwmd_getpin (pwm
, NULL
, NULL
, NULL
, PWMD_PINENTRY_CONFIRM
);
639 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
641 is_remote_url (const char *str
)
644 return PWMD_SOCKET_LOCAL
;
647 if (strstr (str
, "ssh://") || strstr (str
, "ssh4://")
648 || strstr (str
, "ssh6://"))
649 return PWMD_SOCKET_SSH
;
653 if (strstr (str
, "tls://") || strstr (str
, "tls4://")
654 || strstr (str
, "tls6://"))
655 return PWMD_SOCKET_TLS
;
658 return PWMD_SOCKET_LOCAL
;
663 escape (const char *str
)
666 char *buf
= pwmd_malloc (ASSUAN_LINELENGTH
+ 1), *b
= buf
;
669 for (p
= str
; *p
; p
++, len
++)
671 if (len
== ASSUAN_LINELENGTH
)
715 free_inquire (struct inquire_s
*inq
)
720 pwmd_free (inq
->line
);
722 if (inq
->fd
!= -1 && inq
->fd
!= STDIN_FILENO
)
725 pwmd_free (inq
->last_keyword
);
729 /* When *result is not NULL it is updated to the new values and not
732 set_inquire (int fd
, const char *line
, struct inquire_s
**result
)
734 struct inquire_s inq
= { 0 };
735 struct stat st
= { 0 };
740 if (fstat (fd
, &st
) == -1)
741 return gpg_error_from_syserror ();
743 inq
.size
= st
.st_size
;
747 inq
.line
= pwmd_calloc (1, ASSUAN_LINELENGTH
);
749 return GPG_ERR_ENOMEM
;
753 char *s
= escape (line
);
757 pwmd_free (inq
.line
);
758 return GPG_ERR_ENOMEM
;
761 if (strlen (s
) >= ASSUAN_LINELENGTH
)
763 pwmd_free (inq
.line
);
765 return GPG_ERR_LINE_TOO_LONG
;
768 strncpy (inq
.line
, s
, ASSUAN_LINELENGTH
- 1);
769 inq
.len
= strlen (s
);
773 rc
= pwmd_setopt (pwm
, PWMD_OPTION_INQUIRE_TOTAL
,
774 st
.st_size
? st
.st_size
+ strlen (inq
.line
) : 0);
777 pwmd_free (inq
.line
);
782 *result
= pwmd_malloc (sizeof (struct inquire_s
));
785 if ((*result
)->fd
!= -1 && (*result
)->fd
!= STDIN_FILENO
)
786 close ((*result
)->fd
);
788 pwmd_free ((*result
)->line
);
789 (*result
)->line
= NULL
;
794 memcpy (*result
, &inq
, sizeof (struct inquire_s
));
795 memset (&inq
, 0, sizeof (struct inquire_s
));
799 #ifdef HAVE_LIBREADLINE
801 interactive_hook (void)
803 interactive_error
= process_cmd ();
805 if (interactive_error
)
806 rl_event_hook
= NULL
;
812 get_readline_char (FILE *fp
)
815 && (!strncmp (rl_line_buffer
, ".set passphrase-file ", 16)
816 || !strncmp (rl_line_buffer
, ".set new-passphrase-file ", 20)
817 || !strncmp (rl_line_buffer
, ".set sign-passphrase-file ", 21)))
818 rl_inhibit_completion
= 0;
819 else if (rl_line_buffer
820 && !strncmp (rl_line_buffer
, ".redir ", 7))
822 char *p
= strchr (rl_line_buffer
, ' ');
824 if (strchr (++p
, ' '))
825 rl_inhibit_completion
= 1;
827 rl_inhibit_completion
= 0;
829 else if (rl_line_buffer
830 && !strncmp (rl_line_buffer
, ".read ", 6))
832 char *p
= rl_line_buffer
+ 6;
834 if (strstr (p
, "--prefix "))
836 p
= strstr (p
, "--prefix ");
843 if (!p
|| strchr (p
, ' '))
844 rl_inhibit_completion
= 1;
846 rl_inhibit_completion
= 0;
849 rl_inhibit_completion
= 1;
859 ("------------------------------------------------------------\n"
860 "Elements are TAB delimited. Type HELP for protocol commands.\n"
861 "Type .help for pwmc commands. Press CTRL-D to quit.\n"
862 "------------------------------------------------------------\n"));
867 parse_arg (const char *src
, char *dst
, size_t len
)
873 for (; s
&& *s
&& *s
!= ' ' && n
< len
; s
++, n
++)
881 parse_opt (char **line
, const char *opt
, gpg_error_t
* rc
)
883 static char result
[ASSUAN_LINELENGTH
] = { 0 }, *r
= result
;
884 char *s
= strstr (*line
, opt
);
894 size_t rlen
= strlen (opt
);
898 while (*p
&& *p
== ' ')
904 for (; *p
&& len
< sizeof (result
) - 1; p
++, rlen
++)
906 if (isspace (*p
) && !quote
)
909 if (*p
== '\"' && lastc
!= '\\')
922 if (len
>= sizeof (result
) - 1)
923 *rc
= GPG_ERR_LINE_TOO_LONG
;
928 while (*p
&& *p
== ' ')
939 read_command (const char *line
, char **result
, size_t * len
)
943 char *filename
= NULL
;
944 struct inquire_s
*inq
= NULL
;
945 char *p
= (char *) line
;
946 const char *prefix
= parse_opt (&p
, "--prefix", &rc
);
947 char filebuf
[ASSUAN_LINELENGTH
];
956 while (*p
&& isspace (*p
))
959 filename
= parse_arg (p
, filebuf
, sizeof (filebuf
));
960 if (filename
&& *filename
)
962 p
+= strlen (filename
) + 1;
964 while (*p
&& isspace (*p
))
976 ("Usage: .read [--prefix <string>] <filename> <command> [args]\n"));
979 ("Use '\\' to escape special characters in the --prefix (\\t = TAB, \\\\ = \\)\n"));
983 fd
= open (filename
, O_RDONLY
);
985 return gpg_error_from_syserror ();
987 rc
= set_inquire (fd
, prefix
&& *prefix
? prefix
: NULL
, &inq
);
994 rc
= pwmd_command (pwm
, result
, len
, inquire_cb
, inq
, "%s", p
);
1000 redir_command (const char *line
)
1002 const char *p
= line
;
1004 gpg_error_t rc
= GPG_ERR_SYNTAX
;
1005 char *filename
= NULL
;
1006 struct inquire_s
*inq
= NULL
;
1007 char *result
= NULL
;
1009 char filebuf
[ASSUAN_LINELENGTH
];
1011 if (p
&& *p
&& *++p
)
1013 filename
= parse_arg (p
, filebuf
, sizeof (filebuf
));
1014 if (filename
&& *filename
)
1016 p
+= strlen (filename
) + 1;
1018 while (*p
&& isspace (*p
))
1028 fprintf (stderr
, N_("Usage: .redir <filename> <command> [args]\n"));
1032 fd
= open (filename
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0600);
1034 return gpg_error_from_syserror ();
1036 #ifdef HAVE_LIBREADLINE
1037 rc
= set_inquire (interactive
? STDIN_FILENO
: inquirefd
, NULL
, &inq
);
1039 rc
= set_inquire (inquirefd
, NULL
, &inq
);
1047 rc
= parse_dotcommand (p
, &result
, &len
, inq
);
1048 if (!rc
&& result
&& len
--)
1049 { // null byte which is always appended
1050 if (write (fd
, result
, len
) != len
)
1051 rc
= GPG_ERR_TOO_SHORT
;
1061 help_command (const char *line
)
1064 N_("Type HELP for protocol commands. Available pwmc commands:\n\n"
1065 " .redir <filename> <command>\n"
1066 " redirect the output of a command to the specified file\n"
1068 " .open <filename>\n"
1069 " open the specified filename losing any changes to the current one\n"
1071 " .read [--prefix <string>] <filename> <command> [args]\n"
1072 " obtain data from the specified filename for an inquire command\n"
1074 " .set help | <name> [<value>]\n"
1075 " set option <name> to <value>\n"
1078 " write changes of the file to disk\n"
1081 " change the passphrase of a data file\n"
1084 " this help text\n"));
1089 open_command (const char *line
)
1091 struct inquire_s
*inq
= NULL
;
1092 const char *file
= line
;
1095 while (file
&& isspace (*file
))
1098 if (!file
|| !*file
)
1100 fprintf (stderr
, N_("Usage: .open <filename>\n"));
1101 return GPG_ERR_SYNTAX
;
1104 #ifdef HAVE_LIBREADLINE
1105 if (interactive
|| !quiet
)
1109 fprintf (stderr
, N_("Opening data file \"%s\" ...\n"), file
);
1111 #ifdef HAVE_LIBREADLINE
1112 rc
= set_inquire (interactive
? STDIN_FILENO
: -1, NULL
, &inq
);
1114 rc
= set_inquire (-1, NULL
, &inq
);
1121 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 1);
1123 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, 1);
1127 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
1129 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, no_pinentry
);
1133 rc
= pwmd_open (pwm
, file
, inquire_cb
, inq
);
1135 #ifdef HAVE_LIBREADLINE
1143 pwmd_free (filename
);
1144 filename
= pwmd_strdup (file
);
1151 set_command (const char *line
)
1154 char name
[256] = { 0 };
1155 char value
[512] = { 0 };
1158 const char *p
= line
;
1160 while (p
&& *p
&& isspace (*p
))
1163 namep
= parse_arg (p
, name
, sizeof (name
));
1164 if (!namep
|| !*namep
)
1166 fprintf (stderr
, N_("Usage: .set help | <name> [<value>]\n"));
1167 return GPG_ERR_SYNTAX
;
1170 p
+= strlen (namep
);
1171 while (p
&& *p
&& isspace (*p
))
1174 valuep
= parse_arg (p
, value
, sizeof (value
));
1176 if (!strcmp (name
, "passphrase-file") || !strcmp (name
, "new-passphrase-file")
1177 || !strcmp (name
, "sign-passphrase-file"))
1179 int is_newkeyfile
= 1;
1180 int sign
= !strcmp (name
, "sign-passphrase-file");
1182 if (!strcmp (name
, "passphrase-file") || sign
)
1187 pwmd_free (new_keyfile
);
1192 pwmd_free (sign_keyfile
);
1193 sign_keyfile
= NULL
;
1197 pwmd_free (keyfile
);
1204 new_keyfile
= pwmd_strdup (value
);
1206 sign_keyfile
= pwmd_strdup (value
);
1208 keyfile
= pwmd_strdup (value
);
1212 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, 1);
1214 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 1);
1217 else if (!local_pin
&& !no_pinentry
)
1221 pwmd_socket_type (pwm
, &t
);
1222 if (t
== PWMD_SOCKET_LOCAL
)
1224 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, 0);
1226 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
1230 else if (!strcmp(name
, "pinentry-timeout"))
1233 int n
= strtol(valuep
, &e
, 10);
1236 return gpg_error (GPG_ERR_INV_VALUE
);
1239 n
= DEFAULT_PIN_TIMEOUT
;
1241 rc
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TIMEOUT
, n
);
1243 else if (!strcmp (name
, "help"))
1247 ("Set a libpwmd or pwmc option. The option name and optional value is space\n"
1248 "delimited. When no value is specified the option is unset.\n\n"
1249 "passphrase-file [<filename>]\n"
1250 " set or unset the file to be used when a passphrase is required (*)\n"
1252 "new-passphrase-file [<filename>]\n"
1253 " set or unset the file to be used when a new passphrase is required (*)\n"
1255 "sign-passphrase-file [<filename>]\n"
1256 " set or unset the file to be used when a passphrase is required for\n"
1257 " signing (symmetric) (*)\n"
1259 "pinentry-timeout <seconds>\n"
1260 " the amount of seconds before pinentry gives up waiting for input\n"
1262 "* = the next protocol command will unset this value\n"
1266 rc
= GPG_ERR_UNKNOWN_OPTION
;
1272 save_command (const char *line
)
1274 struct inquire_s
*inq
= NULL
;
1277 #ifdef HAVE_LIBREADLINE
1278 rc
= set_inquire (interactive
? STDIN_FILENO
: -1, NULL
, &inq
);
1280 rc
= set_inquire (-1, NULL
, &inq
);
1285 if (new_keyfile
|| keyfile
|| sign_keyfile
)
1287 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 1);
1289 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, 1);
1293 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
1295 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, no_pinentry
);
1299 rc
= pwmd_save (pwm
, line
, inquire_cb
, inq
);
1301 #ifdef HAVE_LIBREADLINE
1311 do_save_passwd_command (const char *line
, int save
)
1313 struct inquire_s
*inq
= NULL
;
1316 #ifdef HAVE_LIBREADLINE
1317 rc
= set_inquire (interactive
? STDIN_FILENO
: -1, NULL
, &inq
);
1319 rc
= set_inquire (-1, NULL
, &inq
);
1324 if (new_keyfile
|| keyfile
|| sign_keyfile
)
1326 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 1);
1328 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, 1);
1332 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
1334 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, no_pinentry
);
1340 rc
= pwmd_save (pwm
, line
, inquire_cb
, inq
);
1342 rc
= pwmd_passwd (pwm
, line
, inquire_cb
, inq
);
1345 #ifdef HAVE_LIBREADLINE
1355 parse_dotcommand (const char *line
, char **result
,
1356 size_t * len
, struct inquire_s
*inq
)
1358 const char *p
= line
;
1361 if (!strncmp (p
, ".read", 5))
1362 rc
= read_command (p
+ 5, result
, len
);
1363 else if (!strncmp (p
, ".redir", 6))
1364 rc
= redir_command (p
+ 6);
1365 else if (!strncmp (p
, ".help", 5))
1366 rc
= help_command (p
+ 5);
1367 else if (!strncmp (p
, ".open", 5))
1368 rc
= open_command (p
+ 5);
1369 else if (!strncmp (p
, ".set", 4))
1370 rc
= set_command (p
+ 4);
1371 else if (!strncmp (p
, ".save", 5))
1372 rc
= do_save_passwd_command (p
+ 5, 1);
1373 else if (!strncmp (p
, ".passwd", 7))
1374 rc
= do_save_passwd_command (p
+ 7, 0);
1377 rc
= pwmd_command (pwm
, result
, len
, inquire_cb
, inq
, "%s", line
);
1378 #ifdef HAVE_LIBREADLINE
1383 #ifdef HAVE_LIBREADLINE
1391 #ifdef HAVE_LIBREADLINE
1396 struct inquire_s
*inq
= NULL
;
1398 signal (SIGINT
, SIG_IGN
);
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 ("pwm> ");
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;
1637 int lock_on_open
= 1;
1638 long lock_timeout
= 50;
1641 /* The order is important. */
1644 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1645 OPT_SOCKET_TIMEOUT
, OPT_CONNECT_TIMEOUT
,
1648 OPT_USE_SSH_AGENT
, OPT_IDENTITY
, OPT_KNOWNHOSTS
,
1651 OPT_CACERT
, OPT_CLIENTCERT
, OPT_CLIENTKEY
, OPT_PRIORITY
, OPT_VERIFY
,
1654 OPT_URL
, OPT_LOCAL
, OPT_TTYNAME
, OPT_TTYTYPE
, OPT_DISPLAY
, OPT_LC_CTYPE
,
1655 OPT_LC_MESSAGES
, OPT_TIMEOUT
, OPT_TRIES
, OPT_PINENTRY
, OPT_KEYFILE
,
1656 OPT_PASSPHRASE_FILE
, OPT_NEW_KEYFILE
, OPT_NEW_PASSPHRASE_FILE
,
1657 OPT_SIGN_KEYFILE
, OPT_SIGN_PASSPHRASE_FILE
, OPT_NOLOCK
, OPT_LOCK_TIMEOUT
,
1658 OPT_SAVE
, OPT_OUTPUT_FD
, OPT_INQUIRE
, OPT_INQUIRE_FD
, OPT_INQUIRE_FILE
,
1659 OPT_INQUIRE_LINE
, OPT_NO_STATUS
, OPT_STATUS_IGNORE
, OPT_STATUSFD
, OPT_NAME
,
1660 OPT_VERSION
, OPT_HELP
, OPT_KEYID
, OPT_SIGN_KEYID
, OPT_SYMMETRIC
,
1661 OPT_KEYPARAMS
, OPT_NO_PINENTRY
, OPT_QUIET
,
1662 #ifdef HAVE_LIBREADLINE
1666 const struct option long_opts
[] = {
1667 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1668 {"socket-timeout", 1, 0, 0},
1669 {"connect-timeout", 1, 0, 0},
1673 {"no-ssh-agent", 0, 0, 0},
1674 {"identity", 1, 0, 'i'},
1675 {"knownhosts", 1, 0, 'k'},
1678 {"ca-cert", 1, 0, 0},
1679 {"client-cert", 1, 0, 0},
1680 {"client-key", 1, 0, 0},
1681 {"tls-priority", 1, 0, 0},
1682 {"tls-verify", 0, 0, 0},
1683 {"tls-fingerprint", 1, 0, 0},
1686 {"local-pinentry", 0, 0},
1687 {"ttyname", 1, 0, 'y'},
1688 {"ttytype", 1, 0, 't'},
1689 {"display", 1, 0, 'd'},
1690 {"lc-ctype", 1, 0, 0},
1691 {"lc-messages", 1, 0, 0},
1692 {"timeout", 1, 0, 0},
1694 {"pinentry", 1, 0, 0},
1695 {"key-file", 1, 0, 0},
1696 {"passphrase-file", 1, 0, 0},
1697 {"new-key-file", 1, 0, 0},
1698 {"new-passphrase-file", 1, 0, 0},
1699 {"sign-key-file", 1, 0, 0},
1700 {"sign-passphrase-file", 1, 0, 0},
1701 {"no-lock", 0, 0, 0},
1702 {"lock-timeout", 1, 0, 0},
1703 {"save", 0, 0, 'S'},
1704 {"output-fd", 1, 0, 0},
1705 {"inquire", 1, 0, 0},
1706 {"inquire-fd", 1, 0, 0},
1707 {"inquire-file", 1, 0, 0},
1708 {"inquire-line", 1, 0, 'L'},
1709 {"no-status", 0, 0, 0},
1710 {"status-ignore", 1, 0, 0},
1711 {"status-fd", 1, 0, 0},
1712 {"name", 1, 0, 'n'},
1713 {"version", 0, 0, 0},
1716 {"sign-keyid", 1, 0, 0},
1717 {"symmetric", 0, 0, 0},
1718 {"key-params", 1, 0, 0},
1719 {"no-pinentry", 0, 0, 0},
1721 #ifdef HAVE_LIBREADLINE
1722 {"interactive", 0, 0},
1727 const char *optstring
= "L:y:t:d:P:I:Sn:i:k:s";
1729 const char *optstring
= "L:y:t:d:P:I:Sn:s";
1734 setlocale (LC_ALL
, "");
1735 bindtextdomain ("libpwmd", LOCALEDIR
);
1738 tries
= DEFAULT_PIN_TRIES
;
1739 inquirefd
= STDIN_FILENO
;
1740 statusfd
= STDERR_FILENO
;
1741 statusfp
= fdopen (statusfd
, "w");
1742 tmp
= pwmd_strdup (DEFAULT_STATUS_IGNORE
);
1743 parse_status_ignore (tmp
);
1747 getopt_long (argc
, argv
, optstring
, long_opts
, &opt_index
)) != -1)
1751 /* Handle long options without a short option part. */
1755 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1756 case OPT_SOCKET_TIMEOUT
:
1757 socket_timeout
= strtol (optarg
, &p
, 10);
1759 case OPT_CONNECT_TIMEOUT
:
1760 connect_timeout
= strtol (optarg
, &p
, 10);
1764 case OPT_USE_SSH_AGENT
:
1772 case OPT_CLIENTCERT
:
1773 clientcert
= optarg
;
1785 tls_fingerprint
= optarg
;
1795 case OPT_PASSPHRASE_FILE
:
1796 keyfile
= pwmd_strdup (optarg
);
1798 case OPT_NEW_KEYFILE
:
1799 case OPT_NEW_PASSPHRASE_FILE
:
1800 new_keyfile
= pwmd_strdup (optarg
);
1802 case OPT_SIGN_KEYFILE
:
1803 case OPT_SIGN_PASSPHRASE_FILE
:
1804 sign_keyfile
= pwmd_strdup (optarg
);
1809 case OPT_LOCK_TIMEOUT
:
1810 lock_timeout
= strtol (optarg
, &p
, 10);
1819 lcctype
= pwmd_strdup (optarg
);
1821 case OPT_LC_MESSAGES
:
1822 lcmessages
= pwmd_strdup (optarg
);
1825 timeout
= strtol (optarg
, &p
, 10);
1828 tries
= strtol (optarg
, &p
, 10);
1831 inquire
= escape (optarg
);
1833 case OPT_INQUIRE_FD
:
1834 inquirefd
= strtol (optarg
, &p
, 10);
1837 inquirefp
= fdopen (inquirefd
, "r");
1839 err (EXIT_FAILURE
, "%i", inquirefd
);
1842 case OPT_INQUIRE_FILE
:
1843 inquirefd
= open (optarg
, O_RDONLY
);
1844 if (inquirefd
== -1)
1845 err (EXIT_FAILURE
, "%s", optarg
);
1846 inquirefp
= fdopen (inquirefd
, "r");
1849 outfd
= strtol (optarg
, &p
, 10);
1852 outfp
= fdopen (outfd
, "w");
1854 err (EXIT_FAILURE
, "%i", outfd
);
1861 statusfd
= strtol (optarg
, &p
, 10);
1864 statusfp
= fdopen (statusfd
, "w");
1866 err (EXIT_FAILURE
, "%i", statusfd
);
1869 case OPT_STATUS_IGNORE
:
1870 parse_status_ignore (optarg
);
1873 printf ("%s (pwmc)\n\n"
1874 "Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016\n"
1876 "Released under the terms of the GPL v2. Use at your own risk.\n\n"
1877 "Compile-time features:\n"
1878 #ifdef HAVE_LIBREADLINE
1893 #ifdef WITH_PINENTRY
1908 "\n", PACKAGE_STRING
, PACKAGE_BUGREPORT
);
1909 exit (EXIT_SUCCESS
);
1911 pinentry_path
= optarg
;
1914 usage (argv
[0], EXIT_SUCCESS
);
1918 case OPT_SIGN_KEYID
:
1919 sign_keyid
= optarg
;
1925 case OPT_NO_PINENTRY
:
1928 #ifdef HAVE_LIBREADLINE
1929 case OPT_INTERACTIVE
:
1934 usage (argv
[0], EXIT_FAILURE
);
1939 fprintf (stderr
, N_("%s: invalid argument for option '--%s'\n"),
1940 argv
[0], long_opts
[opt_index
].name
);
1941 usage (argv
[0], EXIT_FAILURE
);
1950 knownhosts
= optarg
;
1954 inquire_line
= optarg
;
1969 clientname
= optarg
;
1972 usage (argv
[0], EXIT_FAILURE
);
1976 #ifdef HAVE_LIBREADLINE
1977 if (interactive
&& !isatty (STDIN_FILENO
))
1978 usage (argv
[0], EXIT_FAILURE
);
1979 else if (isatty (STDIN_FILENO
) && !inquire
&& !inquire_line
)
1983 filename
= argv
[optind
] ? pwmd_strdup (argv
[optind
]) : NULL
;
1985 rc
= pwmd_new (clientname
, &pwm
);
1989 pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TRIES
, tries
);
1991 fprintf (stderr
, N_("Connecting ...\n"));
1993 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1994 socktype
= is_remote_url (url
);
1995 if (socktype
!= PWMD_SOCKET_LOCAL
)
1998 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1999 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SOCKET_TIMEOUT
, connect_timeout
);
2004 if (socktype
== PWMD_SOCKET_SSH
)
2007 rc
= pwmd_setopt (pwm
, PWMD_OPTION_KNOWNHOST_CB
, knownhost_cb
);
2011 rc
= pwmd_setopt (pwm
, PWMD_OPTION_KNOWNHOST_DATA
, clientname
);
2015 if (!getenv ("SSH_AUTH_SOCK") || identity
)
2018 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SSH_AGENT
, use_ssh_agent
);
2022 rc
= pwmd_connect (pwm
, url
, identity
, knownhosts
);
2028 rc
= pwmd_setopt (pwm
, PWMD_OPTION_TLS_VERIFY
, tls_verify
);
2032 rc
= pwmd_connect (pwm
, url
, clientcert
, clientkey
, cacert
, prio
,
2038 rc
= pwmd_connect (pwm
, url
);
2040 rc
= pwmd_connect (pwm
, url
);
2046 fprintf (stderr
, N_("Connected.\n"));
2049 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
2050 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SOCKET_TIMEOUT
, socket_timeout
);
2057 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
,
2058 "OPTION LOCK-TIMEOUT=%li", lock_timeout
);
2065 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCK_ON_OPEN
, 1);
2070 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DESC
, NULL
, NULL
);
2076 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TIMEOUT
, timeout
);
2081 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, no_pinentry
);
2085 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
,
2086 (local_pin
|| keyfile
|| new_keyfile
|| sign_keyfile
));
2092 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_PATH
, pinentry_path
);
2099 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DISPLAY
, display
);
2106 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TTY
, tty
);
2113 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TERM
, ttytype
);
2120 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_LC_CTYPE
, lcctype
);
2127 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_LC_MESSAGES
, lcmessages
);
2134 rc
= pwmd_setopt (pwm
, PWMD_OPTION_STATUS_CB
, status_msg_cb
);
2141 rc
= open_command (filename
);
2146 #ifdef HAVE_LIBREADLINE
2149 rc
= do_interactive ();
2157 struct inquire_s
*inq
= NULL
;
2159 rc
= set_inquire (inquirefd
, inquire_line
, &inq
);
2161 rc
= pwmd_command (pwm
, &result
, &len
, inquire_cb
, inq
, "%s", inquire
);
2167 if (fcntl (STDIN_FILENO
, F_SETFL
, O_NONBLOCK
) == -1)
2169 rc
= gpg_error_from_errno (errno
);
2177 rc
= process_cmd ();
2182 n
= read (STDIN_FILENO
, command
, sizeof (command
)-1);
2185 if (errno
== EAGAIN
)
2191 rc
= gpg_error_from_errno (errno
);
2202 if (!p
|| !*p
|| !strcasecmp (p
, "BYE"))
2206 struct inquire_s
*inq
= NULL
;
2207 rc
= set_inquire (inquirefd
, inquire_line
, &inq
);
2210 rc
= parse_dotcommand (command
, &result
, &len
, inq
);
2220 fwrite (result
, 1, result
[len
- 1] == 0 ? len
- 1 : len
, outfp
);
2228 else if (gpg_err_code (rc
) == GPG_ERR_BAD_DATA
)
2229 (void) pwmd_command (pwm
, &result
, NULL
, NULL
, NULL
,
2230 "GETINFO last_error");
2232 #ifdef HAVE_LIBREADLINE
2235 memset (command
, 0, sizeof (command
));
2238 show_error (pwm
, rc
, result
);
2244 pwmd_free (filename
);
2245 parse_status_ignore (NULL
);
2246 if (connected
&& !quiet
)
2247 fprintf (stderr
, N_("Connection closed.\n"));
2249 exit (rc
? EXIT_FAILURE
: EXIT_SUCCESS
);