1: static char sccsid[] = "@(#)netrc.c 4.1 (Berkeley) 9/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: }