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