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