chiark / gitweb /
Fix daft error in the comment for @gfshare_get@.
[catacomb] / pixie-common.c
1 /* -*-c-*-
2  *
3  * $Id: pixie-common.c,v 1.1 1999/12/22 15:58:41 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 /*----- Revision history --------------------------------------------------* 
31  *
32  * $Log: pixie-common.c,v $
33  * Revision 1.1  1999/12/22 15:58:41  mdw
34  * Passphrase pixie support.
35  *
36  */
37
38 /*----- Header files ------------------------------------------------------*/
39
40 #include <errno.h>
41 #include <stddef.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45
46 #include <sys/types.h>
47 #include <unistd.h>
48 #include <fcntl.h>
49 #include <termios.h>
50 #include <pwd.h>
51
52 #include <sys/socket.h>
53 #include <sys/un.h>
54
55 #include <mLib/alloc.h>
56 #include <mLib/dstr.h>
57
58 #include "pixie.h"
59
60 /*----- Main code ---------------------------------------------------------*/
61
62 /* --- @pixie_address@ --- *
63  *
64  * Arguments:   @const char *sock@ = pointer to socket name
65  *              @size_t *psz@ = where to write the address size
66  *
67  * Returns:     Pointer to filled-in Unix-domain socket address.
68  *
69  * Use:         Returns a Unix-domain socket address to use to find the
70  *              passphrase pixie.
71  */
72
73 struct sockaddr_un *pixie_address(const char *sock, size_t *psz)
74 {
75   dstr d = DSTR_INIT;
76
77   /* --- Get the default socket path if none specified --- */
78
79   if (!sock)
80     sock = getenv("CATACOMB_PIXIE_SOCKET");
81   if (!sock)
82     sock = "%h/.catacomb/pixie";
83
84   /* --- Substitute interesting sequences in the path --- */
85
86   {
87     const char *q, *qq;
88
89     q = sock;
90     for (;;) {
91       qq = strchr(q, '%');
92       if (!qq || !qq[1]) {
93         DPUTS(&d, q);
94         break;
95       }
96       DPUTM(&d, q, qq - q);
97       q = qq + 1;
98       switch (*q) {
99         case 'u':
100           qq = getenv("USER");
101           if (!qq)
102             qq = getenv("LOGNAME");
103           if (!qq) {
104             struct passwd *pw = getpwuid(getuid());
105             if (pw)
106               qq = pw->pw_name;
107             else
108               qq = "<unknown>";
109           }
110           DPUTS(&d, qq);
111           break;
112         case 'h':
113           qq = getenv("HOME");
114           if (!qq) {
115             struct passwd *pw = getpwuid(getuid());
116             if (pw)
117               qq = pw->pw_dir;
118             else
119               qq = "<unknown>";
120           }
121           DPUTS(&d, qq);
122           break;
123         default:
124           DPUTC(&d, '%');
125           DPUTC(&d, *q);
126           break;
127       }
128       q++;
129     }
130     DPUTZ(&d);
131   }
132
133   /* --- Allocate and initialize the socket address --- */
134
135   {
136     struct sockaddr_un *sun;
137     size_t bsz = offsetof(struct sockaddr_un, sun_path);
138     *psz = bsz + d.len + 1;
139     sun = xmalloc(bsz + d.len + 1);
140     memset(sun, 0, bsz);
141     sun->sun_family = AF_UNIX;
142     memcpy(sun->sun_path, d.buf, d.len + 1);
143     dstr_destroy(&d);
144     return (sun);
145   }
146 }
147
148 /* --- @pixie_fdline@ --- *
149  *
150  * Arguments:   @int fd@ = file descriptor to read from
151  *              @char *buf@ = pointer to buffer
152  *              @size_t sz@ = size of buffer
153  *
154  * Returns:     ---
155  *
156  * Use:         Reads a line from a file descriptor.  The read is done one
157  *              character at a time.  If the entire line won't fit, the end
158  *              is truncated.  The line is null terminated.
159  */
160
161 void pixie_fdline(int fd, char *buf, size_t sz)
162 {
163   char *p = buf;
164   char *q = p + sz - 1;
165
166   for (;;) {
167     char c;
168     if (read(fd, &c, 1) < 1)
169       break;
170     if (c == '\n')
171       break;
172     if (p < q)
173       *p++ = c;
174   }
175   *p = 0;
176 }
177
178 /* --- @pixie_getpass@ --- *
179  *
180  * Arguments:   @const char *prompt@ = pointer to prompt string
181  *              @char *buf@ = pointer to buffer
182  *              @size_t sz@ = size of buffer
183  *
184  * Returns:     Zero if it worked OK, nonzero otherwise.
185  *
186  * Use:         Reads a passphrase from the terminal or some other requested
187  *              source.
188  */
189
190 int pixie_getpass(const char *prompt, char *buf, size_t sz)
191 {
192   const char *pfd = getenv("CATACOMB_PASSPHRASE_FD");
193   int fd = 0;
194
195   /* --- See whether a terminal is what's wanted --- */
196
197   if (pfd) {
198     fd = atoi(pfd);
199     pixie_fdline(fd, buf, sz);
200   } else {
201     struct termios ta;
202     struct termios ota;
203     char nl = '\n';
204
205     if ((fd = open("/dev/tty", O_RDWR)) < 0)
206       goto fail_0;
207     if (tcgetattr(fd, &ta) < 0)
208       goto fail_1;
209     ota = ta;
210     ta.c_lflag &= ~(ECHO | ISIG);
211     if (tcsetattr(fd, TCSAFLUSH, &ta))
212       goto fail_1;
213     write(fd, prompt, strlen(prompt));
214     pixie_fdline(fd, buf, sz);
215     tcsetattr(fd, TCSAFLUSH, &ota);
216     write(fd, &nl, 1);
217     close(fd);
218   }
219   return (0);
220
221   /* --- Tidy up if things went wrong --- */
222
223 fail_1:
224   close(fd);
225 fail_0:
226   return (-1);
227 }
228
229
230 /*----- That's all, folks -------------------------------------------------*/
231