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 */ 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 */ 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 */ 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 } 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 } 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