don't call fclose unless the file was opened
[unix-history] / usr / src / usr.bin / ftp / ruserpass.c
CommitLineData
3a38a184
GM
1/*
2 * Copyright (c) 1985 Regents of the University of California.
11c5f0a3
KB
3 * All rights reserved.
4 *
1343342a 5 * %sccs.include.redist.c%
3a38a184
GM
6 */
7
8#ifndef lint
1343342a 9static char sccsid[] = "@(#)ruserpass.c 5.2 (Berkeley) %G%";
11c5f0a3 10#endif /* not lint */
3a38a184 11
385d0849 12#include <sys/types.h>
3a38a184
GM
13#include <stdio.h>
14#include <utmp.h>
15#include <ctype.h>
3a38a184
GM
16#include <sys/stat.h>
17#include <errno.h>
cdc35b45 18#include "ftp_var.h"
3a38a184
GM
19
20char *renvlook(), *malloc(), *index(), *getenv(), *getpass(), *getlogin();
04480325 21char *strcpy();
3a38a184
GM
22struct utmp *getutmp();
23static FILE *cfile;
24
3a38a184
GM
25#define DEFAULT 1
26#define LOGIN 2
27#define PASSWD 3
28#define ACCOUNT 4
29#define MACDEF 5
30#define ID 10
cdc35b45 31#define MACH 11
3a38a184
GM
32
33static char tokval[100];
34
35static struct toktab {
36 char *tokstr;
37 int tval;
38} toktab[]= {
39 "default", DEFAULT,
40 "login", LOGIN,
41 "password", PASSWD,
cdc35b45 42 "passwd", PASSWD,
3a38a184 43 "account", ACCOUNT,
cdc35b45 44 "machine", MACH,
3a38a184
GM
45 "macdef", MACDEF,
46 0, 0
47};
48
cdc35b45 49ruserpass(host, aname, apass, aacct)
3a38a184
GM
50 char *host, **aname, **apass, **aacct;
51{
04480325 52 char *hdir, buf[BUFSIZ], *tmp;
cdc35b45 53 char myname[MAXHOSTNAMELEN], *mydomain;
ff00793c 54 int t, i, c, usedefault = 0;
3a38a184
GM
55 struct stat stb;
56 extern int errno;
57
58 hdir = getenv("HOME");
59 if (hdir == NULL)
60 hdir = ".";
04480325 61 (void) sprintf(buf, "%s/.netrc", hdir);
3a38a184
GM
62 cfile = fopen(buf, "r");
63 if (cfile == NULL) {
64 if (errno != ENOENT)
65 perror(buf);
66 return(0);
67 }
cdc35b45
MK
68 if (gethostname(myname, sizeof(myname)) < 0)
69 myname[0] = '\0';
70 if ((mydomain = index(myname, '.')) == NULL)
71 mydomain = "";
3a38a184
GM
72next:
73 while ((t = token())) switch(t) {
74
75 case DEFAULT:
ff00793c
MK
76 usedefault = 1;
77 /* FALL THROUGH */
3a38a184 78
cdc35b45
MK
79 case MACH:
80 if (!usedefault) {
81 if (token() != ID)
82 continue;
83 /*
84 * Allow match either for user's input host name
85 * or official hostname. Also allow match of
86 * incompletely-specified host in local domain.
87 */
88 if (strcasecmp(host, tokval) == 0)
89 goto match;
90 if (strcasecmp(hostname, tokval) == 0)
91 goto match;
92 if ((tmp = index(hostname, '.')) != NULL &&
93 strcasecmp(tmp, mydomain) == 0 &&
94 strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
95 tokval[tmp - hostname] == '\0')
96 goto match;
97 if ((tmp = index(host, '.')) != NULL &&
98 strcasecmp(tmp, mydomain) == 0 &&
99 strncasecmp(host, tokval, tmp - host) == 0 &&
100 tokval[tmp - host] == '\0')
101 goto match;
3a38a184 102 continue;
cdc35b45
MK
103 }
104 match:
105 while ((t = token()) && t != MACH && t != DEFAULT) switch(t) {
3a38a184
GM
106
107 case LOGIN:
108 if (token())
109 if (*aname == 0) {
04480325
GM
110 *aname = malloc((unsigned) strlen(tokval) + 1);
111 (void) strcpy(*aname, tokval);
3a38a184
GM
112 } else {
113 if (strcmp(*aname, tokval))
114 goto next;
115 }
116 break;
117 case PASSWD:
cdc35b45
MK
118 if (strcmp(*aname, "anonymous") &&
119 fstat(fileno(cfile), &stb) >= 0 &&
120 (stb.st_mode & 077) != 0) {
e6be46b8 121 fprintf(stderr, "Error - .netrc file not correct mode.\n");
3a38a184 122 fprintf(stderr, "Remove password or correct mode.\n");
cdc35b45 123 goto bad;
3a38a184
GM
124 }
125 if (token() && *apass == 0) {
04480325
GM
126 *apass = malloc((unsigned) strlen(tokval) + 1);
127 (void) strcpy(*apass, tokval);
3a38a184
GM
128 }
129 break;
130 case ACCOUNT:
131 if (fstat(fileno(cfile), &stb) >= 0
132 && (stb.st_mode & 077) != 0) {
e6be46b8 133 fprintf(stderr, "Error - .netrc file not correct mode.\n");
3a38a184 134 fprintf(stderr, "Remove account or correct mode.\n");
cdc35b45 135 goto bad;
3a38a184
GM
136 }
137 if (token() && *aacct == 0) {
04480325
GM
138 *aacct = malloc((unsigned) strlen(tokval) + 1);
139 (void) strcpy(*aacct, tokval);
3a38a184
GM
140 }
141 break;
142 case MACDEF:
143 if (proxy) {
cdc35b45 144 (void) fclose(cfile);
3a38a184
GM
145 return(0);
146 }
147 while ((c=getc(cfile)) != EOF && c == ' ' || c == '\t');
148 if (c == EOF || c == '\n') {
149 printf("Missing macdef name argument.\n");
cdc35b45 150 goto bad;
3a38a184
GM
151 }
152 if (macnum == 16) {
153 printf("Limit of 16 macros have already been defined\n");
cdc35b45 154 goto bad;
3a38a184
GM
155 }
156 tmp = macros[macnum].mac_name;
157 *tmp++ = c;
158 for (i=0; i < 8 && (c=getc(cfile)) != EOF &&
159 !isspace(c); ++i) {
160 *tmp++ = c;
161 }
162 if (c == EOF) {
163 printf("Macro definition missing null line terminator.\n");
cdc35b45 164 goto bad;
3a38a184
GM
165 }
166 *tmp = '\0';
167 if (c != '\n') {
168 while ((c=getc(cfile)) != EOF && c != '\n');
169 }
170 if (c == EOF) {
171 printf("Macro definition missing null line terminator.\n");
cdc35b45 172 goto bad;
3a38a184
GM
173 }
174 if (macnum == 0) {
175 macros[macnum].mac_start = macbuf;
176 }
177 else {
178 macros[macnum].mac_start = macros[macnum-1].mac_end + 1;
179 }
180 tmp = macros[macnum].mac_start;
181 while (tmp != macbuf + 4096) {
182 if ((c=getc(cfile)) == EOF) {
183 printf("Macro definition missing null line terminator.\n");
cdc35b45 184 goto bad;
3a38a184
GM
185 }
186 *tmp = c;
187 if (*tmp == '\n') {
188 if (*(tmp-1) == '\0') {
189 macros[macnum++].mac_end = tmp - 1;
190 break;
191 }
192 *tmp = '\0';
193 }
194 tmp++;
195 }
196 if (tmp == macbuf + 4096) {
197 printf("4K macro buffer exceeded\n");
cdc35b45 198 goto bad;
3a38a184
GM
199 }
200 break;
201 default:
e6be46b8 202 fprintf(stderr, "Unknown .netrc keyword %s\n", tokval);
3a38a184
GM
203 break;
204 }
205 goto done;
206 }
207done:
04480325
GM
208 (void) fclose(cfile);
209 return(0);
cdc35b45
MK
210bad:
211 (void) fclose(cfile);
212 return(-1);
3a38a184
GM
213}
214
215static
216token()
217{
218 char *cp;
219 int c;
220 struct toktab *t;
221
222 if (feof(cfile))
223 return (0);
224 while ((c = getc(cfile)) != EOF &&
225 (c == '\n' || c == '\t' || c == ' ' || c == ','))
226 continue;
227 if (c == EOF)
228 return (0);
229 cp = tokval;
230 if (c == '"') {
231 while ((c = getc(cfile)) != EOF && c != '"') {
232 if (c == '\\')
233 c = getc(cfile);
234 *cp++ = c;
235 }
236 } else {
237 *cp++ = c;
238 while ((c = getc(cfile)) != EOF
239 && c != '\n' && c != '\t' && c != ' ' && c != ',') {
240 if (c == '\\')
241 c = getc(cfile);
242 *cp++ = c;
243 }
244 }
245 *cp = 0;
246 if (tokval[0] == 0)
247 return (0);
248 for (t = toktab; t->tokstr; t++)
249 if (!strcmp(t->tokstr, tokval))
250 return (t->tval);
251 return (ID);
252}