1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2007 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
38 #define N_(msgid) gettext(msgid)
44 #define xrealloc realloc
45 #define xmalloc malloc
46 #define xstrdup strdup
47 #define xcalloc calloc
53 static void show_error(gpg_error_t error
)
55 fprintf(stderr
, "ERR %i %s\n", gpg_err_code(error
), pwmd_strerror(error
));
58 static void usage(const char *pn
)
61 "Reads PWMD protocol commands from standard input.\n\n"
62 "Usage: pwmc [-hvX] [-s <socket>] [-P -T -N -D -t <seconds> |\n"
63 " -p <password>] [-S] [-d <fd>] [-I <fd>] [filename]\n"
64 " -X disable showing of status messages from the server\n"
65 " -s socket path (~/.pwmd/socket)\n"
67 " -P path to the pinentry binary (%s)\n"
69 " -N pinentry terminal type\n"
70 " -D pinentry display\n"
71 " -t pinentry timeout\n"
72 " -d redirect command output to the specified file descriptor\n"
73 " -I read inquire data from the specified file descriptor\n"
74 " -S send the SAVE command before exiting\n"
76 " -h this help text\n"), PINENTRY_PATH
);
85 static gpg_error_t
do_inquire(void *data
, const char *keyword
, gpg_error_t rc
,
86 char **result
, size_t *result_len
)
89 static char buf
[ASSUAN_LINELENGTH
];
92 struct inquire_s
*inq
= (struct inquire_s
*)data
;
95 memset(buf
, 0, sizeof(buf
));
103 snprintf(buf
, sizeof(buf
), "%s", inq
->data
);
110 while ((c
= fgetc(inq
->fp
)) != EOF
) {
111 if (len
== sizeof(buf
)) {
121 memset(buf
, 0, sizeof(buf
));
130 static int status_msg_cb(void *data
, const char *line
)
132 fprintf(stderr
, "%s\n", line
);
136 int main(int argc
, char *argv
[])
139 char *password
= NULL
;
140 char *filename
= NULL
;
141 char *socketpath
= NULL
;
142 char command
[ASSUAN_LINELENGTH
], *p
;
143 int ret
= EXIT_SUCCESS
;
147 char *pinentry_path
= NULL
;
148 char *display
= NULL
, *tty
= NULL
, *ttytype
= NULL
;
150 int outfd
= STDOUT_FILENO
;
151 FILE *outfp
= stdout
;
152 int inquirefd
= STDIN_FILENO
;
153 FILE *inquirefp
= stdin
;
156 setlocale(LC_ALL
, "");
157 bindtextdomain("libpwmd", LOCALEDIR
);
160 while ((opt
= getopt(argc
, argv
, "I:XT:N:D:hvP:t:p:s:Sd:")) != EOF
) {
175 inquirefd
= atoi(optarg
);
176 inquirefp
= fdopen(inquirefd
, "r");
180 err(EXIT_FAILURE
, "%i", inquirefd
);
184 outfd
= atoi(optarg
);
185 outfp
= fdopen(outfd
, "w");
189 err(EXIT_FAILURE
, "%i", outfd
);
196 socketpath
= xstrdup(optarg
);
199 password
= xstrdup(optarg
);
200 memset(optarg
, 0, strlen(optarg
));
203 pinentry_path
= xstrdup(optarg
);
206 timeout
= atoi(optarg
);
210 printf("%s (pwmc)\n%s\n", PACKAGE_STRING
, PACKAGE_BUGREPORT
);
219 filename
= argv
[optind
];
222 if ((pwm
= pwmd_connect(socketpath
, &error
)) == NULL
) {
224 errx(EXIT_FAILURE
, "pwmd_connect(): %s", pwmd_strerror(error
));
227 error
= pwmd_command(pwm
, &result
, "OPTION CLIENT NAME=pwmc");
231 errx(EXIT_FAILURE
, "pwmd_connect(): %s", pwmd_strerror(error
));
235 error
= pwmd_setopt(pwm
, PWMD_OPTION_PASSWORD
, password
);
245 tcgetattr(STDOUT_FILENO
, &term
);
248 error
= pwmd_command(pwm
, &result
, "OPTION PATH=%s", pinentry_path
);
254 snprintf(command
, sizeof(command
), N_("A password is required for the "
255 "file \"%s\". Please\nenter the password below."), filename
);
257 error
= pwmd_command(pwm
, &result
, "OPTION DESC=%s", command
);
263 error
= pwmd_command(pwm
, &result
, "OPTION DISPLAY=%s", display
);
270 error
= pwmd_command(pwm
, &result
, "OPTION TTYNAME=%s", tty
);
277 error
= pwmd_command(pwm
, &result
, "OPTION TTYTYPE=%s", ttytype
);
285 error
= pwmd_setopt(pwm
, PWMD_OPTION_STATUS_FUNC
, status_msg_cb
);
293 error
= pwmd_command(pwm
, &result
, "OPTION TIMEOUT=%i", timeout
);
299 error
= pwmd_open(pwm
, filename
);
302 if (!password
&& error
== GPG_ERR_TIMEOUT
)
303 tcsetattr(STDOUT_FILENO
, TCSANOW
, &term
);
310 p
= fgets(command
, sizeof(command
), stdin
);
316 * This is a known INQUIRE command. We use pwmd_inquire() to send the
317 * data from the do_inquire() callback function.
319 if (strncasecmp(p
, "STORE ", 6) == 0) {
320 struct inquire_s
*inq
= (struct inquire_s
*)malloc(sizeof(struct inquire_s
));
323 error
= gpg_error_from_errno(ENOMEM
);
327 inq
->data
= xstrdup(p
+6);
329 error
= pwmd_inquire(pwm
, "STORE", do_inquire
, inq
);
334 if (strcasecmp(p
, "BYE") == 0)
337 error
= pwmd_command(pwm
, &result
, command
);
338 memset(command
, 0, sizeof(command
));
344 fwrite(result
, 1, strlen(result
), outfp
);
345 pwmd_free_result(result
);
349 memset(command
, 0, sizeof(command
));
351 if (!error
&& save
) {
353 error
= pwmd_save(pwm
);
356 if (error
== EPWMD_BADKEY
|| error
== EPWMD_KEY
)