1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 #pragma ident "%Z%%M% %I% %E% SMI"
41
42 #include <stdio.h>
43 #include <ctype.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <errno.h>
47 #include <unistd.h>
48 #include <strings.h>
49 #include <stdlib.h>
50 #include <libintl.h>
51
52 #ifdef SYSV
53 #define index strchr
54 #endif /* SYSV */
55
56 static void rnetrc(const char *host, char **aname, char **apass);
57 static int token();
58
59 #define DEFAULT 1
60 #define LOGIN 2
61 #define PASSWD 3
62 #define NOTIFY 4
63 #define WRITE 5
64 #define YES 6
65 #define NO 7
66 #define COMMAND 8
67 #define FORCE 9
68 #define ID 10
69 #define MACHINE 11
70
71 #define MAXTOKEN 11
72 #define NTOKENS (MAXTOKEN - 1 + 2 + 1) /* two duplicates and null, minus id */
73
74 static struct ruserdata {
75 char tokval[100];
76 struct toktab {
77 char *tokstr;
78 int tval;
79 } toktab[NTOKENS];
80 FILE *cfile;
81 } *ruserdata, *_ruserdata();
82
83
84 static struct ruserdata *
_ruserdata()85 _ruserdata()
86 {
87 struct ruserdata *d = ruserdata;
88 struct toktab *t;
89
90 if (d == 0) {
91 if ((d = (struct ruserdata *)
92 calloc(1, sizeof (struct ruserdata))) == NULL) {
93 return (NULL);
94 }
95 ruserdata = d;
96 t = d->toktab;
97 t->tokstr = "default"; t++->tval = DEFAULT;
98 t->tokstr = "login"; t++->tval = LOGIN;
99 t->tokstr = "password"; t++->tval = PASSWD;
100 t->tokstr = "notify"; t++->tval = NOTIFY;
101 t->tokstr = "write"; t++->tval = WRITE;
102 t->tokstr = "yes"; t++->tval = YES;
103 t->tokstr = "y"; t++->tval = YES;
104 t->tokstr = "no"; t++->tval = NO;
105 t->tokstr = "n"; t++->tval = NO;
106 t->tokstr = "command"; t++->tval = COMMAND;
107 t->tokstr = "force"; t++->tval = FORCE;
108 t->tokstr = "machine"; t++->tval = MACHINE;
109 t->tokstr = 0; t->tval = 0;
110 }
111 return (d);
112 }
113
114
115 #define MAXANAME 16
116
117 void
_ruserpass(const char * host,char ** aname,char ** apass)118 _ruserpass(const char *host, char **aname, char **apass)
119 {
120
121 if (*aname == 0 || *apass == 0)
122 rnetrc(host, aname, apass);
123 if (*aname == 0) {
124 char myname[L_cuserid];
125
126 *aname = malloc(MAXANAME + 1);
127 (void) cuserid(myname);
128 (void) printf(dgettext(TEXT_DOMAIN, "Name (%s:%s): "),
129 host, myname);
130 (void) fflush(stdout);
131 if (read(2, *aname, MAXANAME) <= 0)
132 exit(1);
133 aname[0][MAXANAME] = '\0';
134 if ((*aname)[0] == '\n')
135 (void) strcpy(*aname, myname);
136 else
137 if (index(*aname, '\n'))
138 *index(*aname, '\n') = 0;
139 }
140 if (*aname && *apass == 0) {
141 (void) printf(dgettext(TEXT_DOMAIN, "Password (%s:%s): "),
142 host, *aname);
143 (void) fflush(stdout);
144 *apass = getpass("");
145 }
146 }
147
148
149 static void
rnetrc(const char * host,char ** aname,char ** apass)150 rnetrc(const char *host, char **aname, char **apass)
151 {
152 struct ruserdata *d = _ruserdata();
153 char *hdir, buf[BUFSIZ];
154 int t;
155 struct stat64 stb;
156
157 if (d == 0)
158 return;
159
160 hdir = getenv("HOME");
161 if (hdir == NULL)
162 hdir = ".";
163 (void) sprintf(buf, "%s/.netrc", hdir);
164 d->cfile = fopen(buf, "rF");
165 if (d->cfile == NULL) {
166 if (errno != ENOENT)
167 perror(buf);
168 return;
169 }
170 next:
171 while ((t = token()))
172 switch (t) {
173
174 case DEFAULT:
175 (void) token();
176 continue;
177
178 case MACHINE:
179 if (token() != ID || strcmp(host, d->tokval))
180 continue;
181 while ((t = token()) != 0 && t != MACHINE)
182 switch (t) {
183
184 case LOGIN:
185 if (token())
186 if (*aname == 0) {
187 *aname = malloc(strlen(d->tokval) + 1);
188 (void) strcpy(*aname, d->tokval);
189 } else {
190 if (strcmp(*aname, d->tokval))
191 goto next;
192 }
193 break;
194 case PASSWD:
195 if (fstat64(fileno(d->cfile), &stb) >= 0 &&
196 (stb.st_mode & 077) != 0) {
197 (void) fprintf(stderr,
198 dgettext(TEXT_DOMAIN,
199 "Error - .netrc file not correct mode.\n"));
200 (void) fprintf(stderr,
201 dgettext(TEXT_DOMAIN,
202 "Remove password or correct mode.\n"));
203 exit(1);
204 }
205 if (token() && *apass == 0) {
206 *apass = malloc(strlen(d->tokval) + 1);
207 (void) strcpy(*apass, d->tokval);
208 }
209 break;
210 case COMMAND:
211 case NOTIFY:
212 case WRITE:
213 case FORCE:
214 (void) token();
215 break;
216 default:
217 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
218 "Unknown .netrc option %s\n"), d->tokval);
219 break;
220 }
221 goto done;
222 }
223 done:
224 (void) fclose(d->cfile);
225 }
226
227 static int
token()228 token()
229 {
230 struct ruserdata *d = _ruserdata();
231 char *cp;
232 int c;
233 struct toktab *t;
234
235 if (d == 0)
236 return (0);
237
238 if (feof(d->cfile))
239 return (0);
240 while ((c = getc(d->cfile)) != EOF &&
241 (c == '\n' || c == '\t' || c == ' ' || c == ','))
242 continue;
243 if (c == EOF)
244 return (0);
245 cp = d->tokval;
246 if (c == '"') {
247 while ((c = getc(d->cfile)) != EOF && c != '"') {
248 if (c == '\\')
249 c = getc(d->cfile);
250 *cp++ = (char)c;
251 }
252 } else {
253 *cp++ = (char)c;
254 while ((c = getc(d->cfile)) != EOF &&
255 c != '\n' && c != '\t' && c != ' ' && c != ',') {
256 if (c == '\\')
257 c = getc(d->cfile);
258 *cp++ = (char)c;
259 }
260 }
261 *cp = 0;
262 if (d->tokval[0] == 0)
263 return (0);
264 for (t = d->toktab; t->tokstr; t++)
265 if ((strcmp(t->tokstr, d->tokval) == 0))
266 return (t->tval);
267 return (ID);
268 }
269