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