|
|
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.3 93/05/18 07:32:18 bin
8: * *** empty log message ***
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.