Make the filename argument to pwmc optional. The command may be a
[libpwmd.git] / pwmc.c
blob1e62495780c48091b276104bf0423395d93d3e31
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 <libpwmd.h>
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
31 #include "mem.h"
33 static void usage(const char *pn)
35 fprintf(stderr,
36 "Reads PWMD protocol commands from standard input.\n\n"
37 "Usage: %s [-hv] [-E] [-s <socket>] [[-a [-P pinentry]] | [-p <password>]] [-S] [filename]\n"
38 " -E exit after a command failure\n"
39 " -s socket path\n"
40 " -p password\n"
41 " -a use pinentry(1) for password retrieval\n"
42 " -P path to the pinentry binary (/usr/bin/pinentry)\n"
43 " -S send the SAVE command after all others\n"
44 " -v version\n"
45 " -h this help text\n",
46 pn);
47 exit(EXIT_FAILURE);
50 static void show_error(gpg_error_t error)
52 fprintf(stderr, "ERR %i %s\n", gpg_err_code(error), pwmd_strerror(error));
55 int main(int argc, char *argv[])
57 int opt;
58 int use_pinentry = 0;
59 char *password = NULL;
60 char *filename = NULL;
61 char *socketpath = NULL;
62 char command[8196], *p;
63 int ret = EXIT_SUCCESS;
64 gpg_error_t error;
65 pwm_t *pwm;
66 char *result = NULL;
67 int save = 0;
68 char *buf = NULL;
69 int total = 0;
70 int do_exit = 0;
71 char *pinentry_path = NULL;
73 while ((opt = getopt(argc, argv, "EhvaP:p:s:S")) != EOF) {
74 switch (opt) {
75 case 'E':
76 do_exit = 1;
77 break;
78 case 'S':
79 save = 1;
80 break;
81 case 's':
82 socketpath = xstrdup(optarg);
83 break;
84 case 'p':
85 password = xstrdup(optarg);
86 break;
87 case 'a':
88 use_pinentry = 1;
89 break;
90 case 'P':
91 pinentry_path = xstrdup(optarg);
92 break;
93 case 'v':
94 printf("%s (pwmc)\n%s\n", PACKAGE_STRING, PACKAGE_BUGREPORT);
95 exit(EXIT_SUCCESS);
96 case 'h':
97 default:
98 usage(argv[0]);
102 if (use_pinentry && password)
103 usage(argv[0]);
105 if (argc - optind == 1)
106 filename = argv[optind];
108 pwmd_init();
110 if ((pwm = pwmd_connect(socketpath, &error)) == NULL) {
111 if (password)
112 xfree(password);
114 errx(EXIT_FAILURE, "pwmd_connect(): %s", pwmd_strerror(error));
117 if (use_pinentry) {
118 if (pwmd_setopt(pwm, &error, PWMD_OPTION_PINENTRY, 1) != PWMD_OK) {
119 show_error(error);
120 pwmd_close(pwm);
121 exit(EXIT_FAILURE);
124 if (pinentry_path) {
125 if (pwmd_setopt(pwm, &error, PWMD_OPTION_PINENTRY_PATH, pinentry_path) != PWMD_OK) {
126 show_error(error);
127 pwmd_close(pwm);
128 exit(EXIT_FAILURE);
132 if (pwmd_setopt(pwm, &error, PWMD_OPTION_PINENTRY_TITLE, "Password Manager Daemon") != PWMD_OK) {
133 show_error(error);
134 pwmd_close(pwm);
135 exit(EXIT_FAILURE);
138 snprintf(command, sizeof(command), "A password is required for the "
139 "file \"%s\". Please\nenter the password below.", filename);
141 if (pwmd_setopt(pwm, &error, PWMD_OPTION_PINENTRY_DESC, command) != PWMD_OK) {
142 show_error(error);
143 pwmd_close(pwm);
144 exit(EXIT_FAILURE);
147 else if (password) {
148 if (pwmd_setopt(pwm, &error, PWMD_OPTION_PASSWORD, password) != PWMD_OK) {
149 xfree(password);
150 show_error(error);
151 pwmd_close(pwm);
152 exit(EXIT_FAILURE);
155 xfree(password);
158 if (filename && pwmd_open(pwm, &error, filename) != PWMD_OK) {
159 show_error(error);
160 pwmd_close(pwm);
161 exit(EXIT_FAILURE);
164 while ((p = fgets(command, sizeof(command), stdin)) != NULL) {
165 int len = strlen(p);
166 char *t;
168 if (p[len - 1] != '\n' && feof(stdin) != 1) {
169 if ((t = (char *)xrealloc(buf, (total + len + 1) * sizeof(char))) == NULL) {
170 if (buf)
171 xfree(buf);
173 memset(&command, 0, sizeof(command));
174 err(EXIT_FAILURE, "xrealloc()");
177 buf = t;
178 memcpy(&buf[total], p, len);
179 total += len;
180 buf[total] = 0;
181 continue;
183 else {
184 if (buf) {
185 if ((t = (char *)xrealloc(buf, (total + len + 1) * sizeof(char))) == NULL) {
186 if (buf)
187 xfree(buf);
189 memset(&command, 0, sizeof(command));
190 err(EXIT_FAILURE, "xrealloc()");
193 buf = t;
194 memcpy(&buf[total], p, len);
195 total += len;
196 buf[total] = 0;
200 p = buf ? buf : command;
202 if (p[strlen(p) - 1] == '\n')
203 p[strlen(p) - 1] = 0;
205 if (strcasecmp(p, "BYE") == 0)
206 break;
208 if (pwmd_command(pwm, &result, &error, p) != PWMD_OK) {
209 if (buf) {
210 xfree(buf);
211 buf = NULL;
212 total = 0;
215 memset(&command, 0, sizeof(command));
216 show_error(error);
218 if (do_exit) {
219 pwmd_close(pwm);
220 exit(EXIT_FAILURE);
223 ret = EXIT_FAILURE;
225 else {
226 if (buf) {
227 xfree(buf);
228 buf = NULL;
229 total = 0;
233 memset(&command, 0, sizeof(command));
235 if (result) {
236 if (result[strlen(result) - 1] == '\n')
237 result[strlen(result) - 1] = 0;
239 fwrite(result, 1, strlen(result), stdout);
240 pwmd_free_result(result);
241 fputc('\n', stdout);
245 memset(&command, 0, sizeof(command));
247 if (save) {
248 save_again:
249 if (pwmd_save(pwm, &error) != PWMD_OK) {
250 if (error == EPWMD_BADKEY || error == EPWMD_KEY)
251 goto save_again;
253 show_error(error);
254 pwmd_close(pwm);
255 exit(EXIT_FAILURE);
259 pwmd_close(pwm);
261 if (socketpath)
262 xfree(socketpath);
264 exit(ret);