xref: /original-bsd/old/berknet/netrc.c (revision 57dcba5d)
1 static char sccsid[] = "@(#)netrc.c	4.1	(Berkeley)	09/12/82";
2 
3 /* sccs id variable */
4 static char *netrc_sid = "@(#)netrc.c	1.2";
5 /*
6 
7 	netrc.c
8 
9 	procedures to read and parse the .netrc file
10 
11 	You may call:
12 		commandfile() 		to read the file.
13 		rdnetfile(cfile)	to read the file.
14 
15 Note:
16 	commandfile()
17 		will read the passwd file
18 		if getenv(HOME) searches the passwd file
19 
20 Table of netrc options
21 	option			default
22 	------			-------
23 	default			default machine
24 	login string		current login
25 	password string		-
26 	notify yes/no		yes
27 	write yes/no		yes
28 	command string		-
29 	force yes/no		no
30 
31 Fabry has suggested that machine names be more general:
32 that you be able to say:
33 
34 	cory:	fabry on Cory
35 	caf:	caf on Cory
36 	c:	fabry on C
37 
38 so the formulation would look like:
39 
40 	default key
41 	key: machine login passwd ...
42 	key: ....
43 
44 and so on
45 
46 Gould has suggested the format be:
47 
48 	pseudo cory 	real Cory 	login fabry
49 	pseudo caf 	real Cory 	login caf
50 	pseudo c 	real C 		login fabry
51 
52 Init file example:
53 format local C remote A
54 
55 	default A
56 	machine A    local C link /dev/net-A    speed 9
57 	machine Cory local C link /dev/net-Cory speed 9
58 
59 if remote == 0, default is A
60 
61 passwords work as follows:
62    passwd = "\n" means no password
63 
64 */
65 # include "defs.h"
66 
67 /* tokens, returned by parser */
68 # define MACHINE 1
69 # define LOGIN 2
70 # define PASSWORD 3
71 # define ONLYUID 4
72 # define NOTIFY 5
73 # define QUIET 6
74 # define COMMAND 7
75 # define ID 8
76 # define YES 9
77 # define DEFAULT 10
78 # define WRITE 11
79 # define NO 12
80 # define FORCE 13
81 # define LOCALTOK 14
82 # define LINK 15
83 # define SPEED 16
84 # define LENGTH 18
85 # define DEBUGTOK 19
86 # define ALTIME 20
87 # define ALCOUNT 21
88 # define HISPEEDLINK 22
89 # define EIGHTBIT 23
90 # define INSPEED 24
91 # define OUTSPEED 25
92 
93 /* global */
94 struct userinfo status;
95 struct daemonparms netd = {
96 	LINKS,			/* inspeed */
97 	LINKS,			/* outspeed */
98 	MAXBREAD,		/* maxbread */
99 	ATIME,			/* atime */
100 	ATIME,			/* oatime */
101 	"/dev/null",		/* device */
102 	SIZE,			/* datasize */
103 	1,			/* trynetl */
104 	0			/* onlyuid */
105 	/* rest are all zero */
106 };
107 
108 /* local */
109 static char tokval[100];
110 
111 static struct tokstruct {
112 	char *tokstr;
113 	int tval;
114 }	toktab[]= {
115 	"machine",	MACHINE,
116 	"login",	LOGIN,
117 	"password",	PASSWORD,
118 	"onlyuid",	ONLYUID,
119 	"notify",	NOTIFY,
120 	"command",	COMMAND,
121 	"yes",		YES,
122 	"y",		YES,
123 	"no",		NO,
124 	"n",		NO,
125 	"default",	DEFAULT,
126 	"write",	WRITE,
127 	"force",	FORCE,
128 	"quiet",	QUIET,
129 	"local",	LOCALTOK,
130 	"speed",	SPEED,
131 	"link",		LINK,
132 	"length",	LENGTH,
133 	"debug",	DEBUGTOK,
134 	"time",		ALTIME,
135 	"count",	ALCOUNT,
136 	"hispeedlink",	HISPEEDLINK,
137 	"8bit",		EIGHTBIT,
138 	"inspeed",	INSPEED,
139 	"outspeed",	OUTSPEED,
140 	0,		0
141 	};
142 
143 static struct stat statbuf;
144 
145 /*
146 	commandfile()
147 
148 	this procedure reads in and parses the .netrc file.
149 	when you call this, if the remote machine is to be explicitely
150 	set, the global variable "remote" must have a value.
151 	on return, if it is non-zero, "remote" will have the
152 	remote machine the data was collected for.
153 	status.localname need not have a value.
154 */
commandfile()155 commandfile(){
156 	char *hdir, buf[BUFSIZ];
157 	FILE *cfile;
158 	hdir = getenv("HOME");
159 	if(hdir == NULL)hdir = ".";
160 	sprintf(buf,"%s/.netrc",hdir);
161 /*
162 	debug("file %s",buf);
163 */
164 	cfile = fopen(buf,"r");
165 	if(cfile == NULL)return;
166 	rdnetfile(cfile);
167 	fclose(cfile);
168 	}
169 /*
170 	read the file cfile and parse
171 */
rdnetfile(cfile)172 rdnetfile(cfile)
173 	FILE *cfile;
174 {
175 	int t;
176 	if(cfile == NULL)return;
177 	if(fstat(fileno(cfile),&statbuf) < 0 || (statbuf.st_mode & 0444) == 0)
178 		return;
179 	while((t = token(cfile))){
180 		switch(t){
181 		case DEFAULT:
182 			if(token(cfile) == ID && remote == 0)remote = lookup(tokval);
183 			/*
184 			debug("rem %c\n",remote);
185 			*/
186 			break;
187 		case MACHINE:
188 			if(remote == 0)remote = getremote(local);
189 			if(token(cfile) != ID)continue;
190 			if(remote != lookup(tokval))continue;
191 			/* this is the entry for the remote mach we want */
192 			getnetline(cfile);
193 			return;
194 			break;
195 		}
196 		}
197 	return;
198 	}
199 /*
200 	read a line of the file
201 */
getnetline(cfile)202 static getnetline(cfile)
203 	FILE *cfile;
204 {
205 	int t;
206 	while((t = token(cfile))){
207 		switch(t){
208 		/* these options are usually in the .netrc file */
209 		case MACHINE: return;
210 		case LOGIN:
211 			if(token(cfile) && status.login[0] == 0)
212 				strcpy(status.login,tokval);
213 			break;
214 		case PASSWORD:
215 			if(fstat(fileno(cfile),&statbuf) >= 0
216 			&& (statbuf.st_mode & 077) != 0){
217 				err("Error - .netrc file not correct mode.\n");
218 				err("Remove password or correct mode.\n");
219 				exit(EX_USAGE);
220 				}
221 			if(token(cfile) && status.mpasswd[0] == 0)
222 				strcpy(status.mpasswd,tokval);
223 			/*
224 			debug("mp:%s:%s\n",status.mpasswd,tokval);
225 			*/
226 			break;
227 		case NOTIFY:
228 			status.nonotify = token(cfile) == NO;
229 			break;
230 		case WRITE:
231 			status.nowrite = token(cfile) == NO;
232 			break;
233 		case COMMAND:
234 			if(token(cfile) && status.defcmd[0] == 0)
235 				strcpy(status.defcmd,tokval);
236 			break;
237 		case QUIET:
238 			status.quiet = token(cfile) == YES;
239 			break;
240 		case FORCE:
241 			status.force = token(cfile) == YES;
242 			break;
243 
244 		/* these options are usually in /usr/net/initfile */
245 		case LOCALTOK:
246 			if(token(cfile))local = lookup(tokval);
247 			break;
248 		case LINK:
249 			if(token(cfile))strcpy(netd.dp_device,tokval);
250 			break;
251 		case SPEED:
252 			if(token(cfile))
253 				netd.dp_inspeed = netd.dp_outspeed=atoi(tokval);
254 			break;
255 		case INSPEED:
256 			if(token(cfile))netd.dp_inspeed = atoi(tokval);
257 			break;
258 		case OUTSPEED:
259 			if(token(cfile))netd.dp_outspeed = atoi(tokval);
260 			break;
261 		case LENGTH:
262 			if(token(cfile))netd.dp_datasize = atoi(tokval);
263 			break;
264 		case DEBUGTOK:
265 			debugflg++;
266 			break;
267 		case ALTIME:
268 			if(token(cfile))netd.dp_oatime = atoi(tokval);
269 			break;
270 		case ALCOUNT:
271 			if(token(cfile))netd.dp_maxbread = atoi(tokval);
272 			break;
273 		case ONLYUID:
274 			if(token(cfile))netd.dp_onlyuid = atoi(tokval);
275 			break;
276 		case EIGHTBIT:
277 			netd.dp_use8bit++;
278 			break;
279 		case HISPEEDLINK:
280 			if(token(cfile))strcpy(netd.dp_hispeedlink,tokval);
281 			break;
282 		default:
283 			err("Unknown .netrc option %s\n",tokval);
284 			break;
285 		}
286 		}
287 	}
token(cfile)288 static token(cfile)
289 	FILE *cfile;
290 {	/* returns next token in cfile, 0 on EOF */
291 	char *p;
292 	int c;
293 	if(feof(cfile))return(0);
294 	while((c = getc(cfile)) != EOF && (c == '\n' || c == '\t'
295 		|| c == ' ' || c == ','));
296 	/* next char begins token */
297 	if(c == EOF)return(0);
298 	p = tokval;
299 	if(c == '"'){	/* process quoted string */
300 		while((c = getc(cfile)) != EOF && c != '"'){
301 			if(c == '\\')c = getc(cfile);
302 			*p++ = c;
303 			}
304 		}
305 	else {
306 		*p++ = c;
307 		while((c = getc(cfile)) != EOF && c != '\n' && c != '\t'
308 			&& c != ' ' && c != ','){
309 			if(c == '\\')c = getc(cfile);
310 			*p++ = c;
311 			}
312 		}
313 	*p = 0;
314 	if(tokval[0] == 0)return(0);
315 /*
316 	debug("tok %s",tokval);
317 */
318 	return(tlookup(tokval));
319 	}
tlookup(str)320 static tlookup(str)
321   char *str; {
322 	struct tokstruct *p;
323 	for(p = toktab; p->tokstr; p++)
324 		if(streql(p->tokstr,str) == 0){
325 			return(p->tval);
326 			}
327 	return(ID);
328 	}
329