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