chiark / gitweb /
build-sys: add a makefile target to run all tests through valgrind
[elogind.git] / src / ask-password / ask-password.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/socket.h>
23 #include <sys/poll.h>
24 #include <sys/types.h>
25 #include <assert.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <sys/un.h>
31 #include <sys/stat.h>
32 #include <sys/signalfd.h>
33 #include <getopt.h>
34 #include <termios.h>
35 #include <limits.h>
36 #include <stddef.h>
37
38 #include "log.h"
39 #include "macro.h"
40 #include "util.h"
41 #include "strv.h"
42 #include "ask-password-api.h"
43 #include "def.h"
44
45 static const char *arg_icon = NULL;
46 static const char *arg_message = NULL;
47 static bool arg_use_tty = true;
48 static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
49 static bool arg_accept_cached = false;
50 static bool arg_multiple = false;
51
52 static int help(void) {
53
54         printf("%s [OPTIONS...] MESSAGE\n\n"
55                "Query the user for a system passphrase, via the TTY or an UI agent.\n\n"
56                "  -h --help          Show this help\n"
57                "     --icon=NAME     Icon name\n"
58                "     --timeout=SEC   Timeout in sec\n"
59                "     --no-tty        Ask question via agent even on TTY\n"
60                "     --accept-cached Accept cached passwords\n"
61                "     --multiple      List multiple passwords if available\n",
62                program_invocation_short_name);
63
64         return 0;
65 }
66
67 static int parse_argv(int argc, char *argv[]) {
68
69         enum {
70                 ARG_ICON = 0x100,
71                 ARG_TIMEOUT,
72                 ARG_NO_TTY,
73                 ARG_ACCEPT_CACHED,
74                 ARG_MULTIPLE
75         };
76
77         static const struct option options[] = {
78                 { "help",          no_argument,       NULL, 'h'               },
79                 { "icon",          required_argument, NULL, ARG_ICON          },
80                 { "timeout",       required_argument, NULL, ARG_TIMEOUT       },
81                 { "no-tty",        no_argument,       NULL, ARG_NO_TTY        },
82                 { "accept-cached", no_argument,       NULL, ARG_ACCEPT_CACHED },
83                 { "multiple",      no_argument,       NULL, ARG_MULTIPLE      },
84                 { NULL,            0,                 NULL, 0                 }
85         };
86
87         int c;
88
89         assert(argc >= 0);
90         assert(argv);
91
92         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
93
94                 switch (c) {
95
96                 case 'h':
97                         help();
98                         return 0;
99
100                 case ARG_ICON:
101                         arg_icon = optarg;
102                         break;
103
104                 case ARG_TIMEOUT:
105                         if (parse_sec(optarg, &arg_timeout) < 0) {
106                                 log_error("Failed to parse --timeout parameter %s", optarg);
107                                 return -EINVAL;
108                         }
109                         break;
110
111                 case ARG_NO_TTY:
112                         arg_use_tty = false;
113                         break;
114
115                 case ARG_ACCEPT_CACHED:
116                         arg_accept_cached = true;
117                         break;
118
119                 case ARG_MULTIPLE:
120                         arg_multiple = true;
121                         break;
122
123                 case '?':
124                         return -EINVAL;
125
126                 default:
127                         log_error("Unknown option code %c", c);
128                         return -EINVAL;
129                 }
130         }
131
132         if (optind != argc-1) {
133                 help();
134                 return -EINVAL;
135         }
136
137         arg_message = argv[optind];
138         return 1;
139 }
140
141 int main(int argc, char *argv[]) {
142         int r;
143         usec_t timeout;
144
145         log_parse_environment();
146         log_open();
147
148         if ((r = parse_argv(argc, argv)) <= 0)
149                 goto finish;
150
151         if (arg_timeout > 0)
152                 timeout = now(CLOCK_MONOTONIC) + arg_timeout;
153         else
154                 timeout = 0;
155
156         if (arg_use_tty && isatty(STDIN_FILENO)) {
157                 char *password = NULL;
158
159                 if ((r = ask_password_tty(arg_message, timeout, NULL, &password)) >= 0) {
160                         puts(password);
161                         free(password);
162                 }
163
164         } else {
165                 char **l;
166
167                 if ((r = ask_password_agent(arg_message, arg_icon, timeout, arg_accept_cached, &l)) >= 0) {
168                         char **p;
169
170                         STRV_FOREACH(p, l) {
171                                 puts(*p);
172
173                                 if (!arg_multiple)
174                                         break;
175                         }
176
177                         strv_free(l);
178                 }
179         }
180
181 finish:
182
183         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
184 }