1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2007-2010 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301 USA
31 #include <sys/select.h>
33 #include <sys/types.h>
41 #ifdef HAVE_GETOPT_LONG
46 #include "getopt_long.h"
49 #ifdef HAVE_LIBREADLINE
50 # if defined(HAVE_READLINE_READLINE_H)
51 # include <readline/readline.h>
52 # elif defined(HAVE_READLINE_H)
53 # include <readline.h>
54 # endif /* !defined(HAVE_READLINE_H) */
55 static int interactive_error
;
56 static int interactive
;
57 #endif /* HAVE_LIBREADLINE */
59 #ifdef HAVE_READLINE_HISTORY
60 # if defined(HAVE_READLINE_HISTORY_H)
61 # include <readline/history.h>
62 # elif defined(HAVE_HISTORY_H)
65 #endif /* HAVE_READLINE_HISTORY */
68 #define N_(msgid) gettext(msgid)
72 #define DEFAULT_PORT 22
75 static char *filename
;
78 static int force_save
;
81 static char *password
;
96 static gpg_error_t
finalize();
98 static void show_error(gpg_error_t error
)
100 fprintf(stderr
, "ERR %i %s\n", gpg_err_code(error
), pwmd_strerror(error
));
103 static void usage(const char *pn
, int status
)
105 fprintf(status
== EXIT_FAILURE
? stderr
: stdout
, N_(
106 "Read a PWMD protocol command from standard input.\n\n"
107 "Usage: pwmc [options] [file]\n"
110 " pinentry method (0=pwmd, 1=libpwmd, 2=pwmd async, "
115 " --host, -h <hostname>\n"
116 " connect to the specified hostname\n"
119 " alterate port (22)\n"
121 " --user <username>\n"
122 " SSH username (default is the invoking user)\n"
125 " use the SSH agent for authentication\n"
127 " --identity, -i <filename>\n"
128 " SSH identity file (if not using the SSH agent)\n"
130 " --known-hosts, -k <filename>\n"
131 " known hosts file (~/.ssh/known_hosts)\n"
133 " --get-hostkey, -g\n"
134 " retrieve the remote SSH host key and exit\n"
137 " try connecting via IPv4 only\n"
140 " try connecting via IPv6 only\n"
144 " a url string to parse (see below)\n"
147 " disable showing of status messages from the server\n"
149 " --name, -n <string>\n"
150 " set the client name\n"
152 " --socket <filename>\n"
153 " local socket to connect to (~/.pwmd/socket)\n"
155 " --passphrase, -P <string>\n"
156 " passphrase to use (disables pinentry use)\n"
158 " --key-file <filename>\n"
159 " obtain the passphrase from the specified filename\n"
162 " the passphrase is base64 encoded\n"
164 " --timeout <seconds>\n"
165 " pinentry timeout\n"
168 " number of pinentry tries before failing (3)\n"
170 " --pinentry <path>\n"
171 " the full path to the pinentry binary (server default)\n"
173 " --ttyname, -y <path>\n"
174 " tty that pinentry will use\n"
176 " --ttytype, -t <string>\n"
177 " pinentry terminal type (default is $TERM)\n"
180 " pinentry display (default is $DISPLAY)\n"
182 " --lc-ctype <string>\n"
183 " locale setting for pinentry\n"
185 " --lc-messages <string>\n"
186 " locale setting for pinentry\n"
188 " --local-pinentry\n"
189 " force using a local pinentry\n"
192 " use a shell like interface to pwmd (allows more than one command)\n"
194 " --output-fd <FD>\n"
195 " redirect command output to the specified file descriptor\n"
197 " --inquire <COMMAND>\n"
198 " the specified command (with any options) uses a server inquire while\n"
199 " command data is read via the inquire file descriptor (stdin)\n"
201 " --inquire-fd <FD>\n"
202 " read inquire data from the specified file descriptor (stdin)\n"
204 " --inquire-line, -L <STRING>\n"
205 " the initial line to send (i.e., element path) before the inquire data\n"
207 " --cipher <string>\n"
208 " the cipher to use when saving (see pwmd(1))\n"
211 " send the SAVE command before exiting\n"
214 " like --save but always ask for a passphrase\n"
216 " --iterations, -I <N>\n"
217 " encrypt with the specified number of iterations\n"
221 fprintf(status
== EXIT_FAILURE
? stderr
: stdout
, N_(
223 "A url string (specified with --url) may be in the form of:\n"
224 " file://[path/to/socket]\n"
226 " ssh[46]://[username@]hostname[:port],identity[,known_hosts]\n"
228 " ssh[46]://[username@]hostname[:port][,,known_hosts] --use-agent\n"
234 static gpg_error_t
inquire_cb(void *user
, const char *cmd
, gpg_error_t rc
,
235 char **data
, size_t *len
)
237 struct inquire_s
*inq
= user
;
245 if (interactive
== 1) {
248 "------------------------------------------------------------------------------\n"
249 "Press CTRL-D to end. Press twice on a non-empty line. Pressing ENTER after\n"
250 "each line during the inquire will send that line including the newline\n"
252 "------------------------------------------------------------------------------\n"
256 /* The first part of the command data. */
264 *len
= read(inq
->fd
, inq
->line
, ASSUAN_LINELENGTH
);
267 return gpg_error_from_syserror();
272 return *len
? 0 : GPG_ERR_EOF
;
275 static int status_msg_cb(void *data
, const char *line
)
277 fprintf(stderr
, "%s\n", line
);
281 static gpg_error_t
process_cmd(pwm_t
*pwm
, char **result
, int input
, int once
)
290 pwmd_fd_t pfds
[nfds
];
291 struct timeval tv
= {0, 50000};
294 rc
= pwmd_get_fds(pwm
, pfds
, &nfds
);
300 s
= pwmd_process(pwm
, &rc
, result
);
304 for (i
= 0, n
= 0; i
< nfds
; i
++) {
305 FD_SET(pfds
[i
].fd
, &rfds
);
306 n
= pfds
[i
].fd
> n
? pfds
[i
].fd
: n
;
310 FD_SET(STDIN_FILENO
, &rfds
);
312 nfds
= select(n
+1, &rfds
, NULL
, NULL
, &tv
);
315 rc
= gpg_error_from_errno(errno
);
319 if (input
&& FD_ISSET(STDIN_FILENO
, &rfds
))
322 s
= pwmd_process(pwm
, &rc
, result
);
326 } while (s
== ASYNC_PROCESS
);
332 static gpg_error_t
knownhost_cb(void *data
, const char *host
, const char *key
,
336 char *buf
= pwmd_strdup_printf(N_("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?"), (char *)data
, host
, host
);
338 rc
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TITLE
, buf
);
344 return pwmd_getpin(pwm
, NULL
, NULL
, PWMD_PINENTRY_CONFIRM
);
347 static int is_remote_url(const char *str
)
349 if (strstr(str
, "file://") || strstr(str
, "local://"))
356 static char *escape(const char *str
)
359 char *buf
= pwmd_malloc(ASSUAN_LINELENGTH
+1), *b
= buf
;
362 for (p
= str
; *p
; p
++, len
++) {
363 if (len
== ASSUAN_LINELENGTH
)
404 static gpg_error_t
send_inquire(int fd
, const char *command
, const char *line
)
406 struct inquire_s inq
;
410 if (fstat(fd
, &st
) == -1)
411 return gpg_error_from_syserror();
413 memset(&inq
, 0, sizeof(inq
));
415 inq
.line
= pwmd_calloc(1, ASSUAN_LINELENGTH
);
419 return GPG_ERR_ENOMEM
;
422 char *s
= escape(line
);
424 strncpy(inq
.line
, s
, ASSUAN_LINELENGTH
-1);
429 rc
= pwmd_setopt(pwm
, PWMD_OPTION_INQUIRE_TOTAL
,
430 st
.st_size
? st
.st_size
+strlen(inq
.line
) : 0);
435 rc
= pwmd_inquire(pwm
, command
, inquire_cb
, &inq
);
440 #ifdef HAVE_LIBREADLINE
441 static int interactive_hook(void)
443 interactive_error
= process_cmd(pwm
, NULL
, 0, 1);
445 if (interactive_error
)
446 rl_event_hook
= NULL
;
451 static gpg_error_t
do_interactive()
453 gpg_error_t rc
= process_cmd(pwm
, NULL
, 0, 1);
458 fprintf(stderr
, N_("WARNING: interactive mode doesn't use secure memory!\n"));
460 "------------------------------------------------------------------------------\n"
461 "Type HELP for protocol command help (since pwmd 2.19). Commands which use a\n"
462 "server inquire need a non-protocol command to send the data. These commands\n"
463 "including any options are:\n"
465 " INQUIRE <command> - to read from the terminal\n"
466 " INQUIRE_FILE <filename> <command> - to read the specified filename\n"
468 "Elements are TAB delimited. Press CTRL-V then TAB to insert from the prompt.\n"
469 "------------------------------------------------------------------------------\n"
472 rl_event_hook
= &interactive_hook
;
473 rl_set_keyboard_input_timeout(100000);
479 line
= readline("pwm> ");
481 if (interactive_error
)
482 return interactive_error
;
490 fprintf(stderr
, "ERR %i: %s\n", rc
, pwmd_strerror(rc
));
498 #ifdef HAVE_READLINE_HISTORY
502 /* INQUIRE <COMMAND [options ...]> */
503 if (!strncasecmp(line
, "inquire ", 8))
504 rc
= send_inquire(STDIN_FILENO
, line
+8, NULL
);
505 /* INQUIRE_FILE <FILENAME> <COMMAND [options ...]> */
506 else if (!strncasecmp(line
, "inquire_file ", 13)) {
507 char *p
= strchr(line
+13, ' ');
508 char *f
= p
? line
+13 : NULL
;
511 if (!f
|| !*f
|| !*p
) {
512 fprintf(stderr
, N_("Syntax error. Usage: INQUIRE_FILE <filename> <command>\n"));
517 f
[strlen(f
) - strlen(p
++)] = 0;
518 fd
= open(f
, O_RDONLY
);
521 fprintf(stderr
, "%s\n", strerror(errno
));
526 rc
= send_inquire(fd
, p
, NULL
);
531 rc
= pwmd_command(pwm
, &result
, line
);
536 fprintf(stderr
, "ERR %i: %s\n", rc
, pwmd_strerror(rc
));
537 else if (result
&& *result
)
538 printf("%s%s", result
, result
[strlen(result
)-1] != '\n' ? "\n" : "");
548 static gpg_error_t
finalize()
552 #ifdef HAVE_LIBREADLINE
553 if (!force_save
&& interactive
&& filename
) {
556 fprintf(stderr
, "\n");
559 fprintf(stderr
, N_("Do you want to save your changes? [y/n]: "));
560 p
= fgets(buf
, sizeof(buf
), stdin
);
561 } while (!p
|| (*p
!= 'n' && *p
!= 'y'));
570 if (save
&& filename
) {
571 fprintf(stderr
, N_("Saving changes ...\n"));
574 rc
= pwmd_setopt(pwm
, PWMD_OPTION_ITERATIONS
, iter
);
581 rc
= pwmd_setopt(pwm
, PWMD_OPTION_CIPHER
, cipher
);
591 rc
= pwmd_command(pwm
, NULL
, "ISCACHED %s", filename
);
593 if (rc
&& rc
!= GPG_ERR_NOT_FOUND
&&
594 rc
!= GPG_ERR_ENOENT
)
600 rc
= pwmd_getpin(pwm
, filename
, &p1
, PWMD_PINENTRY_SAVE
);
605 rc
= pwmd_getpin(pwm
, filename
, &password
,
606 PWMD_PINENTRY_SAVE_CONFIRM
);
613 if ((p1
|| password
) && ((!p1
&& password
) || (!password
&& p1
) ||
614 strcmp(p1
, password
))) {
624 rc
= pwmd_setopt(pwm
, PWMD_OPTION_PASSPHRASE
, password
);
634 rc
= pwmd_command(pwm
, NULL
, "CLEARCACHE %s", filename
);
640 rc
= pwmd_setopt(pwm
, PWMD_OPTION_PASSPHRASE
, NULL
);
648 if (keyfile
&& !local_pin
) {
649 struct inquire_s inq
;
651 memset(&inq
, 0, sizeof(inq
));
652 inq
.fd
= open(keyfile
, O_RDONLY
);
655 rc
= gpg_error_from_syserror();
659 inq
.line
= pwmd_calloc(1, ASSUAN_LINELENGTH
);
666 rc
= pwmd_save_inquire(pwm
, inquire_cb
, &inq
);
677 rc
= pwmd_save2(pwm
);
680 rc
= pwmd_save_async(pwm
);
683 rc
= pwmd_save_async2(pwm
);
687 if (!rc
&& method
>= 2)
688 rc
= process_cmd(pwm
, NULL
, 0, 0);
693 rc
= pwmd_save2(pwm
);
704 int main(int argc
, char *argv
[])
709 char *socketpath
= NULL
;
710 char command
[ASSUAN_LINELENGTH
], *p
;
711 int ret
= EXIT_SUCCESS
;
713 char *pinentry_path
= NULL
;
714 char *display
= NULL
, *tty
= NULL
, *ttytype
= NULL
, *lcctype
= NULL
,
716 int outfd
= STDOUT_FILENO
;
717 FILE *outfp
= stdout
;
718 int inquirefd
= STDIN_FILENO
;
719 FILE *inquirefp
= stdin
;
721 char *clientname
= "pwmc";
722 char *inquire
= NULL
;
723 char *inquire_line
= NULL
;
728 int port
= DEFAULT_PORT
;
729 char *username
= NULL
;
731 char *known_hosts
= NULL
;
733 int prot
= PWMD_IP_ANY
;
740 int lock_on_open
= 1;
744 char *url_string
= NULL
;
745 /* The order is important. */
751 OPT_HOST
, OPT_PORT
, OPT_IDENTITY
, OPT_KNOWN_HOSTS
, OPT_USER
,
752 OPT_GET_HOSTKEY
, OPT_IPV4
, OPT_IPV6
, OPT_USE_AGENT
,
754 OPT_URL
, OPT_LOCAL
, OPT_FORCE_SAVE
, OPT_TTYNAME
, OPT_TTYTYPE
,
755 OPT_DISPLAY
, OPT_LC_CTYPE
, OPT_LC_MESSAGES
, OPT_TIMEOUT
, OPT_TRIES
,
756 OPT_PINENTRY
, OPT_PASSPHRASE
, OPT_KEYFILE
, OPT_BASE64
, OPT_SOCKET
,
757 OPT_NOLOCK
, OPT_SAVE
, OPT_ITERATIONS
, OPT_OUTPUT_FD
, OPT_INQUIRE
,
758 OPT_INQUIRE_FD
, OPT_INQUIRE_LINE
, OPT_NO_STATUS
, OPT_NAME
,
759 OPT_VERSION
, OPT_HELP
, OPT_CIPHER
,
760 #ifdef HAVE_LIBREADLINE
764 const struct option long_opts
[] = {
766 { "debug", 1, 0, 0 },
769 { "host", 1, 0, 'h' },
770 { "port", 1, 0, 'p' },
771 { "identity", 1, 0, 'i' },
772 { "known-hosts", 1, 0, 'k' },
773 { "user", 1, 0, 'u' },
774 { "get-hostkey", 0, 0, 'g' },
775 { "ipv4", 0, 0, '4' },
776 { "ipv6", 0, 0, '6' },
777 { "use-agent", 0, 0, 0 },
780 { "local-pinentry", 0, 0 },
781 { "force-save", 0, 0 },
782 { "ttyname", 1, 0, 'y' },
783 { "ttytype", 1, 0, 't' },
784 { "display", 1, 0, 'd' },
785 { "lc-ctype", 1, 0, 0 },
786 { "lc-messages", 1, 0, 0 },
787 { "timeout", 1, 0, 0 },
788 { "tries", 1, 0, 0 },
789 { "pinentry", 1, 0, 0 },
790 { "passphrase", 1, 0, 'P' },
791 { "key-file", 1, 0, 0 },
792 { "base64", 0, 0, 0 },
793 { "socket", 1, 0, 0 },
794 { "no-lock", 0, 0, 0 },
795 { "save", 0, 0, 'S' },
796 { "iterations", 1, 0, 'I' },
797 { "output-fd", 1, 0, 0 },
798 { "inquire", 1, 0, 0 },
799 { "inquire-fd", 1, 0, 0 },
800 { "inquire-line", 1, 0, 'L' },
801 { "no-status", 0, 0, 0 },
802 { "name", 1, 0, 'n' },
803 { "version", 0, 0, 0 },
805 { "cipher", 1, 0, 0 },
806 #ifdef HAVE_LIBREADLINE
807 { "interactive", 0, 0 },
812 const char *optstring
= "L:46h:p:i:k:u:gy:t:d:P:I:Sn:";
814 const char *optstring
= "L:y:t:d:P:I:Sn:";
819 setlocale(LC_ALL
, "");
820 bindtextdomain("libpwmd", LOCALEDIR
);
823 #ifdef HAVE_LIBREADLINE
824 if (!strcmp(basename(argv
[0]), "pwmsh"))
830 while ((opt
= getopt_long(argc
, argv
, optstring
, long_opts
, &opt_index
)) != -1) {
832 /* Handle long options without a short option part. */
837 method
= atoi(optarg
);
864 save
= force_save
= 1;
867 lcctype
= pwmd_strdup(optarg
);
869 case OPT_LC_MESSAGES
:
870 lcmessages
= pwmd_strdup(optarg
);
873 timeout
= atoi(optarg
);
876 tries
= atoi(optarg
);
880 socketpath
= pwmd_strdup(optarg
);
886 inquirefd
= atoi(optarg
);
887 inquirefp
= fdopen(inquirefd
, "r");
891 err(EXIT_FAILURE
, "%i", inquirefd
);
895 outfd
= atoi(optarg
);
896 outfp
= fdopen(outfd
, "w");
900 err(EXIT_FAILURE
, "%i", outfd
);
908 printf("%s (pwmc)\n%s\n\n"
909 "Compile-time features:\n"
930 #ifdef HAVE_LIBREADLINE
936 , PACKAGE_STRING
, PACKAGE_BUGREPORT
);
939 pinentry_path
= optarg
;
942 usage(argv
[0], EXIT_SUCCESS
);
946 #ifdef HAVE_LIBREADLINE
947 case OPT_INTERACTIVE
:
952 usage(argv
[0], EXIT_FAILURE
);
964 host
= pwmd_strdup(optarg
);
970 ident
= pwmd_strdup(optarg
);
973 username
= pwmd_strdup(optarg
);
976 known_hosts
= pwmd_strdup(optarg
);
983 inquire_line
= optarg
;
998 iter
= strtol(optarg
, NULL
, 10);
1002 password
= pwmd_strdup(optarg
);
1003 memset(optarg
, 0, strlen(optarg
));
1006 clientname
= optarg
;
1009 pwmd_free(password
);
1010 usage(argv
[0], EXIT_FAILURE
);
1014 #ifdef HAVE_LIBREADLINE
1015 if (interactive
&& !isatty(STDIN_FILENO
)) {
1016 pwmd_free(password
);
1017 usage(argv
[0], EXIT_FAILURE
);
1025 if (host
&& !get
&& !ident
) {
1026 pwmd_free(password
);
1027 usage(argv
[0], EXIT_FAILURE
);
1031 pwmd_free(password
);
1032 usage(argv
[0], EXIT_FAILURE
);
1039 filename
= argv
[optind
];
1041 pwm
= pwmd_new(clientname
);
1047 if (host
|| url_string
) {
1052 if (prot
!= PWMD_IP_ANY
) {
1053 error
= pwmd_setopt(pwm
, PWMD_OPTION_IP_VERSION
, prot
);
1059 error
= pwmd_setopt(pwm
, PWMD_OPTION_KNOWNHOST_CB
, knownhost_cb
);
1064 error
= pwmd_setopt(pwm
, PWMD_OPTION_KNOWNHOST_DATA
, clientname
);
1069 error
= pwmd_setopt(pwm
, PWMD_OPTION_SSH_AGENT
, use_agent
);
1074 fprintf(stderr
, N_("Connecting ...\n"));
1081 error
= pwmd_get_hostkey_async(pwm
, host
, port
);
1084 errx(EXIT_FAILURE
, "%s: %s", host
, pwmd_strerror(error
));
1086 error
= process_cmd(pwm
, &hostkey
, 0, 0);
1091 printf("%s", hostkey
);
1093 pwmd_free(password
);
1099 error
= pwmd_connect_url_async(pwm
, url_string
);
1101 error
= pwmd_ssh_connect_async(pwm
, host
, port
, ident
, username
,
1107 error
= process_cmd(pwm
, NULL
, 0, 0);
1117 error
= pwmd_get_hostkey(pwm
, host
, port
, &hostkey
);
1122 printf("%s", hostkey
);
1124 pwmd_free(password
);
1130 error
= pwmd_connect_url(pwm
, url_string
);
1132 error
= pwmd_ssh_connect(pwm
, host
, port
, ident
, username
, known_hosts
);
1143 error
= pwmd_connect_url(pwm
, url_string
);
1145 error
= pwmd_connect(pwm
, socketpath
);
1153 fprintf(stderr
, N_("Connected.\n"));
1154 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TITLE
, NULL
);
1155 error
= pwmd_socket_type(pwm
, &s
);
1161 if (s
== PWMD_SOCKET_SSH
&& force_save
&& !local_pin
) {
1162 error
= GPG_ERR_WRONG_KEY_USAGE
;
1168 error
= pwmd_command(pwm
, &result
, "VERSION");
1176 pwmd_free(password
);
1178 usage(argv
[0], EXIT_FAILURE
);
1182 if (filename
&& lock_on_open
) {
1183 error
= pwmd_setopt(pwm
, PWMD_OPTION_LOCK_ON_OPEN
, 1);
1190 error
= pwmd_setopt(pwm
, PWMD_OPTION_BASE64
, 1);
1197 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TIMEOUT
, timeout
);
1203 if (local_pin
&& filename
&& !keyfile
) {
1204 error
= pwmd_command(pwm
, NULL
, "ISCACHED %s", filename
);
1206 if (error
== GPG_ERR_NOT_FOUND
) {
1208 if (try++ == local_tries
)
1212 pwmd_free(password
);
1217 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TIMEOUT
, 0);
1219 error
= pwmd_getpin(pwm
, filename
, &password
,
1220 try > 1 ? PWMD_PINENTRY_OPEN_FAILED
: PWMD_PINENTRY_OPEN
);
1225 error
= pwmd_setopt(pwm
, PWMD_OPTION_PASSPHRASE
, password
);
1233 else if (error
&& error
!= GPG_ERR_ENOENT
)
1238 error
= pwmd_setopt(pwm
, PWMD_OPTION_PASSPHRASE
, password
);
1244 if (pinentry_path
) {
1245 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_PATH
, pinentry_path
);
1252 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_DISPLAY
, display
);
1259 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TTY
, tty
);
1266 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TERM
, ttytype
);
1273 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_LC_CTYPE
, lcctype
);
1280 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_LC_MESSAGES
,
1288 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TRIES
, tries
);
1296 error
= pwmd_setopt(pwm
, PWMD_OPTION_STATUS_CB
, status_msg_cb
);
1304 fprintf(stderr
, N_("Opening data file \"%s\" ...\n"), filename
);
1307 if (keyfile
&& (!local_pin
|| host
|| is_remote_url(url_string
))) {
1308 struct inquire_s inq
;
1310 memset(&inq
, 0, sizeof(inq
));
1311 inq
.fd
= open(keyfile
, O_RDONLY
);
1314 error
= gpg_error_from_syserror();
1318 inq
.line
= pwmd_calloc(1, ASSUAN_LINELENGTH
);
1321 error
= GPG_ERR_ENOMEM
;
1325 error
= pwmd_open_inquire(pwm
, filename
, inquire_cb
, &inq
);
1326 pwmd_free(inq
.line
);
1338 error
= pwmd_open(pwm
, filename
);
1341 error
= pwmd_open2(pwm
, filename
);
1344 error
= pwmd_open_async(pwm
, filename
);
1348 error
= pwmd_open_async2(pwm
, filename
);
1352 if (error
&& local_pin
&& error
== GPG_ERR_INV_PASSPHRASE
)
1353 goto local_password
;
1359 error
= process_cmd(pwm
, &result
, 0, 0);
1363 error
= pwmd_open2(pwm
, filename
);
1366 error
= pwmd_open(pwm
, filename
);
1368 if (error
&& local_pin
&& error
== GPG_ERR_INV_PASSPHRASE
)
1369 goto local_password
;
1379 #ifdef HAVE_LIBREADLINE
1384 error
= do_interactive();
1390 int fd
= fileno(inquirefp
);
1393 error
= gpg_error_from_syserror();
1397 error
= send_inquire(fd
, inquire
, inquire_line
);
1402 fcntl(STDIN_FILENO
, F_SETFL
, O_NONBLOCK
);
1406 error
= process_cmd(pwm
, NULL
, 1, 0);
1411 n
= read(STDIN_FILENO
, command
, sizeof(command
));
1414 if (errno
== EAGAIN
)
1417 error
= gpg_error_from_errno(errno
);
1431 if (strcasecmp(p
, "BYE") == 0)
1434 error
= pwmd_command(pwm
, &result
, command
);
1440 fwrite(result
, 1, strlen(result
), outfp
);
1447 pwmd_free(password
);
1455 memset(command
, 0, sizeof(command
));
1465 pwmd_free(socketpath
);