]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/ask-password/ask-password.c
Merge pull request #11827 from keszybz/pkgconfig-variables
[thirdparty/systemd.git] / src / ask-password / ask-password.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
490aed58 2
490aed58 3#include <errno.h>
490aed58 4#include <getopt.h>
0e098b15 5#include <stddef.h>
00843602 6#include <unistd.h>
490aed58 7
00843602
LP
8#include "ask-password-api.h"
9#include "def.h"
490aed58
LP
10#include "log.h"
11#include "macro.h"
c7d7adf5 12#include "main-func.h"
294bf0c3 13#include "pretty-print.h"
21bc923a 14#include "strv.h"
490aed58
LP
15
16static const char *arg_icon = NULL;
9fa1de96 17static const char *arg_id = NULL;
e287086b
LP
18static const char *arg_keyname = NULL;
19static char *arg_message = NULL;
7f434cf4 20static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
21bc923a 21static bool arg_multiple = false;
a5a4e365 22static bool arg_no_output = false;
e287086b 23static AskPasswordFlags arg_flags = ASK_PASSWORD_PUSH_CACHE;
490aed58 24
c7d7adf5
YW
25STATIC_DESTRUCTOR_REGISTER(arg_message, freep);
26
37ec0fdd
LP
27static int help(void) {
28 _cleanup_free_ char *link = NULL;
29 int r;
30
31 r = terminal_urlify_man("systemd-ask-password", "1", &link);
32 if (r < 0)
33 return log_oom();
34
490aed58 35 printf("%s [OPTIONS...] MESSAGE\n\n"
ad6ab0af 36 "Query the user for a system passphrase, via the TTY or an UI agent.\n\n"
e287086b
LP
37 " -h --help Show this help\n"
38 " --icon=NAME Icon name\n"
39 " --id=ID Query identifier (e.g. \"cryptsetup:/dev/sda5\")\n"
40 " --keyname=NAME Kernel key name for caching passwords (e.g. \"cryptsetup\")\n"
41 " --timeout=SEC Timeout in seconds\n"
42 " --echo Do not mask input (useful for usernames)\n"
43 " --no-tty Ask question via agent even on TTY\n"
44 " --accept-cached Accept cached passwords\n"
45 " --multiple List multiple passwords if available\n"
a5a4e365 46 " --no-output Do not print password to standard output\n"
37ec0fdd
LP
47 "\nSee the %s for details.\n"
48 , program_invocation_short_name
49 , link
50 );
51
52 return 0;
490aed58
LP
53}
54
55static int parse_argv(int argc, char *argv[]) {
56
57 enum {
58 ARG_ICON = 0x100,
1b39d4b9 59 ARG_TIMEOUT,
64845bdc 60 ARG_ECHO,
21bc923a
LP
61 ARG_NO_TTY,
62 ARG_ACCEPT_CACHED,
9fa1de96 63 ARG_MULTIPLE,
e287086b
LP
64 ARG_ID,
65 ARG_KEYNAME,
a5a4e365 66 ARG_NO_OUTPUT,
37ec0fdd 67 ARG_VERSION,
490aed58
LP
68 };
69
70 static const struct option options[] = {
21bc923a 71 { "help", no_argument, NULL, 'h' },
37ec0fdd 72 { "version", no_argument, NULL, ARG_VERSION },
21bc923a
LP
73 { "icon", required_argument, NULL, ARG_ICON },
74 { "timeout", required_argument, NULL, ARG_TIMEOUT },
64845bdc 75 { "echo", no_argument, NULL, ARG_ECHO },
21bc923a
LP
76 { "no-tty", no_argument, NULL, ARG_NO_TTY },
77 { "accept-cached", no_argument, NULL, ARG_ACCEPT_CACHED },
78 { "multiple", no_argument, NULL, ARG_MULTIPLE },
9fa1de96 79 { "id", required_argument, NULL, ARG_ID },
e287086b 80 { "keyname", required_argument, NULL, ARG_KEYNAME },
a5a4e365 81 { "no-output", no_argument, NULL, ARG_NO_OUTPUT },
eb9da376 82 {}
490aed58
LP
83 };
84
85 int c;
86
87 assert(argc >= 0);
88 assert(argv);
89
601185b4 90 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
490aed58
LP
91
92 switch (c) {
93
94 case 'h':
37ec0fdd
LP
95 return help();
96
97 case ARG_VERSION:
98 return version();
490aed58
LP
99
100 case ARG_ICON:
101 arg_icon = optarg;
102 break;
103
104 case ARG_TIMEOUT:
baaa35ad
ZJS
105 if (parse_sec(optarg, &arg_timeout) < 0)
106 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
107 "Failed to parse --timeout parameter %s",
108 optarg);
490aed58
LP
109 break;
110
64845bdc 111 case ARG_ECHO:
e287086b 112 arg_flags |= ASK_PASSWORD_ECHO;
64845bdc
DS
113 break;
114
1b39d4b9 115 case ARG_NO_TTY:
e287086b 116 arg_flags |= ASK_PASSWORD_NO_TTY;
1b39d4b9
LP
117 break;
118
21bc923a 119 case ARG_ACCEPT_CACHED:
e287086b 120 arg_flags |= ASK_PASSWORD_ACCEPT_CACHED;
21bc923a
LP
121 break;
122
123 case ARG_MULTIPLE:
124 arg_multiple = true;
125 break;
126
9fa1de96
DH
127 case ARG_ID:
128 arg_id = optarg;
129 break;
130
e287086b
LP
131 case ARG_KEYNAME:
132 arg_keyname = optarg;
133 break;
134
a5a4e365
CH
135 case ARG_NO_OUTPUT:
136 arg_no_output = true;
137 break;
138
490aed58
LP
139 case '?':
140 return -EINVAL;
141
142 default:
eb9da376 143 assert_not_reached("Unhandled option");
490aed58 144 }
490aed58 145
e287086b
LP
146 if (argc > optind) {
147 arg_message = strv_join(argv + optind, " ");
148 if (!arg_message)
149 return log_oom();
490aed58
LP
150 }
151
1b39d4b9 152 return 1;
490aed58
LP
153}
154
c7d7adf5 155static int run(int argc, char *argv[]) {
ab84f5b9 156 _cleanup_strv_free_erase_ char **l = NULL;
7dcda352 157 usec_t timeout;
e287086b
LP
158 char **p;
159 int r;
1b39d4b9
LP
160
161 log_parse_environment();
162 log_open();
163
601185b4
ZJS
164 r = parse_argv(argc, argv);
165 if (r <= 0)
c7d7adf5 166 return r;
1b39d4b9 167
7dcda352
LP
168 if (arg_timeout > 0)
169 timeout = now(CLOCK_MONOTONIC) + arg_timeout;
170 else
171 timeout = 0;
172
e287086b 173 r = ask_password_auto(arg_message, arg_icon, arg_id, arg_keyname, timeout, arg_flags, &l);
c7d7adf5
YW
174 if (r < 0)
175 return log_error_errno(r, "Failed to query password: %m");
21bc923a 176
e287086b 177 STRV_FOREACH(p, l) {
a5a4e365
CH
178 if (!arg_no_output)
179 puts(*p);
ec863ba6 180
e287086b
LP
181 if (!arg_multiple)
182 break;
7f4e0805 183 }
1b39d4b9 184
c7d7adf5 185 return 0;
1b39d4b9 186}
c7d7adf5
YW
187
188DEFINE_MAIN_FUNCTION(run);