Too obviously cloned. Ooops.
[u/mdw/catacomb] / pixie-common.c
1 /* -*-c-*-
2 *
3 * $Id: pixie-common.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
4 *
5 * Common code for Pixie client and server (Unix-specific)
6 *
7 * (c) 1999 Straylight/Edgeware
8 */
9
10 /*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of Catacomb.
13 *
14 * Catacomb is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * Catacomb is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU Library General Public
25 * License along with Catacomb; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 * MA 02111-1307, USA.
28 */
29
30 /*----- Header files ------------------------------------------------------*/
31
32 #include <errno.h>
33 #include <stddef.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include <sys/types.h>
39 #include <unistd.h>
40 #include <fcntl.h>
41 #include <termios.h>
42 #include <pwd.h>
43
44 #include <sys/socket.h>
45 #include <sys/un.h>
46
47 #include <mLib/alloc.h>
48 #include <mLib/dstr.h>
49
50 #include "pixie.h"
51
52 /*----- Main code ---------------------------------------------------------*/
53
54 /* --- @pixie_address@ --- *
55 *
56 * Arguments: @const char *sock@ = pointer to socket name
57 * @size_t *psz@ = where to write the address size
58 *
59 * Returns: Pointer to filled-in Unix-domain socket address.
60 *
61 * Use: Returns a Unix-domain socket address to use to find the
62 * passphrase pixie.
63 */
64
65 struct sockaddr_un *pixie_address(const char *sock, size_t *psz)
66 {
67 dstr d = DSTR_INIT;
68
69 /* --- Get the default socket path if none specified --- */
70
71 if (!sock)
72 sock = getenv("CATACOMB_PIXIE_SOCKET");
73 if (!sock)
74 sock = "%h/.catacomb/pixie";
75
76 /* --- Substitute interesting sequences in the path --- */
77
78 {
79 const char *q, *qq;
80
81 q = sock;
82 for (;;) {
83 qq = strchr(q, '%');
84 if (!qq || !qq[1]) {
85 DPUTS(&d, q);
86 break;
87 }
88 DPUTM(&d, q, qq - q);
89 q = qq + 1;
90 switch (*q) {
91 case 'u':
92 qq = getenv("USER");
93 if (!qq)
94 qq = getenv("LOGNAME");
95 if (!qq) {
96 struct passwd *pw = getpwuid(getuid());
97 if (pw)
98 qq = pw->pw_name;
99 else
100 qq = "<unknown>";
101 }
102 DPUTS(&d, qq);
103 break;
104 case 'h':
105 qq = getenv("HOME");
106 if (!qq) {
107 struct passwd *pw = getpwuid(getuid());
108 if (pw)
109 qq = pw->pw_dir;
110 else
111 qq = "<unknown>";
112 }
113 DPUTS(&d, qq);
114 break;
115 default:
116 DPUTC(&d, '%');
117 DPUTC(&d, *q);
118 break;
119 }
120 q++;
121 }
122 DPUTZ(&d);
123 }
124
125 /* --- Allocate and initialize the socket address --- */
126
127 {
128 struct sockaddr_un *sun;
129 size_t bsz = offsetof(struct sockaddr_un, sun_path);
130 *psz = bsz + d.len + 1;
131 sun = xmalloc(bsz + d.len + 1);
132 memset(sun, 0, bsz);
133 sun->sun_family = AF_UNIX;
134 memcpy(sun->sun_path, d.buf, d.len + 1);
135 dstr_destroy(&d);
136 return (sun);
137 }
138 }
139
140 /* --- @pixie_fdline@ --- *
141 *
142 * Arguments: @int fd@ = file descriptor to read from
143 * @char *buf@ = pointer to buffer
144 * @size_t sz@ = size of buffer
145 *
146 * Returns: ---
147 *
148 * Use: Reads a line from a file descriptor. The read is done one
149 * character at a time. If the entire line won't fit, the end
150 * is truncated. The line is null terminated.
151 */
152
153 void pixie_fdline(int fd, char *buf, size_t sz)
154 {
155 char *p = buf;
156 char *q = p + sz - 1;
157
158 for (;;) {
159 char c;
160 if (read(fd, &c, 1) < 1)
161 break;
162 if (c == '\n')
163 break;
164 if (p < q)
165 *p++ = c;
166 }
167 *p = 0;
168 }
169
170 /* --- @pixie_getpass@ --- *
171 *
172 * Arguments: @const char *prompt@ = pointer to prompt string
173 * @char *buf@ = pointer to buffer
174 * @size_t sz@ = size of buffer
175 *
176 * Returns: Zero if it worked OK, nonzero otherwise.
177 *
178 * Use: Reads a passphrase from the terminal or some other requested
179 * source.
180 */
181
182 int pixie_getpass(const char *prompt, char *buf, size_t sz)
183 {
184 const char *pfd = getenv("CATACOMB_PASSPHRASE_FD");
185 int fd = 0;
186
187 /* --- See whether a terminal is what's wanted --- */
188
189 if (pfd) {
190 fd = atoi(pfd);
191 pixie_fdline(fd, buf, sz);
192 } else {
193 struct termios ta;
194 struct termios ota;
195 char nl = '\n';
196
197 if ((fd = open("/dev/tty", O_RDWR)) < 0)
198 goto fail_0;
199 if (tcgetattr(fd, &ta) < 0)
200 goto fail_1;
201 ota = ta;
202 ta.c_lflag &= ~(ECHO | ISIG);
203 if (tcsetattr(fd, TCSAFLUSH, &ta))
204 goto fail_1;
205 write(fd, prompt, strlen(prompt));
206 pixie_fdline(fd, buf, sz);
207 tcsetattr(fd, TCSAFLUSH, &ota);
208 write(fd, &nl, 1);
209 close(fd);
210 }
211 return (0);
212
213 /* --- Tidy up if things went wrong --- */
214
215 fail_1:
216 close(fd);
217 fail_0:
218 return (-1);
219 }
220
221
222 /*----- That's all, folks -------------------------------------------------*/
223