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
34 #define N_(msgid) gettext(msgid)
40 #define xrealloc realloc
41 #define xmalloc malloc
42 #define xstrdup strdup
43 #define xcalloc calloc
49 static void show_error(gpg_error_t error
)
51 fprintf(stderr
, "ERR %i %s\n", gpg_err_code(error
), pwmd_strerror(error
));
54 void catchsig(int sig
)
60 if (pwm
&& timeout
> 0 && elapsed
++ >= timeout
) {
61 error
= pwmd_terminate_pinentry(pwm
);
76 static void usage(const char *pn
)
79 "Reads PWMD protocol commands from standard input.\n\n"
80 "Usage: pwmc [-hv] [-E] [-s <socket>] [[-a [-P -T -N -D] [-t <seconds>]] |\n"
81 " [-p <password>]] [-S] [-d <descriptor>] [filename]\n"
82 " -E exit after a command failure\n"
85 " -a use pinentry(1) for password retrieval\n"
86 " -P path to the pinentry binary (%s)\n"
88 " -N pinentry terminal type\n"
89 " -D pinentry display\n"
90 " -t pinentry timeout\n"
91 " -d redirect command output to the specified file descriptor\n"
92 " -S send the SAVE command after all others\n"
94 " -h this help text\n"), PINENTRY_PATH
);
98 int set_pinentry_option(int option
, char *value
)
102 error
= pwmd_setopt(pwm
, option
, value
);
113 int main(int argc
, char *argv
[])
116 int use_pinentry
= 0;
117 char *password
= NULL
;
118 char *filename
= NULL
;
119 char *socketpath
= NULL
;
120 char command
[8196], *p
;
121 int ret
= EXIT_SUCCESS
;
128 char *pinentry_path
= NULL
;
129 char *display
= NULL
, *tty
= NULL
, *ttytype
= NULL
;
132 FILE *outfp
= stdout
;
134 setlocale(LC_ALL
, "");
135 bindtextdomain("libpwmd", LOCALEDIR
);
138 while ((opt
= getopt(argc
, argv
, "T:N:D:EhvaP:t:p:s:Sd:")) != EOF
) {
150 outfd
= atoi(optarg
);
159 socketpath
= xstrdup(optarg
);
162 password
= xstrdup(optarg
);
168 pinentry_path
= xstrdup(optarg
);
171 timeout
= atoi(optarg
);
174 printf("%s (pwmc)\n%s\n", PACKAGE_STRING
, PACKAGE_BUGREPORT
);
182 if (use_pinentry
&& password
) {
187 filename
= argv
[optind
];
190 if ((pwm
= pwmd_connect(socketpath
, &error
)) == NULL
) {
192 errx(EXIT_FAILURE
, "pwmd_connect(): %s", pwmd_strerror(error
));
196 if (set_pinentry_option(PWMD_OPTION_PASSWORD
, password
)) {
203 else if (use_pinentry
) {
204 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY
, 1);
212 if (set_pinentry_option(PWMD_OPTION_PINENTRY_PATH
, pinentry_path
))
215 if (set_pinentry_option(PWMD_OPTION_PINENTRY_TITLE
,
216 N_("Password Manager Daemon")))
219 snprintf(command
, sizeof(command
), N_("A password is required for the "
220 "file \"%s\". Please\nenter the password below."), filename
);
222 if (set_pinentry_option(PWMD_OPTION_PINENTRY_DESC
, command
))
226 if (set_pinentry_option(PWMD_OPTION_PINENTRY_DISPLAY
, display
))
231 if (set_pinentry_option(PWMD_OPTION_PINENTRY_TTY
, tty
))
236 if (set_pinentry_option(PWMD_OPTION_PINENTRY_TERM
, ttytype
))
242 if (use_pinentry
&& timeout
!= -1) {
243 tcgetattr(STDOUT_FILENO
, &term
);
244 signal(SIGALRM
, catchsig
);
248 error
= pwmd_open(pwm
, filename
);
251 if (error
== GPG_ERR_TIMEOUT
) {
252 tcsetattr(STDOUT_FILENO
, 0, &term
);
262 signal(SIGALRM
, SIG_IGN
);
266 outfp
= fdopen(outfd
, "w");
268 while ((p
= fgets(command
, sizeof(command
), stdin
)) != NULL
) {
272 if (p
[len
- 1] != '\n' && feof(stdin
) != 1) {
273 if ((t
= (char *)xrealloc(buf
, (total
+ len
+ 1) * sizeof(char))) == NULL
) {
277 memset(&command
, 0, sizeof(command
));
278 err(EXIT_FAILURE
, "xrealloc()");
282 memcpy(&buf
[total
], p
, len
);
289 if ((t
= (char *)xrealloc(buf
, (total
+ len
+ 1) * sizeof(char))) == NULL
) {
293 memset(&command
, 0, sizeof(command
));
294 err(EXIT_FAILURE
, "xrealloc()");
298 memcpy(&buf
[total
], p
, len
);
304 p
= buf
? buf
: command
;
306 if (p
[strlen(p
) - 1] == '\n')
307 p
[strlen(p
) - 1] = 0;
309 if (strcasecmp(p
, "BYE") == 0)
312 error
= pwmd_command(pwm
, &result
, p
);
321 memset(&command
, 0, sizeof(command
));
339 memset(&command
, 0, sizeof(command
));
342 if (result
[strlen(result
) - 1] == '\n')
343 result
[strlen(result
) - 1] = 0;
345 fwrite(result
, 1, strlen(result
), outfp
);
346 pwmd_free_result(result
);
354 memset(&command
, 0, sizeof(command
));
358 error
= pwmd_save(pwm
);
361 if (use_pinentry
&& (error
== EPWMD_BADKEY
|| error
== EPWMD_KEY
))