Added a 'deb' Makefile target.
[libpwmd.git] / pwmc.c
blob73c03ed937eaffcdb912f4e18831524119218328
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
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
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <err.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <signal.h>
26 #include <termios.h>
27 #include <libpwmd.h>
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
33 #include "mem.h"
35 int timeout, elapsed;
36 pwm_t *pwm;
38 static void show_error(gpg_error_t error)
40 fprintf(stderr, "ERR %i %s\n", gpg_err_code(error), pwmd_strerror(error));
43 void catchsig(int sig)
45 gpg_error_t error;
47 switch (sig) {
48 case SIGALRM:
49 if (pwm && timeout > 0 && elapsed++ >= timeout) {
50 error = pwmd_terminate_pinentry(pwm);
52 if (error)
53 show_error(error);
55 break;
58 alarm(1);
59 break;
60 default:
61 break;
65 static void usage(const char *pn)
67 fprintf(stderr,
68 "Reads PWMD protocol commands from standard input.\n\n"
69 "Usage: %s [-hv] [-E] [-s <socket>] [[-a [-P pinentry] [-t <seconds>]] |\n"
70 " [-p <password>]] [-S] [filename]\n"
71 " -E exit after a command failure\n"
72 " -s socket path\n"
73 " -p password\n"
74 " -a use pinentry(1) for password retrieval\n"
75 " -P path to the pinentry binary (/usr/bin/pinentry)\n"
76 " -t pinentry timeout\n"
77 " -S send the SAVE command after all others\n"
78 " -v version\n"
79 " -h this help text\n",
80 pn);
81 exit(EXIT_FAILURE);
84 int main(int argc, char *argv[])
86 int opt;
87 int use_pinentry = 0;
88 char *password = NULL;
89 char *filename = NULL;
90 char *socketpath = NULL;
91 char command[8196], *p;
92 int ret = EXIT_SUCCESS;
93 gpg_error_t error;
94 char *result = NULL;
95 int save = 0;
96 char *buf = NULL;
97 int total = 0;
98 int do_exit = 0;
99 char *pinentry_path = NULL;
100 struct termios term;
102 timeout = -1;
104 while ((opt = getopt(argc, argv, "EhvaP:t:p:s:S")) != EOF) {
105 switch (opt) {
106 case 'E':
107 do_exit = 1;
108 break;
109 case 'S':
110 save = 1;
111 break;
112 case 's':
113 socketpath = xstrdup(optarg);
114 break;
115 case 'p':
116 password = xstrdup(optarg);
117 break;
118 case 'a':
119 use_pinentry = 1;
120 break;
121 case 'P':
122 pinentry_path = xstrdup(optarg);
123 break;
124 case 't':
125 timeout = atoi(optarg);
126 break;
127 case 'v':
128 printf("%s (pwmc)\n%s\n", PACKAGE_STRING, PACKAGE_BUGREPORT);
129 exit(EXIT_SUCCESS);
130 case 'h':
131 default:
132 usage(argv[0]);
136 if (use_pinentry && password) {
137 xfree(password);
138 usage(argv[0]);
141 if (argc - optind == 1)
142 filename = argv[optind];
144 pwmd_init();
146 if ((pwm = pwmd_connect(socketpath, &error)) == NULL) {
147 xfree(password);
148 errx(EXIT_FAILURE, "pwmd_connect(): %s", pwmd_strerror(error));
151 if (use_pinentry) {
152 error = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY, 1);
154 if (error) {
155 xfree(password);
156 show_error(error);
157 pwmd_close(pwm);
158 exit(EXIT_FAILURE);
161 if (pinentry_path) {
162 error = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_PATH, pinentry_path);
164 if (error) {
165 xfree(password);
166 show_error(error);
167 pwmd_close(pwm);
168 exit(EXIT_FAILURE);
172 error = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_TITLE, "Password Manager Daemon");
174 if (error) {
175 xfree(password);
176 show_error(error);
177 pwmd_close(pwm);
178 exit(EXIT_FAILURE);
181 snprintf(command, sizeof(command), "A password is required for the "
182 "file \"%s\". Please\nenter the password below.", filename);
184 error = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_DESC, command);
186 if (error) {
187 xfree(password);
188 show_error(error);
189 pwmd_close(pwm);
190 exit(EXIT_FAILURE);
193 else if (password) {
194 error = pwmd_setopt(pwm, PWMD_OPTION_PASSWORD, password);
196 if (error) {
197 xfree(password);
198 show_error(error);
199 pwmd_close(pwm);
200 exit(EXIT_FAILURE);
203 xfree(password);
206 if (filename) {
207 if (use_pinentry && timeout != -1) {
208 tcgetattr(STDOUT_FILENO, &term);
209 signal(SIGALRM, catchsig);
210 alarm(1);
213 error = pwmd_open(pwm, filename);
215 if (error) {
216 if (use_pinentry && timeout != -1 && elapsed >= timeout) {
217 error = GPG_ERR_TIMEOUT;
218 tcsetattr(STDOUT_FILENO, 0, &term);
219 printf("\r\n");
222 show_error(error);
223 pwmd_close(pwm);
224 exit(EXIT_FAILURE);
228 signal(SIGALRM, SIG_IGN);
229 elapsed = 0;
231 while ((p = fgets(command, sizeof(command), stdin)) != NULL) {
232 int len = strlen(p);
233 char *t;
235 if (p[len - 1] != '\n' && feof(stdin) != 1) {
236 if ((t = (char *)xrealloc(buf, (total + len + 1) * sizeof(char))) == NULL) {
237 if (buf)
238 xfree(buf);
240 memset(&command, 0, sizeof(command));
241 err(EXIT_FAILURE, "xrealloc()");
244 buf = t;
245 memcpy(&buf[total], p, len);
246 total += len;
247 buf[total] = 0;
248 continue;
250 else {
251 if (buf) {
252 if ((t = (char *)xrealloc(buf, (total + len + 1) * sizeof(char))) == NULL) {
253 if (buf)
254 xfree(buf);
256 memset(&command, 0, sizeof(command));
257 err(EXIT_FAILURE, "xrealloc()");
260 buf = t;
261 memcpy(&buf[total], p, len);
262 total += len;
263 buf[total] = 0;
267 p = buf ? buf : command;
269 if (p[strlen(p) - 1] == '\n')
270 p[strlen(p) - 1] = 0;
272 if (strcasecmp(p, "BYE") == 0)
273 break;
275 error = pwmd_command(pwm, &result, p);
277 if (error) {
278 if (buf) {
279 xfree(buf);
280 buf = NULL;
281 total = 0;
284 memset(&command, 0, sizeof(command));
285 show_error(error);
287 if (do_exit) {
288 pwmd_close(pwm);
289 exit(EXIT_FAILURE);
292 ret = EXIT_FAILURE;
294 else {
295 if (buf) {
296 xfree(buf);
297 buf = NULL;
298 total = 0;
302 memset(&command, 0, sizeof(command));
304 if (result) {
305 if (result[strlen(result) - 1] == '\n')
306 result[strlen(result) - 1] = 0;
308 fwrite(result, 1, strlen(result), stdout);
309 pwmd_free_result(result);
310 fputc('\n', stdout);
314 if (buf)
315 xfree(buf);
317 memset(&command, 0, sizeof(command));
319 if (save) {
320 save_again:
321 error = pwmd_save(pwm);
323 if (error) {
324 if (error == EPWMD_BADKEY || error == EPWMD_KEY)
325 goto save_again;
327 show_error(error);
328 pwmd_close(pwm);
329 exit(EXIT_FAILURE);
333 pwmd_close(pwm);
335 if (socketpath)
336 xfree(socketpath);
338 exit(ret);