|
|
1.1 root 1: /* mx1.c 4.6 81/03/11 */
2:
3: #include "../h/param.h"
4: #include "../h/systm.h"
5: #include "../h/dir.h"
6: #include "../h/user.h"
7: #include "../h/reg.h"
8: #include "../h/proc.h"
9: #include "../h/tty.h"
10: #include "../h/inode.h"
11: #include "../h/mx.h"
12: #include "../h/file.h"
13: #include "../h/conf.h"
14:
15: /*
16: * Multiplexor: clist version
17: *
18: * installation:
19: * requires a line in cdevsw -
20: * mxopen, mxclose, mxread, mxwrite, mxioctl, 0,
21: *
22: * also requires a line in linesw -
23: * mxopen, mxclose, mcread, mcwrite, mxioctl, nulldev, nulldev,
24: *
25: * The linesw entry for mpx should be the last one in the table.
26: * 'nldisp' (number of line disciplines) should not include the
27: * mpx line. This is to prevent mpx from being enabled by an ioctl.
28: */
29: struct chan chans[NCHANS];
30: struct schan schans[NPORTS];
31: struct group *groups[NGROUPS];
32: int mpxline;
33: struct chan *xcp();
34: dev_t mpxdev = -1;
35:
36:
37: char mcdebugs[NDEBUGS];
38:
39:
40: /*
41: * Allocate a channel, set c_index to index.
42: */
43: struct chan *
44: challoc(index, isport)
45: {
46: register s,i;
47: register struct chan *cp;
48:
49: s = spl6();
50: for(i=0;i<((isport)?NPORTS:NCHANS);i++) {
51: cp = (isport)? (struct chan *)(schans+i): chans+i;
52: if(cp->c_group == NULL) {
53: cp->c_index = index;
54: cp->c_pgrp = 0;
55: cp->c_flags = 0;
56: splx(s);
57: return(cp);
58: }
59: }
60: splx(s);
61: return(NULL);
62: }
63:
64:
65:
66: /*
67: * Allocate a group table cell.
68: */
69: gpalloc()
70: {
71: register i;
72:
73: for (i=NGROUPS-1; i>=0; i--)
74: if (groups[i]==NULL) {
75: groups[i]++;
76: return(i);
77: }
78: u.u_error = ENXIO;
79: return(i);
80: }
81:
82:
83: /*
84: * Add a channel to the group in
85: * inode ip.
86: */
87: struct chan *
88: addch(ip, isport)
89: struct inode *ip;
90: {
91: register struct chan *cp;
92: register struct group *gp;
93: register i;
94:
95: plock(ip);
96: gp = &ip->i_un.i_group;
97: for(i=0;i<NINDEX;i++) {
98: cp = (struct chan *)gp->g_chans[i];
99: if (cp == NULL) {
100: if ((cp=challoc(i, isport)) != NULL) {
101: gp->g_chans[i] = cp;
102: cp->c_group = gp;
103: }
104: break;
105: }
106: cp = NULL;
107: }
108: prele(ip);
109: return(cp);
110: }
111:
112: /*
113: * Mpxchan system call.
114: */
115:
116: mpxchan()
117: {
118: extern mxopen(), mcread(), sdata(), scontrol();
119: struct inode *ip, *gip;
120: struct tty *tp;
121: struct file *fp, *chfp, *gfp;
122: struct chan *cp;
123: struct group *gp, *ngp;
124: struct mx_args vec;
125: struct a {
126: int cmd;
127: int *argvec;
128: } *uap;
129: dev_t dev;
130: register int i;
131:
132: /*
133: * Common setup code.
134: */
135:
136: uap = (struct a *)u.u_ap;
137: (void) copyin((caddr_t)uap->argvec, (caddr_t)&vec, sizeof vec);
138: gp = NULL; gfp = NULL; cp = NULL;
139:
140: switch(uap->cmd) {
141:
142: case NPGRP:
143: if (vec.m_arg[1] < 0)
144: break;
145: case CHAN:
146: case JOIN:
147: case EXTR:
148: case ATTACH:
149: case DETACH:
150: case CSIG:
151: gfp = getf(vec.m_arg[1]);
152: if (gfp==NULL)
153: return;
154: gip = gfp->f_inode;
155: gp = &gip->i_un.i_group;
156: if (gp->g_inode != gip) {
157: u.u_error = ENXIO;
158: return;
159: }
160: }
161:
162: switch(uap->cmd) {
163:
164: /*
165: * Create an MPX file.
166: */
167:
168: case MPX:
169: case MPXN:
170: if (mpxdev < 0) {
171: for (i=0; linesw[i].l_open; i++) {
172: if (linesw[i].l_read==mcread) {
173: mpxline = i;
174: for (i=0; cdevsw[i].d_open; i++) {
175: if (cdevsw[i].d_open==mxopen) {
176: mpxdev = (dev_t)(i<<8);
177: }
178: }
179: }
180: }
181: if (mpxdev < 0) {
182: u.u_error = ENXIO;
183: return;
184: }
185: }
186: if (uap->cmd==MPXN) {
187: if ((ip=ialloc(pipedev))==NULL)
188: return;
189: ip->i_mode = ((vec.m_arg[1]&0777)+IFMPC) & ~u.u_cmask;
190: ip->i_flag = IACC|IUPD|ICHG;
191: } else {
192: u.u_dirp = vec.m_name;
193: ip = namei(uchar,1);
194: if (ip != NULL) {
195: i = ip->i_mode&IFMT;
196: u.u_error = EEXIST;
197: if (i==IFMPC || i==IFMPB) {
198: i = minor(ip->i_un.i_rdev);
199: gp = groups[i];
200: if (gp && gp->g_inode==ip)
201: u.u_error = EBUSY;
202: }
203: iput(ip);
204: return;
205: }
206: if (u.u_error)
207: return;
208: ip = maknode((vec.m_arg[1]&0777)+IFMPC);
209: if (ip == NULL)
210: return;
211: }
212: if ((i=gpalloc()) < 0) {
213: iput(ip);
214: return;
215: }
216: if ((fp=falloc()) == NULL) {
217: iput(ip);
218: groups[i] = NULL;
219: return;
220: }
221: ip->i_un.i_rdev = (daddr_t)(mpxdev+i);
222: ip->i_count++;
223: prele(ip);
224:
225: gp = &ip->i_un.i_group;
226: groups[i] = gp;
227: gp->g_inode = ip;
228: gp->g_state = INUSE|ISGRP;
229: gp->g_group = NULL;
230: gp->g_file = fp;
231: gp->g_index = 0;
232: gp->g_rotmask = 1;
233: gp->g_rot = 0;
234: gp->g_datq = 0;
235: for(i=0;i<NINDEX;)
236: gp->g_chans[i++] = NULL;
237:
238: fp->f_flag = FREAD|FWRITE|FMP;
239: fp->f_inode = ip;
240: fp->f_un.f_chan = NULL;
241: return;
242:
243: /*
244: * join file descriptor (arg 0) to group (arg 1)
245: * return channel number
246: */
247:
248: case JOIN:
249: if ((fp=getf(vec.m_arg[0]))==NULL)
250: return;
251: ip = fp->f_inode;
252: switch (ip->i_mode & IFMT) {
253:
254: case IFMPC:
255: if ((fp->f_flag&FMP) != FMP) {
256: u.u_error = ENXIO;
257: return;
258: }
259: ngp = &ip->i_un.i_group;
260: if (mtree(ngp, gp) == NULL)
261: return;
262: fp->f_count++;
263: u.u_r.r_val1 = cpx((struct chan *)ngp);
264: return;
265:
266: case IFCHR:
267: dev = (dev_t)ip->i_un.i_rdev;
268: tp = cdevsw[major(dev)].d_ttys;
269: if (tp==NULL) {
270: u.u_error = ENXIO;
271: return;
272: }
273: tp = &tp[minor(dev)];
274: if (tp->t_chan) {
275: u.u_error = ENXIO;
276: return;
277: }
278: if ((cp=addch(gip, 1))==NULL) {
279: u.u_error = ENXIO;
280: return;
281: }
282: tp->t_chan = cp;
283: cp->c_fy = fp;
284: fp->f_count++;
285: cp->c_ttyp = tp;
286: cp->c_line = tp->t_line;
287: cp->c_flags = XGRP+PORT;
288: u.u_r.r_val1 = cpx(cp);
289: return;
290:
291: default:
292: u.u_error = ENXIO;
293: return;
294:
295: }
296:
297: /*
298: * Attach channel (arg 0) to group (arg 1).
299: */
300:
301: case ATTACH:
302: cp = xcp(gp, vec.m_arg[0]);
303: if (cp==NULL || cp->c_flags&ISGRP) {
304: u.u_error = ENXIO;
305: return;
306: }
307: u.u_r.r_val1 = cpx(cp);
308: wakeup((caddr_t)cp);
309: return;
310:
311: case DETACH:
312: cp = xcp(gp, vec.m_arg[0]);
313: if (cp==NULL) {
314: u.u_error = ENXIO;
315: return;
316: }
317: (void) detach(cp);
318: return;
319:
320: /*
321: * Extract channel (arg 0) from group (arg 1).
322: */
323:
324: case EXTR:
325: cp = xcp(gp, vec.m_arg[0]);
326: if (cp==NULL) {
327: u.u_error = ENXIO;
328: return;
329: }
330: if (cp->c_flags & ISGRP) {
331: (void) mxfalloc(((struct group *)cp)->g_file);
332: return;
333: }
334: if ((fp=cp->c_fy) != NULL) {
335: (void) mxfalloc(fp);
336: return;
337: }
338: if ((fp=falloc()) == NULL)
339: return;
340: fp->f_inode = gip;
341: gip->i_count++;
342: fp->f_un.f_chan = cp;
343: fp->f_flag = (vec.m_arg[2]) ?
344: (FREAD|FWRITE|FMPY) : (FREAD|FWRITE|FMPX);
345: cp->c_fy = fp;
346: return;
347:
348: /*
349: * Make new chan on group (arg 1).
350: */
351:
352: case CHAN:
353: if((gfp->f_flag&FMP)==FMP)cp = addch(gip, 0);
354: if(cp == NULL){
355: u.u_error = ENXIO;
356: return;
357: }
358: cp->c_flags = XGRP;
359: cp->c_fy = NULL;
360: cp->c_ttyp = cp->c_ottyp = (struct tty *)cp;
361: cp->c_line = cp->c_oline = mpxline;
362: u.u_r.r_val1 = cpx(cp);
363: return;
364:
365: /*
366: * Connect fd (arg 0) to channel fd (arg 1).
367: * (arg 2 < 0) => fd to chan only
368: * (arg 2 > 0) => chan to fd only
369: * (arg 2 == 0) => both directions
370: */
371:
372: case CONNECT:
373: if ((fp=getf(vec.m_arg[0]))==NULL)
374: return;
375: if ((chfp=getf(vec.m_arg[1]))==NULL)
376: return;
377: ip = fp->f_inode;
378: i = ip->i_mode&IFMT;
379: if (i!=IFCHR) {
380: u.u_error = ENXIO;
381: return;
382: }
383: dev = (dev_t)ip->i_un.i_rdev;
384: tp = cdevsw[major(dev)].d_ttys;
385: if (tp==NULL) {
386: u.u_error = ENXIO;
387: return;
388: }
389: tp = &tp[minor(dev)];
390: if (!(chfp->f_flag&FMPY)) {
391: u.u_error = ENXIO;
392: return;
393: }
394: cp = chfp->f_un.f_chan;
395: if (cp==NULL || cp->c_flags&PORT) {
396: u.u_error = ENXIO;
397: return;
398: }
399: i = vec.m_arg[2];
400: if (i>=0) {
401: cp->c_ottyp = tp;
402: cp->c_oline = tp->t_line;
403: }
404: if (i<=0) {
405: tp->t_chan = cp;
406: cp->c_ttyp = tp;
407: cp->c_line = tp->t_line;
408: }
409: u.u_r.r_val1 = 0;
410: return;
411:
412: case NPGRP: {
413: register struct proc *pp;
414:
415: if (gp != NULL) {
416: cp = xcp(gp, vec.m_arg[0]);
417: if (cp==NULL) {
418: u.u_error = ENXIO;
419: return;
420: }
421: }
422: pp = u.u_procp;
423: pp->p_pgrp = pp->p_pid;
424: if (vec.m_arg[2])
425: pp->p_pgrp = vec.m_arg[2];
426: if (gp != NULL)
427: cp->c_pgrp = pp->p_pgrp;
428: u.u_r.r_val1 = pp->p_pgrp;
429: return;
430: }
431:
432: case CSIG:
433: cp = xcp(gp, vec.m_arg[0]);
434: if (cp==NULL) {
435: u.u_error = ENXIO;
436: return;
437: }
438: gsignal(cp->c_pgrp, vec.m_arg[2]);
439: u.u_r.r_val1 = vec.m_arg[2];
440: return;
441:
442: case DEBUG:
443: i = vec.m_arg[0];
444: if (i<0 || i>NDEBUGS)
445: return;
446: mcdebugs[i] = vec.m_arg[1];
447: if (i==ALL)
448: for(i=0;i<NDEBUGS;i++)
449: mcdebugs[i] = vec.m_arg[1];
450: return;
451:
452: default:
453: u.u_error = ENXIO;
454: return;
455: }
456:
457: }
458: detach(cp)
459: register struct chan *cp;
460: {
461: register struct group *master,*sub;
462: register index;
463:
464: if (cp==NULL)
465: return(0);
466: if (cp->c_flags&ISGRP) {
467: sub = (struct group *)cp;
468: master = sub->g_group; index = sub->g_index;
469: closef(sub->g_file);
470: if (master != NULL)
471: master->g_chans[index] = NULL;
472: return(0);
473: } else if (cp->c_flags&PORT && cp->c_ttyp != NULL) {
474: closef(cp->c_fy);
475: chdrain(cp);
476: chfree(cp);
477: return(0);
478: }
479: if (cp->c_flags & WCLOSE) {
480: if (cp->c_fy) {
481: if (cp->c_fy->f_count)
482: return(1);
483: chdrain(cp);
484: chfree(cp);
485: return(0);
486: }
487: }
488: cp->c_flags |= WCLOSE;
489: chwake(cp);
490: return(1);
491: }
492:
493:
494: mxfalloc(fp)
495: register struct file *fp;
496: {
497: register i;
498:
499: if (fp==NULL) {
500: u.u_error = ENXIO;
501: return(-1);
502: }
503: i = ufalloc();
504: if (i < 0)
505: return(i);
506: u.u_ofile[i] = fp;
507: fp->f_count++;
508: u.u_r.r_val1 = i;
509: return(i);
510: }
511:
512: /*
513: * Grow a branch on a tree.
514: */
515:
516: mtree(sub,master)
517: register struct group *sub, *master;
518: {
519: register i;
520: int mtresiz, stresiz;
521:
522: if ((mtresiz=mup(master,sub)) == NULL) {
523: u.u_error = ENXIO;
524: return(NULL);
525: }
526: if ((stresiz=mdown(sub,master)) <= 0) {
527: u.u_error = ENXIO;
528: return(NULL);
529: }
530: if (sub->g_group != NULL) {
531: u.u_error = ENXIO;
532: return(NULL);
533: }
534: if (stresiz+mtresiz > NLEVELS) {
535: u.u_error = ENXIO;
536: return(NULL);
537: }
538: for (i=0;i<NINDEX;i++) {
539: if (master->g_chans[i] != NULL)
540: continue;
541: master->g_chans[i] = (struct chan *)sub;
542: sub->g_group = master;
543: sub->g_index = i;
544: return(1);
545: }
546: u.u_error = ENXIO;
547: return(NULL);
548: }
549:
550: mup(master,sub)
551: struct group *master, *sub;
552: {
553: register struct group *top;
554: register int depth;
555:
556: depth = 1; top = master;
557: while (top->g_group) {
558: depth++;
559: top = top->g_group;
560: }
561: if(top == sub)
562: return(NULL);
563: return(depth);
564: }
565:
566:
567: mdown(sub,master)
568: struct group *sub, *master;
569: {
570: register int maxdepth, i, depth;
571:
572: if(sub == (struct group *)NULL || (sub->g_state&ISGRP) == 0)
573: return(0);
574: if(sub == master)
575: return(-1);
576: maxdepth = 0;
577: for(i=0; i<NINDEX; i++) {
578: if((depth=mdown((struct group *)sub->g_chans[i],master)) == -1)
579: return(-1);
580: maxdepth = (depth>maxdepth) ? depth: maxdepth;
581: }
582: return(maxdepth+1);
583: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.