annotate pwm.c @ 18:1e39a251cbe9

Use libtecla for interactive input
author Guido Berhoerster <guido+pwm@berhoerster.name>
date Thu, 24 Aug 2017 13:10:56 +0200
parents a07665727c19
children 5c6155c8e9b6
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
1 /*
13
cf81eb0c2d5a Warn before quitting if there are unsaved changes
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 5
diff changeset
2 * Copyright (C) 2017 Guido Berhoerster <guido+pwm@berhoerster.name>
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
3 *
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
4 * Permission is hereby granted, free of charge, to any person obtaining
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
5 * a copy of this software and associated documentation files (the
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
6 * "Software"), to deal in the Software without restriction, including
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
7 * without limitation the rights to use, copy, modify, merge, publish,
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
8 * distribute, sublicense, and/or sell copies of the Software, and to
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
9 * permit persons to whom the Software is furnished to do so, subject to
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
10 * the following conditions:
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
11 *
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
12 * The above copyright notice and this permission notice shall be included
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
13 * in all copies or substantial portions of the Software.
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
14 *
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
22 */
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
23
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
24 #include "compat.h"
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
25
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
26 #ifdef HAVE_ERR_H
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
27 #include <err.h>
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
28 #endif /* HAVE_ERR_H */
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
29 #include <errno.h>
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
30 #include <fcntl.h>
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
31 #include <langinfo.h>
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
32 #include <locale.h>
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
33 #include <pwd.h>
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
34 #include <stdlib.h>
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
35 #include <stdio.h>
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
36 #include <string.h>
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
37 #include <pwd.h>
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
38 #include <sys/stat.h>
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
39 #include <time.h>
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
40 #include <unistd.h>
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
41
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
42 #include "pwm.h"
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
43 #include "cmd.h"
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
44 #include "pwfile.h"
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
45 #include "tok.h"
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
46 #include "util.h"
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
47
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
48 #ifndef PWM_HISTORY_ENTRIES_MAX
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
49 #define PWM_HISTORY_ENTRIES_MAX 1024
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
50 #endif /* !PWM_HISTORY_MAX */
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
51
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
52 #ifndef PWM_HISTORY_LINES_MAX
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
53 #define PWM_HISTORY_LINES_MAX 256
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
54 #endif /* !PWM_HISTORY_LINES_MAX */
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
55
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
56 #ifndef PWM_HISTORY_MAX
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
57 #define PWM_HISTORY_MAX (PWM_HISTORY_LINES_MAX * PWM_LINE_MAX)
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
58 #endif /* !PWM_HISTORY_MAX */
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
59
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
60 static void
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
61 usage(void)
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
62 {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
63 fprintf(stderr, "usage: %s [-P file] [filename]\n", getprogname());
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
64 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
65
16
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
66 void
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
67 pwm_err(struct pwm_ctx *ctx, char *fmt, ...)
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
68 {
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
69 va_list args;
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
70
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
71 free(ctx->errmsg);
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
72
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
73 if (fmt != NULL) {
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
74 va_start(args, fmt);
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
75 xvasprintf(&ctx->errmsg, fmt, args);
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
76 va_end(args);
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
77
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
78 fprintf(stderr, "%s\n", ctx->errmsg);
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
79 } else {
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
80 ctx->errmsg = NULL;
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
81 }
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
82 }
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
83
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
84 static int
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
85 complete_nothing(WordCompletion *cpl, void *data, const char *line,
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
86 int word_end)
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
87 {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
88 return (0);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
89 }
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
90
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
91 static int
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
92 run_input_loop(struct pwm_ctx *ctx, int is_interactive)
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
93 {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
94 int retval = -1;
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
95 char prompt[8 + 2 + 1];
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
96 GetLine *gl = NULL;
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
97 char buf[PWM_LINE_MAX];
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
98 char *line = buf;
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
99 int c;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
100 int argc = 0;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
101 char **argv = NULL;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
102 struct cmd *cmd;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
103 int i;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
104
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
105 snprintf(prompt, sizeof (prompt), "%.*s> ", 8, getprogname());
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
106
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
107 /* initialize libtecla */
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
108 gl = new_GetLine(PWM_LINE_MAX, PWM_HISTORY_MAX);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
109 if (gl == NULL) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
110 err(1, "new_GetLine");
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
111 }
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
112 gl_limit_history(gl, PWM_HISTORY_LINES_MAX);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
113 /* disable default filename completion */
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
114 gl_customize_completion(gl, NULL, complete_nothing);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
115
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
116 for (;;) {
13
cf81eb0c2d5a Warn before quitting if there are unsaved changes
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 5
diff changeset
117 cmd = NULL;
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
118 line = gl_get_line(gl, prompt, NULL, -1);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
119 if (line == NULL) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
120 switch (gl_return_status(gl)) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
121 case GLR_EOF:
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
122 break;
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
123 case GLR_ERROR:
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
124 warnx("gl_get_line: %s",
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
125 gl_error_message(gl, NULL, 0));
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
126 }
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
127 break;
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
128 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
129
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
130 /* tokenize line */
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
131 switch (tok_tokenize(line, &argc, &argv)) {
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
132 case TOK_ERR_SYSTEM_ERROR:
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
133 err(1, "tok_tokenize");
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
134 case TOK_ERR_UNTERMINATED_QUOTE:
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
135 fprintf(stderr, "unterminated quote\n");
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
136 if (!is_interactive) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
137 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
138 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
139 goto next;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
140 case TOK_ERR_TRAILING_BACKSLASH:
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
141 fprintf(stderr, "trailing backslash\n");
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
142 if (!is_interactive) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
143 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
144 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
145 goto next;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
146 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
147
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
148 if (argc == 0) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
149 /* empty line */
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
150 goto next;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
151 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
152
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
153 /* find and execute the command */
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
154 cmd = cmd_match(argv[0]);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
155 if (cmd == NULL) {
16
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
156 pwm_err(ctx, "unknown command: %s", argv[0]);
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
157 if (is_interactive) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
158 goto next;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
159 } else {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
160 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
161 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
162 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
163 switch (cmd->cmd_func(ctx, argc, argv)) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
164 case CMD_OK:
16
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
165 pwm_err(ctx, NULL); /* clear error */
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
166 break;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
167 case CMD_USAGE:
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
168 fprintf(stderr, "usage: %s\n", cmd->usage);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
169 case CMD_ERR: /* FALLTHROUGH */
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
170 if (!is_interactive) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
171 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
172 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
173 break;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
174 case CMD_QUIT:
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
175 goto quit;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
176 }
16
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
177 ctx->prev_cmd = cmd->full_cmd;
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
178
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
179 next:
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
180 for (i = 0; i < argc; i++) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
181 free(argv[i]);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
182 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
183 free(argv);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
184 argc = 0;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
185 argv = NULL;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
186 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
187
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
188 quit:
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
189 retval = 0;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
190
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
191 out:
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
192 for (i = 0; i < argc; i++) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
193 free(argv[i]);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
194 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
195 free(argv);
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
196 del_GetLine(gl);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
197
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
198 return (retval);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
199 }
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
200
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
201 int
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
202 pwm_read_password(struct pwm_ctx *ctx, int is_new_password)
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
203 {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
204 int retval = -1;
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
205 GetLine *gl = NULL;
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
206 char *line;
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
207 size_t len;
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
208 char password_buf[sizeof (ctx->password)] = { '\0' };
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
209
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
210 /* initialize libtecla */
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
211 gl = new_GetLine(sizeof (password_buf) - 1, 0);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
212 if (gl == NULL) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
213 err(1, "new_GetLine");
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
214 }
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
215 /* disable default filename completion */
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
216 gl_customize_completion(gl, NULL, complete_nothing);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
217 gl_echo_mode(gl, 0);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
218
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
219 line = gl_get_line(gl, is_new_password ? "New password: " :
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
220 "Password: ", NULL, -1);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
221 putchar('\n');
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
222 if (line == NULL) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
223 if (gl_return_status(gl) == GLR_ERROR) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
224 errx(1, "gl_get_line: %s", gl_error_message(gl, NULL,
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
225 0));
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
226 }
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
227 goto out;
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
228 }
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
229 len = strlen(line);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
230 if ((len > 0) && (line[len - 1] == '\n')) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
231 line[--len] = '\0';
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
232 }
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
233 if (len == 0) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
234 fprintf(stderr, "password must not be empty\n");
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
235 goto out;
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
236 }
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
237 strcpy(password_buf, line);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
238
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
239 /* confirm the entered password entered */
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
240 if (is_new_password) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
241 line = gl_get_line(gl, "Confirm password: ", NULL, -1);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
242 putchar('\n');
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
243 if (line == NULL) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
244 if (gl_return_status(gl) == GLR_ERROR) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
245 errx(1, "gl_get_line: %s", gl_error_message(gl,
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
246 NULL, 0));
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
247 }
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
248 goto out;
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
249 }
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
250 len = strlen(line);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
251 if ((len > 0) && (line[len - 1] == '\n')) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
252 line[--len] = '\0';
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
253 }
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
254 if (strcmp(password_buf, line) != 0) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
255 fprintf(stderr, "passwords do not match\n");
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
256 goto out;
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
257 }
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
258 }
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
259
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
260 strcpy(ctx->password, password_buf);
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
261 retval = 0;
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
262
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
263 out:
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
264 del_GetLine(gl);
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
265
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
266 return (retval);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
267 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
268
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
269 static int
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
270 read_password_from_file(const char *filename, char *password,
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
271 size_t password_size)
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
272 {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
273 int retval = -1;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
274 char *buf = NULL;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
275 FILE *fp = NULL;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
276 size_t password_len = 0;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
277
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
278 buf = xmalloc(password_size);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
279
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
280 fp = fopen(filename, "r");
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
281 if (fp == NULL) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
282 warn("failed to open master password file \"%s\"", filename);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
283 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
284 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
285 if (fgets(buf, password_size, fp) == NULL) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
286 /* read error or empty file */
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
287 if (ferror(fp)) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
288 /* read error */
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
289 warn("failed to read master password from \"%s\"",
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
290 filename);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
291 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
292 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
293 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
294 password_len = strlen(buf);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
295 if (buf[password_len - 1] == '\n') {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
296 /* strip trailing newline */
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
297 password_len--;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
298 if (password_len == 0) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
299 /* first line is empty */
5
0b1bce8db371 Prevent misleading double error message
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 0
diff changeset
300 fprintf(stderr, "malformed password file\n");
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
301 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
302 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
303 } else if (!feof(fp)) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
304 /* the first line was truncated, password is too long */
5
0b1bce8db371 Prevent misleading double error message
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 0
diff changeset
305 fprintf(stderr, "malformed password file\n");
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
306 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
307 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
308 memcpy(password, buf, password_size);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
309 retval = 0;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
310
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
311 out:
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
312 password[password_len] = '\0';
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
313
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
314 if (fp != NULL) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
315 fclose(fp);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
316 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
317 free(buf);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
318
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
319 return (retval);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
320 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
321
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
322 int
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
323 main(int argc, char *argv[])
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
324 {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
325 int status = EXIT_FAILURE;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
326 char *locale;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
327 int is_interactive;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
328 int errflag = 0;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
329 int c;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
330 const char *master_password_filename = NULL;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
331 struct pwm_ctx ctx = { 0 };
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
332 struct passwd *passwd;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
333 char *pwm_dirname = NULL;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
334 FILE *fp = NULL;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
335
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
336 setprogname(argv[0]);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
337
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
338 /* set up locale and check for UTF-8 codeset */
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
339 locale = setlocale(LC_ALL, "");
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
340 if (locale == NULL) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
341 errx(1, "invalid locale");
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
342 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
343 if ((strcasecmp(nl_langinfo(CODESET), "UTF-8") != 0) &&
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
344 (strcasecmp(nl_langinfo(CODESET), "UTF8") != 0)) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
345 fprintf(stderr, "pwm requires a locale with UTF-8 character "
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
346 "encoding.\n");
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
347 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
348 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
349
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
350 /* timestamps are processed as UTC */
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
351 if (setenv("TZ", "", 1) != 0) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
352 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
353 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
354 tzset();
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
355
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
356 /* initialize libpws */
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
357 if (pws_init() != 0) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
358 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
359 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
360
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
361 is_interactive = isatty(STDIN_FILENO);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
362
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
363 while (!errflag && (c = getopt(argc, argv, "P:h")) != -1) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
364 switch (c) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
365 case 'P':
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
366 master_password_filename = optarg;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
367 break;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
368 case 'h':
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
369 usage();
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
370 status = EXIT_SUCCESS;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
371 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
372 default:
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
373 errflag = 1;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
374 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
375 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
376 if (errflag || (optind + 1 < argc)) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
377 usage();
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
378 status = EXIT_USAGE;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
379 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
380 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
381
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
382 if (optind == argc) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
383 passwd = getpwuid(getuid());
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
384 if (passwd == NULL) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
385 err(1, "getpwuid");
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
386 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
387 xasprintf(&pwm_dirname, "%s/.pwm", passwd->pw_dir);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
388 xasprintf(&ctx.filename, "%s/pwm.psafe3", pwm_dirname);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
389
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
390 /* create ~/.pwm directory if necessary */
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
391 if ((mkdir(pwm_dirname, S_IRWXU) != 0) && (errno != EEXIST)) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
392 warn("failed to create directory \"%s\"", pwm_dirname);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
393 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
394 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
395 } else if (optind + 1 == argc) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
396 ctx.filename = xstrdup(argv[optind++]);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
397 } else {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
398 usage();
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
399 status = EXIT_USAGE;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
400 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
401 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
402
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
403 if (is_interactive) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
404 printf("pwm version %s\n", VERSION);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
405 } else if (master_password_filename == NULL) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
406 fprintf(stderr, "master password file must be specified when "
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
407 "running non-interactively\n");
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
408 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
409 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
410
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
411 pwfile_init(&ctx);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
412
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
413 fp = fopen(ctx.filename, "r");
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
414 if ((fp == NULL) && (errno != ENOENT)) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
415 warn("failed to open password database");
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
416 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
417 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
418 /* obtain master password */
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
419 if (master_password_filename != NULL) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
420 if (read_password_from_file(master_password_filename,
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
421 ctx.password, sizeof (ctx.password)) != 0) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
422 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
423 }
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
424 } else if (pwm_read_password(&ctx, (fp == NULL)) != 0) {
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 16
diff changeset
425 goto out;
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
426 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
427 if (fp != NULL) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
428 if (pwfile_read_file(&ctx, fp) != 0) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
429 goto out;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
430 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
431 fclose(fp);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
432 fp = NULL;
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
433 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
434
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
435 /* run main input loop */
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
436 status = (run_input_loop(&ctx, is_interactive) != 0);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
437
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
438 out:
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
439 pwfile_destroy(&ctx);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
440 if (fp != NULL) {
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
441 fclose(fp);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
442 }
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
443 free(ctx.filename);
16
a07665727c19 Add status command
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 13
diff changeset
444 free(ctx.errmsg);
0
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
445 free(pwm_dirname);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
446
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
447 exit(status);
a7e41e1a79c8 Initial revision
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
448 }