|
|
1.1 root 1: #include <sys/types.h>
2: #include <sys/stat.h>
3: #include <sys/filio.h>
4: #include <stdio.h>
5: #include <errno.h>
6: #include <sys/dkio.h>
7:
8: extern int errno;
9: extern int uxp_ld;
10: extern int dkp_ld;
11: extern char *netfiles; /* /dev/dk/dk by default */
12:
13: static char *cnames[] = {
14: "%sctl0",
15: "%sctl",
16: "%sctl2",
17: 0
18: };
19: static char *names[] = {
20: "%s0%c%c",
21: "%s%c%c",
22: "%s2%c%c",
23: 0
24: };
25:
26: static char alph[] = "0123456789abcdefghijklmnopqrstuvwxyz";
27:
28: static int high[] = {256, 256};
29: static int low[] = {1, 1};
30:
31: /*
32: * figure out which set of dk channels to use
33: */
34: static
35: dkindex(traffic, unit)
36: int traffic;
37: int unit;
38: {
39: switch(unit) {
40: case '0':
41: return 0;
42: case '2':
43: return 2;
44: case 'b':
45: return traffic;
46: default:
47: return 1;
48: }
49: }
50:
51: /*
52: * Open a free dk channel and remember the `type' in namefmt.
53: * If one device doesn't work, try another.
54: */
55: static int
56: dkchan2(traffic, unit, chanp, ctlfdp)
57: int traffic;
58: int unit;
59: int *chanp;
60: int *ctlfdp;
61: {
62: int missing=0;
63: char outname[64];
64: register i,j;
65: int k;
66: int fd;
67: int ai;
68: int nfd;
69:
70: /*
71: * get the control channel and ask for a suggested channel
72: */
73: *ctlfdp = dkctlchan(traffic, unit);
74: if(*ctlfdp<0)
75: return -1;
76: k = 0;
77: if(ioctl(*ctlfdp, DIOCCHAN, &k)>0 && k>0)
78: low[0] = high[1] = k;
79:
80: /*
81: * starting with the suggested channel, loop through all
82: * channels looking for one not in use
83: */
84: ai=dkindex(traffic, unit);
85: for (j=0; j<2; j++) {
86: for (i=low[j]; i<high[j]; i++) {
87: sprintf(outname, names[ai], netfiles, alph[i/10], alph[i%10]);
88: if ((fd = open(outname, 2)) >= 0){
89: if ((nfd = open(outname, 2)) >= 0) {
90: close(nfd);
91: close(fd);
92: continue; /* already in use */
93: }
94: flabclr(fd); /* for secure unix */
95: break;
96: }
97: if (errno==ENOENT)
98: if (++missing>5)
99: break;
100: }
101: if (fd>=0)
102: break;
103: }
104: if (fd < 0)
105: return -1;
106: low[0] = high[1] = i+1;
107: *chanp = i;
108: return fd;
109: }
110: int
111: dkchan(trafp, unit, chanp, ctlfdp)
112: int *trafp;
113: int unit;
114: int *chanp;
115: int *ctlfdp;
116: {
117: int fd;
118:
119: fd = dkchan2(*trafp, unit, chanp, ctlfdp);
120: if(fd >= 0)
121: return fd;
122: if (*trafp == 0)
123: *trafp = 2;
124: else
125: *trafp = 0;
126: return dkchan2(*trafp, unit, chanp, ctlfdp);
127: }
128:
129: /*
130: * open common control channel
131: */
132: dkctlchan(traffic, unit)
133: {
134: register i ;
135: char dkctlfile[32];
136: int ai;
137:
138: ai=dkindex(traffic, unit);
139: sprintf(dkctlfile, cnames[ai], netfiles);
140: i = open(dkctlfile, 2);
141: if (i < 0)
142: return -1;
143: ioctl(i, DIOCNXCL, 0);
144: if (ioctl(i, FIOLOOKLD, 0) != uxp_ld) {
145: if (dkproto(i, dkp_ld) < 0) {
146: fprintf(stderr, "can't push dkp_ld on %s\n", dkctlfile) ;
147: close(i) ;
148: return -1;
149: }
150: if (ioctl(i, FIOPUSHLD, &uxp_ld) < 0) {
151: fprintf(stderr, "can't push unixp_ld on %s\n", dkctlfile) ;
152: close(i) ;
153: return -1;
154: }
155: if (ioctl(i, DIOCLHN, (char *)0) < 0) {
156: fprintf(stderr, "can't be manager on %s\n", dkctlfile) ;
157: close(i);
158: return -1;
159: }
160: }
161: return i;
162: }
163:
164: /*
165: * find the file name corresponding to a given channel.
166: * assumes dkctlchan has been called.
167: * Used for incoming calls.
168: */
169: char *
170: dkfilename(traffic, unit, chan)
171: {
172: static char name[64];
173:
174: sprintf(name, names[dkindex(traffic, unit)], netfiles, alph[chan/10], alph[chan%10]);
175: return(name);
176: }
177:
178: /*
179: * Make sure that URP protocol is enabled on a datakit file.
180: */
181: int
182: dkproto(file, linedis)
183: {
184: if (ioctl(file, KIOCISURP, (char *)0) < 0)
185: return(ioctl(file, FIOPUSHLD, &linedis));
186: ioctl(file, KIOCINIT, (char *)0);
187: return(0);
188: }
189:
190: /*
191: * find the traffic type and channel number corresponding to an fd.
192: * Used for redial.
193: */
194: int
195: dkid(fd, unit, trafficp, chanp, ctlfdp)
196: int fd;
197: int unit;
198: int *trafficp;
199: int *chanp;
200: int *ctlfdp;
201: {
202: struct stat s;
203: struct stat s2;
204:
205: /*
206: * find major minor
207: */
208: if(fstat(fd, &s)<0)
209: return -1;
210:
211: /*
212: * compare major/minor of fd against that of device 3
213: */
214: if(stat(dkfilename(0, unit, 3), &s2)>=0){
215: if(major(s.st_rdev)==major(s2.st_rdev)){
216: if(minor(s.st_rdev)>minor(s2.st_rdev)-3){
217: *trafficp = 0;
218: *chanp = minor(s.st_rdev)-minor(s2.st_rdev)+3;
219: *ctlfdp = dkctlchan(*trafficp, unit);
220: if(*ctlfdp < 0)
221: return -1;
222: return 0;
223: }
224: }
225: }
226: if(stat(dkfilename(2, unit, 3), &s2)>=0){
227: if(major(s.st_rdev)==major(s2.st_rdev)){
228: if(minor(s.st_rdev)>minor(s2.st_rdev)-3){
229: *trafficp = 2;
230: *chanp = minor(s.st_rdev)-minor(s2.st_rdev)+3;
231: *ctlfdp = dkctlchan(*trafficp, unit);
232: if(*ctlfdp < 0)
233: return -1;
234: return 0;
235: }
236: }
237: }
238: return -1;
239: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.