|
|
1.1 ! root 1: /* ! 2: * File: asymkdev.c ! 3: * ! 4: * Purpose: read a spec from stdin, ask questions, and make nodes ! 5: * ! 6: * $Log: asymkdev.c,v $ ! 7: * Revision 1.1 92/07/17 15:28:53 bin ! 8: * Initial revision ! 9: * ! 10: */ ! 11: ! 12: /* ! 13: * ---------------------------------------------------------------------- ! 14: * Includes. ! 15: */ ! 16: #include <stdio.h> ! 17: #include <termio.h> ! 18: #include <sys/ktty.h> ! 19: #include <sys/asy.h> ! 20: #include <sys/devices.h> ! 21: ! 22: /* ! 23: * ---------------------------------------------------------------------- ! 24: * Definitions. ! 25: * Constants. ! 26: * Macros with argument lists. ! 27: * Typedefs. ! 28: * Enums. ! 29: */ ! 30: #define BSZ 256 ! 31: #define ASYNC_SPECFILE "/etc/default/async" ! 32: #define ASYNC_MKNODS "asy_mknod" ! 33: ! 34: #define L_ 0 ! 35: #define R_ 1 ! 36: #define PL_ 2 ! 37: #define PR_ 3 ! 38: #define FL_ 4 ! 39: #define FR_ 5 ! 40: #define FPL_ 6 ! 41: #define FPR_ 7 ! 42: ! 43: #define NO(a,b,c,d) {use_opt[a]=0;use_opt[b]=0;use_opt[c]=0;use_opt[d]=0;} ! 44: #define MAX_OPT 8 ! 45: #define prompt if(!uflag)printf ! 46: ! 47: /* ! 48: * ---------------------------------------------------------------------- ! 49: * Functions. ! 50: * Import Functions. ! 51: * Export Functions. ! 52: * Local Functions. ! 53: */ ! 54: void fatal(); ! 55: void g_rec(); ! 56: void get_opts(); ! 57: void m_rec(); ! 58: void make_nodes(); ! 59: void p_rec(); ! 60: void usage(); ! 61: ! 62: /* ! 63: * ---------------------------------------------------------------------- ! 64: * Global Data. ! 65: * Import Variables. ! 66: * Export Variables. ! 67: * Local Variables. ! 68: */ ! 69: int line; /* line number in input file */ ! 70: unsigned int x1,x2,x3,x4,x5,x6,x7; ! 71: char *cmd; ! 72: char chan_found[MAX_ASY]; /* true if record seen for the channel */ ! 73: int port[MAX_ASY]; /* port address for the channel */ ! 74: char buf[BSZ]; /* input line buffer */ ! 75: char msg[BSZ]; /* error message line buffer */ ! 76: char expect_chan; /* number of "M" records expected */ ! 77: char uflag; /* unprompted mode */ ! 78: char *suffix[MAX_OPT] = { ! 79: "l", /* L_ */ ! 80: "r", /* R_ */ ! 81: "pl", /* PL_ */ ! 82: "pr", /* PR_ */ ! 83: "fl", /* FL_ */ ! 84: "fr", /* FR_ */ ! 85: "fpl", /* FPL_ */ ! 86: "fpr" /* FPR_ */ ! 87: }; ! 88: char *ofile, *sfile; ! 89: unsigned char nmod, poll, flow; ! 90: ! 91: /* ! 92: * ---------------------------------------------------------------------- ! 93: * Code. ! 94: */ ! 95: ! 96: /* ! 97: * main() ! 98: * ! 99: * while able to read a line from input ! 100: * call routine to process the record type ! 101: */ ! 102: main(argc, argv) ! 103: int argc; ! 104: char **argv; ! 105: { ! 106: char *cp; ! 107: FILE *fp; ! 108: ! 109: cmd = argv[0]; ! 110: ! 111: if (!isatty(1)) ! 112: usage(); ! 113: ! 114: /* ! 115: * Scan command arguments. ! 116: */ ! 117: while (cp = *++argv) { ! 118: if (*cp == '-') { ! 119: while(*++cp) { ! 120: switch (*cp) { ! 121: case 'u': ! 122: uflag = 1; ! 123: break; ! 124: default: ! 125: usage(); ! 126: } ! 127: } ! 128: } else { ! 129: if (ofile) { ! 130: usage(); ! 131: } else { ! 132: if (sfile) ! 133: ofile = cp; ! 134: else ! 135: sfile = cp; ! 136: } ! 137: } ! 138: } ! 139: if (!ofile) ! 140: ofile = ASYNC_MKNODS; ! 141: if (!sfile) ! 142: sfile = ASYNC_SPECFILE; ! 143: ! 144: /* ! 145: * Find out which channels are in use. ! 146: */ ! 147: if ((fp = fopen(sfile, "r")) == 0) { ! 148: sprintf(msg, "%s: can't open spec file %s", cmd, sfile); ! 149: fatal(msg); ! 150: } ! 151: while (fgets(buf, BSZ, fp)) { ! 152: line++; ! 153: switch (buf[0]) { ! 154: case 'P': p_rec(); break; ! 155: case 'G': g_rec(); break; ! 156: case 'M': m_rec(); break; ! 157: } ! 158: } ! 159: fclose(fp); ! 160: ! 161: if (expect_chan) { ! 162: sprintf(msg, "expecting %d \"M\" entries", expect_chan); ! 163: fatal(msg); ! 164: } ! 165: ! 166: make_nodes(); ! 167: ! 168: prompt("Done.\n"); ! 169: exit(0); ! 170: } ! 171: ! 172: void ! 173: p_rec() ! 174: { ! 175: if (expect_chan) { ! 176: sprintf(msg, "expecting %d \"M\" entries", expect_chan); ! 177: fatal(msg); ! 178: } ! 179: ! 180: /* ! 181: * "P" record is: ! 182: * P port irq outs excl speed channel nms ! 183: * port and outs are in hex, others in decimal ! 184: */ ! 185: if (sscanf(buf+1, "%x%d%x%d%d%d%d",&x1,&x2,&x3,&x4,&x5,&x6,&x7) != 7) ! 186: fatal("need 7 parameters"); ! 187: ! 188: if (x6 >= MAX_ASY) { ! 189: sprintf(msg, "invalid channel #%d\n", x6); ! 190: fatal(msg); ! 191: } ! 192: ! 193: if (chan_found[x6]) { ! 194: sprintf(msg, "duplicate channel #%d\n", x6); ! 195: fatal(msg); ! 196: } ! 197: chan_found[x6] = 1; ! 198: port[x6] = x1; ! 199: } ! 200: ! 201: void ! 202: g_rec() ! 203: { ! 204: if (expect_chan) { ! 205: fprintf(stderr, "expecting %d \"M\" entries", expect_chan); ! 206: fatal("record out of order"); ! 207: } ! 208: ! 209: /* ! 210: * "G" record is: ! 211: * G port irq outs type number-of-channels nms ! 212: * port and outs are in hex, others in decimal ! 213: * see asy.h for valid types ! 214: */ ! 215: if (sscanf(buf+1, "%x%d%x%d%d%d",&x1,&x2,&x3,&x4,&x5,&x6) != 6) ! 216: fatal("need 6 parameters"); ! 217: if (x5 >= MAX_ASY || x5 == 0) ! 218: fatal("number of channels must be in range 1..8"); ! 219: expect_chan = x5; ! 220: } ! 221: ! 222: void ! 223: usage() ! 224: { ! 225: fprintf(stderr, "Usage: %s [-u] specfile outfile\n", cmd); ! 226: exit(1); ! 227: } ! 228: ! 229: void ! 230: fatal(s) ! 231: char *s; ! 232: { ! 233: fprintf(stderr, "%s: line %d %s\n", cmd, line, s); ! 234: exit(1); ! 235: } ! 236: ! 237: void ! 238: m_rec() ! 239: { ! 240: if (expect_chan == 0) { ! 241: fatal("unexpected \"M\" record"); ! 242: } ! 243: ! 244: /* ! 245: * "M" record is: ! 246: * M port speed slot channel ! 247: * port is in hex, speed in decimal ! 248: */ ! 249: if (sscanf(buf+1, "%x%d%d%d",&x1,&x2,&x3,&x4) != 4) ! 250: fatal("need 4 parameters"); ! 251: ! 252: if (x4 >= MAX_ASY) { ! 253: sprintf(msg, "invalid channel #%d\n", x4); ! 254: fatal(msg); ! 255: } ! 256: ! 257: chan_found[x4] = 1; ! 258: port[x4] = x1; ! 259: expect_chan--; ! 260: } ! 261: ! 262: void ! 263: make_nodes() ! 264: { ! 265: char chan; ! 266: char devname[20] = ""; ! 267: int last; ! 268: unsigned char minor; ! 269: char use_opt[MAX_OPT], opt; ! 270: FILE *ofp; ! 271: ! 272: if ((ofp = fopen(ofile, "w")) == 0) { ! 273: sprintf(msg, "%s: can't open outfile %s", cmd, ofile); ! 274: fatal(msg); ! 275: } ! 276: fprintf(ofp, ! 277: "set -x\n" ! 278: "DEV=${DEV-/dev}\n" ! 279: "if [ -d $DEV ]\n" ! 280: "then\n" ! 281: "\t:\n" ! 282: "else\n" ! 283: "\techo \"Invalid device directory $DEV\"\n" ! 284: "\texit 1\n" ! 285: "fi\n"); ! 286: ! 287: line = 0; ! 288: for (chan = 0; chan < MAX_ASY; chan++) { ! 289: if (chan_found[chan]) { ! 290: /* ! 291: * Make default device name. ! 292: * Add 1 to last character of previous name, with carry. ! 293: * Start with "asy00". ! 294: */ ! 295: if (devname[0]) { ! 296: last = strlen(devname) - 1; ! 297: if (last > 0 && devname[last]++ == '9') { ! 298: devname[last--] = '0'; ! 299: devname[last]++; ! 300: } ! 301: } else { ! 302: strcpy(devname, "asy00"); ! 303: } ! 304: prompt("Channel %2d is port %4x\n", chan, port[chan]); ! 305: prompt("Device name [%s]: ", devname); ! 306: line++; ! 307: if (!fgets(buf, BSZ, stdin)) { ! 308: sprintf(msg, "%s: input error at channel %d", ! 309: cmd, chan); ! 310: fatal(msg); ! 311: } ! 312: sscanf(buf, "%s", devname); ! 313: ! 314: /* ! 315: * Get user preferences about which devices to make. ! 316: */ ! 317: get_opts(chan); ! 318: ! 319: /* ! 320: * Make up to 8 nodes per device. ! 321: */ ! 322: for (opt = 0; opt < MAX_OPT; opt++) ! 323: use_opt[opt] = 1; ! 324: if (nmod == 0) ! 325: NO(L_, PL_, FL_, FPL_) ! 326: else if (nmod == 1) ! 327: NO(R_, PR_, FR_, FPR_) ! 328: if (poll == 0) ! 329: NO(PL_, PR_, FPL_, FPR_) ! 330: else if (poll == 1) ! 331: NO(L_, R_, FL_, FR_) ! 332: if (flow == 0) ! 333: NO(FL_, FR_, FPL_, FPR_) ! 334: else if (flow == 1) ! 335: NO(L_, R_, PL_, PR_) ! 336: for (opt = 0; opt < MAX_OPT; opt++) ! 337: if (use_opt[opt]) { ! 338: minor = chan; ! 339: if ((opt & 1) == 0) ! 340: minor |= 0x80; ! 341: if (opt & 2) ! 342: minor |= 0x40; ! 343: if (opt & 4) ! 344: minor |= 0x20; ! 345: fprintf(ofp, "/etc/mknod -f $DEV/%s%s c %d %d || exit 1\n", ! 346: devname, suffix[opt], ASY_MAJOR, minor); ! 347: fprintf(ofp, "/bin/chmog 666 sys sys $DEV/%s%s || exit 1\n", ! 348: devname, suffix[opt]); ! 349: } ! 350: } ! 351: } ! 352: fclose(ofp); ! 353: } ! 354: ! 355: /* ! 356: * get_opts() ! 357: * ! 358: * set nmod, poll, flow ! 359: */ ! 360: void ! 361: get_opts(chan) ! 362: int chan; ! 363: { ! 364: static char my_opts[20] = "lrin"; ! 365: char *cp; ! 366: ! 367: prompt("options - (l|r) (i|p) (f|n) [%s]: ", my_opts); ! 368: line++; ! 369: if (!fgets(buf, BSZ, stdin)) { ! 370: sprintf(msg, "input error at channel %d", chan); ! 371: fatal(msg); ! 372: } ! 373: sscanf(buf, "%s", my_opts); ! 374: ! 375: /* ! 376: * Must have at least one of each pair of switches. ! 377: */ ! 378: nmod = 0; ! 379: poll = 0; ! 380: flow = 0; ! 381: for (cp = my_opts; *cp; cp++) { ! 382: switch (*cp) { ! 383: case 'r': nmod |= 1; break; ! 384: case 'l': nmod |= 2; break; ! 385: case 'i': poll |= 1; break; ! 386: case 'p': poll |= 2; break; ! 387: case 'n': flow |= 1; break; ! 388: case 'f': flow |= 2; break; ! 389: default: ! 390: sprintf(msg, ! 391: "invalid option [%s], channel %d", ! 392: my_opts, chan); ! 393: fatal(msg); ! 394: } ! 395: } ! 396: if (nmod) ! 397: nmod--; ! 398: else { ! 399: sprintf(msg, "missing (l|r) option [%s], channel %d", ! 400: my_opts, chan); ! 401: fatal(msg); ! 402: } ! 403: if (poll) ! 404: poll--; ! 405: else { ! 406: sprintf(msg, "missing (i|p) option [%s], channel %d", ! 407: my_opts, chan); ! 408: fatal(msg); ! 409: } ! 410: if (flow) ! 411: flow--; ! 412: else { ! 413: sprintf(msg, "missing (f|n) option [%s], channel %d", ! 414: my_opts, chan); ! 415: fatal(msg); ! 416: } ! 417: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.