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