1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2007-2008 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 02111-1307 USA
28 #include <sys/select.h>
41 #define N_(msgid) gettext(msgid)
47 #define xrealloc realloc
48 #define xmalloc malloc
49 #define xstrdup strdup
50 #define xcalloc calloc
55 static void show_error(gpg_error_t error
)
57 fprintf(stderr
, "ERR %i %s\n", gpg_err_code(error
), pwmd_strerror(error
));
60 static void usage(const char *pn
)
63 "Reads PWMD protocol commands from standard input.\n\n"
65 "Usage: pwmc [-hvX] [-s <socket>] [-E <n> -P -T -N -D | -p <password>] [-S] \n"
67 "Usage: pwmc [-hvX] [-s <socket>] [-P -T -N -D | -p <password>] [-S] \n"
69 " [-c <name>] [-d <fd>] [-I <fd>] [filename]\n"
71 " -E pinentry method (0=pwmd, 1=pwmd async, 2=libpwmd, 3=libpwmd nb)\n"
72 " -M pinentry timeout (method 3 only)\n"
74 " -X disable showing of status messages from the server\n"
75 " -c set the client name\n"
76 " -s socket path (~/.pwmd/socket)\n"
78 " -P path to the pinentry binary (server default)\n"
80 " -N pinentry terminal type\n"
81 " -D pinentry display\n"
82 " -d redirect command output to the specified file descriptor\n"
83 " -I read inquire data from the specified file descriptor\n"
84 " -S send the SAVE command before exiting\n"
86 " -h this help text\n"));
95 static gpg_error_t
do_inquire(void *data
, const char *keyword
, gpg_error_t rc
,
96 char **result
, size_t *result_len
)
99 static char buf
[ASSUAN_LINELENGTH
];
102 struct inquire_s
*inq
= (struct inquire_s
*)data
;
105 memset(buf
, 0, sizeof(buf
));
113 snprintf(buf
, sizeof(buf
), "%s", inq
->data
);
120 while ((c
= fgetc(inq
->fp
)) != EOF
) {
121 if (len
== sizeof(buf
)) {
131 memset(buf
, 0, sizeof(buf
));
140 static int status_msg_cb(void *data
, const char *line
)
142 fprintf(stderr
, "%s\n", line
);
147 static gpg_error_t
do_nb_command(int fd
, int which
)
150 gpg_error_t error
= 0;
152 fcntl(fd
, F_SETFL
, O_NONBLOCK
);
156 struct timeval tv
= {0, 50000};
160 n
= select(fd
+1, &fds
, NULL
, NULL
, &tv
);
163 if (FD_ISSET(fd
, &fds
)) {
164 pwmd_nb_status_t status
;
166 n
= read(fd
, &status
, sizeof(status
));
169 error
= gpg_error_from_errno(errno
);
174 error
= pwmd_open_nb_finalize(pwm
, &status
);
176 error
= pwmd_save_nb_finalize(pwm
, &status
);
183 fprintf(stderr
, "Waiting ...\n");
191 int main(int argc
, char *argv
[])
194 char *password
= NULL
;
195 char *filename
= NULL
;
196 char *socketpath
= NULL
;
197 char command
[ASSUAN_LINELENGTH
], *p
;
198 int ret
= EXIT_SUCCESS
;
202 char *pinentry_path
= NULL
;
203 char *display
= NULL
, *tty
= NULL
, *ttytype
= NULL
;
204 int outfd
= STDOUT_FILENO
;
205 FILE *outfp
= stdout
;
206 int inquirefd
= STDIN_FILENO
;
207 FILE *inquirefp
= stdin
;
209 char *clientname
= NULL
;
210 char *inquire
= NULL
;
217 setlocale(LC_ALL
, "");
218 bindtextdomain("libpwmd", LOCALEDIR
);
221 while ((opt
= getopt(argc
, argv
, "E:M:c:I:XT:N:D:hvP:p:s:Sd:")) != EOF
) {
223 while ((opt
= getopt(argc
, argv
, "c:I:XT:N:D:hvP:p:s:Sd:")) != EOF
) {
228 method
= atoi(optarg
);
231 timeout
= atoi(optarg
);
235 clientname
= xstrdup(optarg
);
250 inquirefd
= atoi(optarg
);
251 inquirefp
= fdopen(inquirefd
, "r");
255 err(EXIT_FAILURE
, "%i", inquirefd
);
259 outfd
= atoi(optarg
);
260 outfp
= fdopen(outfd
, "w");
264 err(EXIT_FAILURE
, "%i", outfd
);
271 socketpath
= xstrdup(optarg
);
274 password
= xstrdup(optarg
);
275 memset(optarg
, 0, strlen(optarg
));
278 pinentry_path
= xstrdup(optarg
);
282 printf("%s (pwmc)\n%s\n", PACKAGE_STRING
, PACKAGE_BUGREPORT
);
291 filename
= argv
[optind
];
294 if ((pwm
= pwmd_connect(socketpath
, &error
)) == NULL
) {
296 errx(EXIT_FAILURE
, "pwmd_connect(): %s", pwmd_strerror(error
));
299 error
= pwmd_command(pwm
, &result
, "OPTION CLIENT NAME=%s", clientname
? clientname
: "pwmc");
304 errx(EXIT_FAILURE
, "pwmd_connect(): %s", pwmd_strerror(error
));
308 error
= pwmd_setopt(pwm
, PWMD_OPTION_PASSWORD
, password
);
319 error
= pwmd_command(pwm
, &result
, "OPTION PATH=%s", pinentry_path
);
326 error
= pwmd_command(pwm
, &result
, "OPTION DISPLAY=%s", display
);
333 error
= pwmd_command(pwm
, &result
, "OPTION TTYNAME=%s", tty
);
340 error
= pwmd_command(pwm
, &result
, "OPTION TTYTYPE=%s", ttytype
);
347 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY
, 1);
356 error
= pwmd_setopt(pwm
, PWMD_OPTION_STATUS_FUNC
, status_msg_cb
);
365 error
= pwmd_open_async(pwm
, filename
);
369 s
= pwmd_process(pwm
, &error
);
370 fprintf(stderr
, "Waiting ...\n");
372 } while (s
== ASYNC_PROCESS
);
377 else if (method
== 3) {
378 int fd
= pwmd_open_nb(pwm
, &error
, filename
, timeout
);
383 error
= do_nb_command(fd
, 0);
386 error
= pwmd_open(pwm
, filename
);
388 error
= pwmd_open(pwm
, filename
);
395 p
= fgets(command
, sizeof(command
), stdin
);
401 * This is a known INQUIRE command. We use pwmd_inquire() to send the
402 * data from the do_inquire() callback function.
404 if (strncasecmp(p
, "STORE ", 6) == 0) {
408 else if (strncasecmp(p
, "IMPORT ", 7) == 0) {
414 struct inquire_s
*inq
= (struct inquire_s
*)malloc(sizeof(struct inquire_s
));
417 error
= gpg_error_from_errno(ENOMEM
);
421 inq
->data
= xstrdup(p
);
423 error
= pwmd_inquire(pwm
, inquire
, do_inquire
, inq
);
428 if (strcasecmp(p
, "BYE") == 0)
431 error
= pwmd_command(pwm
, &result
, command
);
432 memset(command
, 0, sizeof(command
));
438 fwrite(result
, 1, strlen(result
), outfp
);
439 pwmd_free_result(result
);
443 memset(command
, 0, sizeof(command
));
445 if (!error
&& save
) {
448 error
= pwmd_save_async(pwm
);
452 s
= pwmd_process(pwm
, &error
);
453 fprintf(stderr
, "Waiting ...\n");
455 } while (s
== ASYNC_PROCESS
);
460 else if (method
== 3) {
461 int fd
= pwmd_save_nb(pwm
, &error
);
466 error
= do_nb_command(fd
, 1);
469 error
= pwmd_save(pwm
);
471 error
= pwmd_save(pwm
);