Merge commit '00f1a4f432b3d8aad1aa270e91c44c57f03ef407'
[unleashed.git] / usr / src / lib / libc / port / inet / ruserpass.c
blobcfd46609c94fa5054656d8c27b075c4f4e864869
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
40 #include <stdio.h>
41 #include <ctype.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <errno.h>
45 #include <unistd.h>
46 #include <strings.h>
47 #include <stdlib.h>
48 #include <libintl.h>
49 #include <limits.h>
51 #ifdef SYSV
52 #define index strchr
53 #endif /* SYSV */
55 static void rnetrc(const char *host, char **aname, char **apass);
56 static int token();
58 #define DEFAULT 1
59 #define LOGIN 2
60 #define PASSWD 3
61 #define NOTIFY 4
62 #define WRITE 5
63 #define YES 6
64 #define NO 7
65 #define COMMAND 8
66 #define FORCE 9
67 #define ID 10
68 #define MACHINE 11
70 #define MAXTOKEN 11
71 #define NTOKENS (MAXTOKEN - 1 + 2 + 1) /* two duplicates and null, minus id */
73 static struct ruserdata {
74 char tokval[100];
75 struct toktab {
76 char *tokstr;
77 int tval;
78 } toktab[NTOKENS];
79 FILE *cfile;
80 } *ruserdata, *_ruserdata();
83 static struct ruserdata *
84 _ruserdata()
86 struct ruserdata *d = ruserdata;
87 struct toktab *t;
89 if (d == 0) {
90 if ((d = (struct ruserdata *)
91 calloc(1, sizeof (struct ruserdata))) == NULL) {
92 return (NULL);
94 ruserdata = d;
95 t = d->toktab;
96 t->tokstr = "default"; t++->tval = DEFAULT;
97 t->tokstr = "login"; t++->tval = LOGIN;
98 t->tokstr = "password"; t++->tval = PASSWD;
99 t->tokstr = "notify"; t++->tval = NOTIFY;
100 t->tokstr = "write"; t++->tval = WRITE;
101 t->tokstr = "yes"; t++->tval = YES;
102 t->tokstr = "y"; t++->tval = YES;
103 t->tokstr = "no"; t++->tval = NO;
104 t->tokstr = "n"; t++->tval = NO;
105 t->tokstr = "command"; t++->tval = COMMAND;
106 t->tokstr = "force"; t++->tval = FORCE;
107 t->tokstr = "machine"; t++->tval = MACHINE;
108 t->tokstr = 0; t->tval = 0;
110 return (d);
114 #define MAXANAME 16
116 void
117 _ruserpass(const char *host, char **aname, char **apass)
120 if (*aname == 0 || *apass == 0)
121 rnetrc(host, aname, apass);
122 if (*aname == 0) {
123 char myname[L_cuserid];
125 *aname = malloc(MAXANAME + 1);
126 (void) cuserid(myname);
127 (void) printf(dgettext(TEXT_DOMAIN, "Name (%s:%s): "),
128 host, myname);
129 (void) fflush(stdout);
130 if (read(2, *aname, MAXANAME) <= 0)
131 exit(1);
132 aname[0][MAXANAME] = '\0';
133 if ((*aname)[0] == '\n')
134 (void) strcpy(*aname, myname);
135 else
136 if (index(*aname, '\n'))
137 *index(*aname, '\n') = 0;
139 if (*aname && *apass == 0) {
140 (void) printf(dgettext(TEXT_DOMAIN, "Password (%s:%s): "),
141 host, *aname);
142 (void) fflush(stdout);
143 *apass = getpass("");
148 static void
149 rnetrc(const char *host, char **aname, char **apass)
151 struct ruserdata *d = _ruserdata();
152 char *hdir, buf[PATH_MAX];
153 int t;
154 struct stat64 stb;
156 if (d == 0)
157 return;
159 hdir = getenv("HOME");
160 if (hdir == NULL)
161 hdir = ".";
162 t = snprintf(buf, sizeof (buf), "%s/.netrc", hdir);
163 if (t < 0 || t >= sizeof (buf)) {
164 if (t < 0) {
165 perror(buf);
166 } else {
167 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
168 "HOME directory name is too long: %s\n"), hdir);
170 return;
173 d->cfile = fopen(buf, "rF");
174 if (d->cfile == NULL) {
175 if (errno != ENOENT)
176 perror(buf);
177 return;
179 next:
180 while ((t = token()))
181 switch (t) {
183 case DEFAULT:
184 (void) token();
185 continue;
187 case MACHINE:
188 if (token() != ID || strcmp(host, d->tokval))
189 continue;
190 while ((t = token()) != 0 && t != MACHINE)
191 switch (t) {
193 case LOGIN:
194 if (token())
195 if (*aname == 0) {
196 *aname = malloc(strlen(d->tokval) + 1);
197 (void) strcpy(*aname, d->tokval);
198 } else {
199 if (strcmp(*aname, d->tokval))
200 goto next;
202 break;
203 case PASSWD:
204 if (fstat64(fileno(d->cfile), &stb) >= 0 &&
205 (stb.st_mode & 077) != 0) {
206 (void) fprintf(stderr,
207 dgettext(TEXT_DOMAIN,
208 "Error - .netrc file not correct mode.\n"));
209 (void) fprintf(stderr,
210 dgettext(TEXT_DOMAIN,
211 "Remove password or correct mode.\n"));
212 exit(1);
214 if (token() && *apass == 0) {
215 *apass = malloc(strlen(d->tokval) + 1);
216 (void) strcpy(*apass, d->tokval);
218 break;
219 case COMMAND:
220 case NOTIFY:
221 case WRITE:
222 case FORCE:
223 (void) token();
224 break;
225 default:
226 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
227 "Unknown .netrc option %s\n"), d->tokval);
228 break;
230 goto done;
232 done:
233 (void) fclose(d->cfile);
236 static int
237 token()
239 struct ruserdata *d = _ruserdata();
240 char *cp;
241 int c;
242 struct toktab *t;
244 if (d == 0)
245 return (0);
247 if (feof(d->cfile))
248 return (0);
249 while ((c = getc(d->cfile)) != EOF &&
250 (c == '\n' || c == '\t' || c == ' ' || c == ','))
251 continue;
252 if (c == EOF)
253 return (0);
254 cp = d->tokval;
255 if (c == '"') {
256 while ((c = getc(d->cfile)) != EOF && c != '"') {
257 if (c == '\\')
258 c = getc(d->cfile);
259 *cp++ = (char)c;
261 } else {
262 *cp++ = (char)c;
263 while ((c = getc(d->cfile)) != EOF &&
264 c != '\n' && c != '\t' && c != ' ' && c != ',') {
265 if (c == '\\')
266 c = getc(d->cfile);
267 *cp++ = (char)c;
270 *cp = 0;
271 if (d->tokval[0] == 0)
272 return (0);
273 for (t = d->toktab; t->tokstr; t++)
274 if ((strcmp(t->tokstr, d->tokval) == 0))
275 return (t->tval);
276 return (ID);