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