|
|
1.1 root 1: #define MUXTERM
2: #define MPXTERM
3:
4: #include "dmd.h"
5: #include "font.h"
6: #include "menu.h"
7: #include "defs.h"
8:
9: #undef getname /* strange hack to avoid name clash */
10:
11: /* user nice sys queue idle */
12:
13: Texture16 black={
14: 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
15: 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
16: };
17: Texture16 white={
18: 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
19: 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
20: };
21: Texture16 darkgrey = {
22: 0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777,
23: 0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777,
24: };
25: Texture16 lightgrey = {
26: 0x2222, 0x8888, 0x2222, 0x8888, 0x2222, 0x8888, 0x2222, 0x8888,
27: 0x2222, 0x8888, 0x2222, 0x8888, 0x2222, 0x8888, 0x2222, 0x8888,
28: };
29: Texture16 grey = {
30: 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555,
31: 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555,
32: };
33:
34: Texture16 *txt[]={
35: &black, &lightgrey, &darkgrey, &grey, &white
36: };
37:
38: # define TIMELEN 6
39: char time[TIMELEN];
40: # define NAMELEN 9
41: # define LOADLEN 13
42: # define MAILLEN 18
43:
44: struct nodedef {
45: Rectangle bar; /* the bar graph of system use */
46: char name[NAMELEN]; /* node name */
47: char load[LOADLEN]; /* load numbers */
48: int vec[5]; /* current use vectors */
49: int oldvec[5]; /* old use vectors */
50: char mail[MAILLEN]; /* last mail from this node */
51: };
52: struct nodedef node0; /* preallocate node 0 */
53: int nodes = 0; /* number of nodes */
54: struct nodedef *node[MAXMACHS] = {
55: &node0
56: };
57:
58: /* size contraints */
59: #define ICONSEP 2
60: #define BARHEIGHT 18
61: #define MINBARHEIGHT 4
62: #define MAXBARHEIGHT 24
63: #define TIMEORIGIN 2
64: int CHARHEIGHT;
65: int CHARWIDTH;
66: int TIMECORNER;
67: int LOADORIGIN;
68: int LOADCORNER;
69: int MAILORIGIN;
70: int MAILCORNER;
71:
72: int size;
73: int barheight;
74: int iconorigin;
75:
76: /* the communications process */
77: struct Proc *cwp;
78:
79: /* icon info */
80: #define ICONSIZE 48
81: #define ICONWORDS (ICONSIZE*(ICONSIZE/16))
82: Bitmap *icon, *ticon;
83: int icons = 0;
84: int maxicons;
85: int haveicons = 0;
86:
87: /* dynamically add/remove monitored systems */
88:
89: static NMitem astroitems[] = {
90: "alice",
91: "arend",
92: "bowell",
93: "coma",
94: "crab",
95: "dutoit",
96: "encke",
97: "kwee",
98: "panther",
99: "pipe",
100: "r70",
101: "research",
102: "seki",
103: "spit",
104: "swift",
105: "west",
106: "westphal",
107: "wild",
108: 0
109: };
110:
111: static NMenu astromenu = {astroitems};
112:
113: static NMitem phoneitems[] = {
114: {"atomic"},
115: {"fry"},
116: {"gauss"},
117: {"shannon"},
118: {"sid"},
119: {0}
120: };
121:
122: static NMenu phonemenu = {phoneitems};
123:
124: static NMitem mercuryitems[] = {
125: {"arachne"},
126: {"balin"},
127: {"bashful"},
128: {"bifur"},
129: {"capek"},
130: {"doc"},
131: {"eeyore"},
132: {"gimli"},
133: {"grumpy"},
134: {"gunn"},
135: {"happy"},
136: {"hunny"},
137: {"icarus"},
138: {"indra"},
139: {"iota"},
140: {"jones"},
141: {"kanga"},
142: {"sapir"},
143: {"siriusb"},
144: {"sola"},
145: {"sweet"},
146: {"thorin"},
147: {0}
148: };
149:
150: static NMenu mercurymenu = {mercuryitems};
151:
152: static NMitem machitems[] = {
153: {"ca/xunet/fs"},
154: {"nj/astro", 0, &astromenu},
155: {"nj/garage/europa"},
156: {"nj/mercury", 0, &mercurymenu},
157: {"nj/phone", 0, &phonemenu},
158: {"nj/vlsi/araki"},
159: {"pa/ram/most"},
160: {0}
161: };
162:
163: NMenu nmenu2 = {machitems};
164:
165: static struct {
166: char *name;
167: NMitem *base, *lim;
168: } menulist[] = {
169: {"nj/astro/", astroitems, astroitems+sizeof(astroitems)/(sizeof(NMitem))-1},
170: {"nj/mercury/", mercuryitems, mercuryitems+sizeof(mercuryitems)/(sizeof(NMitem))-1},
171: {"nj/phone/", phoneitems, phoneitems+sizeof(phoneitems)/(sizeof(NMitem))-1},
172: {0}
173: };
174:
175:
176: main()
177: {
178: register i, state, hadmouse;
179:
180:
181: request(RCV|MOUSE|KBD);
182:
183: CHARHEIGHT = defont.height - 2;
184: CHARWIDTH = strwidth(&defont, "m");
185: TIMECORNER = NAMELEN*CHARWIDTH;
186: LOADORIGIN = TIMECORNER;
187: LOADCORNER = TIMECORNER + LOADLEN*CHARWIDTH;
188: MAILORIGIN = LOADCORNER;
189: MAILCORNER = LOADCORNER + MAILLEN*CHARWIDTH;
190: barheight = MAXBARHEIGHT;
191: iconorigin = MAILCORNER;
192: time[0] = 0;
193: hadmouse = 0;
194:
195: for(;;sleep(3)){
196: if (cwp != 0 && cwp->state == 0)
197: cwp = 0;
198: state = own();
199: if(state&RCV)
200: get();
201: if(state&MOUSE) {
202: if(button2()) {
203: domenu();
204: } else if(button3()) {
205: request(RCV|KBD);
206: sleep(1);
207: request(RCV|KBD|MOUSE);
208: } else if (!hadmouse || button1()) {
209: clearmail();
210: clearicon();
211: }
212: }
213: hadmouse = state&MOUSE;
214: if(state&KBD) {
215: while(kbdchar() != -1) /* dump any keyboard input */
216: ;
217: }
218: for (i = 0; i < nodes; i++)
219: drawbar (node[i]);
220: if(P->state&RESHAPED)
221: reshape(0);
222: }
223: }
224:
225: reshape(msg)
226: char *msg;
227: {
228: register int i;
229:
230: P->state&=~RESHAPED;
231: rectf(&display, Drect, F_CLR);
232:
233: /* output an error message */
234: if (msg != 0) {
235: string(&defont, msg, &display,
236: Pt (Drect.origin.x+2, Drect.origin.y + 2), F_XOR);
237: sleep(200);
238: rectf(&display, Drect, F_CLR);
239: }
240:
241: /* resize objects */
242: size = Drect.corner.x-Drect.origin.x;
243: barheight = (Drect.corner.y-Drect.origin.y-2)/(nodes?nodes:1) - CHARHEIGHT;
244: if (barheight < MINBARHEIGHT)
245: barheight = MINBARHEIGHT;
246: if (haveicons) {
247: if (barheight > MAXBARHEIGHT)
248: barheight = MAXBARHEIGHT;
249: i = 3*size/4;
250: size = (i > MAILCORNER) ? MAILCORNER
251: : ((i > LOADCORNER) ? LOADCORNER
252: : TIMECORNER);
253: iconorigin = size;
254: maxicons = (Drect.corner.x-Drect.origin.x-iconorigin)
255: / (ICONSIZE+ICONSEP);
256: }
257:
258: /* redraw */
259: for (i = 0; i < nodes; i++) {
260: nodeinit(i);
261: drawload(node[i]);
262: drawmail(node[i]);
263: };
264: drawtime();
265: clearmail();
266: clearicon();
267: }
268:
269:
270: /* clear out the bar and write in the node name */
271: nodeinit (ind)
272: int ind; /* index into node array */
273: {
274: register struct nodedef *n;
275: register int i;
276:
277: n = node[ind];
278:
279: /* make the bar */
280: n->bar.origin.x = Drect.origin.x;
281: n->bar.origin.y = Drect.origin.y + ind*(barheight+CHARHEIGHT);
282: n->bar.corner.x = Drect.origin.x + size;
283: n->bar.corner.y = n->bar.origin.y + barheight;
284: n->bar = inset(n->bar, 4);
285: rectf(&display, inset(n->bar, -2), F_OR);
286: rectf(&display, n->bar, F_CLR);
287:
288: /* init the node */
289: for(i = 0; i<4; i++)
290: n->vec[i] = n->oldvec[i] = 0;
291: n->vec[4]=n->oldvec[4]=size;
292:
293: /* write the name */
294: if (ind != 0 && size >= TIMECORNER)
295: string (&defont, n->name, &display,
296: Pt(TIMEORIGIN+Drect.origin.x, n->bar.origin.y+barheight-6),
297: F_XOR);
298: };
299:
300: domenu() {
301: NMitem *mhit(), *sys;
302: char name[48];
303:
304: sys = mhit(&nmenu2, 2, 0);
305: if (sys) {
306: register int i;
307: strcpy(name, "M");
308: for (i = 0; menulist[i].name; i++) {
309: if (sys >= menulist[i].base && sys < menulist[i].lim) {
310: strcat (name, menulist[i].name);
311: break;
312: }
313: }
314: strcat(name, sys->text);
315: strcat(name, "\n");
316: if (index (name, '/'))
317: sendnchars(strlen(name), name);
318: }
319: }
320:
321:
322: Point pt[4];
323: Rectangle new, old;
324:
325: /* draw the bar graph for a system's CPU time */
326: drawbar (n)
327: struct nodedef *n;
328: {
329: register i, now;
330:
331: pt[0].y = pt[2].y = n->bar.origin.y;
332: pt[1].y = pt[3].y = n->bar.corner.y;
333: new = old = n->bar;
334: for(i=0; i<5; i++){
335: now = relax(n->oldvec[i], n->vec[i]);
336: old.corner.x = n->oldvec[i] + old.origin.x;
337: new.corner.x = now+new.origin.x;
338: sort(old.origin.x,old.corner.x, new.origin.x,new.corner.x);
339: if (pt[3].x > n->bar.corner.x)
340: pt[3].x = n->bar.corner.x;
341: if (pt[1].x > n->bar.corner.x)
342: pt[1].x = n->bar.corner.x;
343: texture(&display, Rpt(pt[0], pt[1]), txt[i], F_XOR);
344: texture(&display, Rpt(pt[2], pt[3]), txt[i], F_XOR);
345: new.origin.x = new.corner.x;
346: old.origin.x = old.corner.x;
347: n->oldvec[i] = now;
348: }
349: }
350:
351: relax(o, n)
352: int o, n;
353: {
354: register a;
355: register s=1;
356: register long lo = o;
357: register long ln = n;
358:
359: if(o>n)
360: s= -1;
361: a=abs(o-n);
362: if(a<2)
363: return n;
364: if(a<127)
365: return o+s;
366: ln = (127L*lo + ln) / 128L;
367: s = ln;
368:
369: return s;
370: }
371:
372: sort(x)
373: int x;
374: {
375: register int *p= &x;
376: register i,j;
377: register t;
378: for(i=0; i<3; i++){
379: for(j=0; j<3; j++)
380: if(p[j]>p[j+1]){
381: t=p[j];
382: p[j]=p[j+1];
383: p[j+1]=t;
384: }
385: }
386: for(i=0; i<4; i++)
387: pt[i].x=p[i];
388: }
389:
390: drawload(n)
391: struct nodedef *n;
392: {
393: if (size < LOADCORNER)
394: return;
395: string(&defont, n->load, &display,
396: Pt (Drect.origin.x+LOADORIGIN, n->bar.origin.y+barheight-6), F_XOR);
397: }
398:
399: drawtime()
400: {
401: if (size < TIMECORNER)
402: return;
403: string(&defont, time, &display,
404: Pt (Drect.origin.x+TIMEORIGIN, Drect.origin.y+barheight-2), F_XOR);
405: }
406:
407: drawmail(n)
408: struct nodedef *n;
409: {
410: if (size < MAILCORNER)
411: return;
412: string(&defont, n->mail, &display,
413: Pt (Drect.origin.x+MAILORIGIN, n->bar.origin.y+barheight-6), F_XOR);
414: }
415:
416: clearmail()
417: {
418: register int i;
419:
420: for (i = 0; i < nodes; i++) {
421: drawmail(node[i]);
422: node[i]->mail[0] = '\0';
423: }
424: }
425:
426: drawicon()
427: {
428: Rectangle rect;
429: Point to;
430: int bltwidth, i;
431:
432: if (!haveicons || maxicons < 1)
433: return;
434:
435: /* move icons right */
436: bltwidth = (maxicons-1)*(ICONSIZE+ICONSEP) - ICONSEP;
437: rect.origin.x = Drect.origin.x + iconorigin;
438: rect.origin.y = Drect.origin.y + 2;
439: rect.corner.x = rect.origin.x + bltwidth;
440: rect.corner.y = rect.origin.y + ICONSIZE + 4 + CHARHEIGHT;
441: to.x = rect.origin.x + ICONSIZE + ICONSEP;
442: to.y = rect.origin.y;
443: bitblt(&display, rect, &display, to, F_STORE);
444:
445: if (icons != maxicons)
446: icons++;
447:
448: /* clear area */
449: rect.corner.x = to.x;
450: rectf(&display, rect, F_CLR);
451:
452: /* drop in new picture */
453: to = rect.origin;
454: rect = icon->rect;
455: rect.origin.x += ICONSIZE/2;
456: rect.origin.y += ICONSIZE/2;
457: rect.corner.x -= ICONSIZE/2;
458: rect.corner.y -= ICONSIZE/2;
459: to.x += ICONSIZE/2;
460: to.y += ICONSIZE/2;
461: for (i=0; i<ICONSIZE/2; i++){
462: rect.origin.x--;
463: rect.origin.y--;
464: rect.corner.x++;
465: rect.corner.y++;
466: to.x--;
467: to.y--;
468: bitblt(icon, rect, &display, to, F_STORE);
469: sleep(2);
470: }
471:
472: /* add a time stamp */
473: to.y += ICONSIZE + 4;
474: string(&defont, time, &display, to, F_XOR);
475: }
476:
477: clearicon()
478: {
479: Rectangle rect;
480:
481: if (!haveicons || maxicons < 1 || icons == 0)
482: return;
483: icons = 0;
484: rect.origin.x = Drect.origin.x + iconorigin - 1;
485: rect.origin.y = Drect.origin.y + 1;
486: rect.corner.x = rect.origin.x + maxicons*(ICONSIZE+ICONSEP) - ICONSEP + 2;
487: rect.corner.y = rect.origin.y + ICONSIZE + CHARHEIGHT + 6;
488: rectf(&display, rect, F_CLR);
489: }
490:
491: /* process a host message */
492: get(){
493: register int ch;
494: register struct nodedef *n;
495: struct nodedef *nodeptr();
496:
497: ch = hostchar();
498: if (ch == MAGIC_CH) {
499:
500: /* this is probably a message from the host half of sysmon */
501: ch = hostchar();
502: switch(ch){
503: case 'V':
504: while ((ch = hostchar()) != -1) {
505: n = nodeptr(ch);
506: getvec(n);
507: }
508: break;
509: case 'L':
510: while ((ch = hostchar()) != -1) {
511: n = nodeptr(ch);
512: drawload(n);
513: getload(n);
514: drawload(n);
515: }
516: break;
517: case 'T':
518: drawtime();
519: gettime();
520: drawtime();
521: break;
522: case 'M':
523: n = nodeptr(hostchar());
524: drawmail(n);
525: getmail(n);
526: drawmail(n);
527: break;
528: case 'I':
529: geticon();
530: drawicon();
531: break;
532: case 'N':
533: getname();
534: reshape(0);
535: break;
536: case 'Q':
537: icon = balloc(Rect(0, 0, ICONSIZE, ICONSIZE));
538: ticon = balloc(Rect(0, 0, ICONSIZE, ICONSIZE));
539: if (!icon || !ticon) {
540: reshape("Not enough memory for faces.");
541: sendnchars(2, "R\n"); /* refuse faces */
542: break;
543: }
544: sendnchars(2, "A\n"); /* accept faces */
545: haveicons = 1;
546: reshape(0);
547: break;
548: case 'R':
549: remove(hostchar()-'0');
550: reshape(0);
551: break;
552: case -1:
553: return;
554: default:
555: writecw(ch);
556: break;
557: }
558: } else {
559: writecw(ch);
560: }
561: ignorerest();
562: }
563:
564: struct nodedef *
565: nodeptr(c)
566: int c;
567: {
568: register i;
569:
570: i = c - '0';
571: if (i < 0 || i >= nodes)
572: i = 0;
573: return node[i];
574: }
575:
576: getvec(n)
577: struct nodedef *n;
578: {
579: register int i, sum, nsum, vec[5];
580:
581: for(sum=0,i=0; i<5; i++)
582: sum += (vec[i] = hostchar());
583: sum = sum ? sum : 1;
584: for(nsum=0,i=0; i<4; i++)
585: nsum += n->vec[i] = ((long)(vec[i])*size) / sum;
586: n->vec[4]=size-nsum;
587: }
588:
589: gettime()
590: {
591: register char *p=time;
592: register int c, i=0;
593:
594: while((c = hostchar()) != -1 && ++i < TIMELEN)
595: *p++ = c;
596: *p=0;
597: }
598:
599: getload(n)
600: struct nodedef *n;
601: {
602: register char *p=n->load;
603: register int i=0;
604:
605: while((*p = hostchar()) != '\t' && ++i < LOADLEN)
606: p++;
607: *p=0;
608: }
609:
610: getname()
611: {
612: register char *p;
613: register int c, i=0;
614:
615: if (nodes != 0) {
616: node[nodes] = (struct nodedef *)alloc(sizeof (struct nodedef));
617: if (!node[nodes]) {
618: reshape("out of memory");
619: sendnchars(2, "R\n"); /* refuse connection */
620: return;
621: }
622: }
623: sendnchars(2, "A\n"); /* accept connection */
624: p = node[nodes]->name;
625: while((c = hostchar()) != -1 && ++i < NAMELEN)
626: *p++ = c;
627: *p=0;
628: nodes++;
629: }
630:
631: remove(ind)
632: register int ind;
633: {
634: if (ind < 0 || ind >= nodes)
635: return;
636: free (node[ind]);
637: for (; ind < nodes-1; ind++)
638: node[ind] = node[ind+1];
639: nodes--;
640: }
641:
642: getmail(n)
643: struct nodedef *n;
644: {
645: register char *p=n->mail;
646: register int c, i=0;
647:
648: while((c = hostchar()) != -1 && ++i < MAILLEN)
649: *p++ = c;
650: upfront(P->layer);
651: ringbell ();
652: *p=0;
653: }
654:
655: geticon()
656: {
657: register int c, i, j;
658: register short *ip;
659:
660: /* once per scan line */
661: ip = (short *)icon->base;
662: for (i = 0; i < ICONSIZE; i++) {
663:
664: /* once per short */
665: for (j = 0; j < ICONSIZE/16; j++) {
666: c = hostchar();
667: *ip = (c<<8) | hostchar();
668: #ifndef mc68000
669: if (VALSCREENCOLOR==0)
670: *ip = ~*ip;
671: #endif mc68000
672: ip++;
673: }
674:
675: #ifndef mc68000
676: /* blit and 5620 have different size bitmaps */
677: ip++;
678: #endif mc68000
679: }
680: }
681:
682: int atend = 0; /* non-zero if at end of message */
683:
684: hostchar(){
685: register int c;
686:
687: if (atend)
688: return -1;
689:
690: if((c=rcvchar())==-1)
691: wait(RCV), c=rcvchar();
692:
693: if (c == '\n') {
694:
695: /* newline's mark end of message */
696: atend = 1;
697: return -1;
698: } else if (c == '\\') {
699:
700: /* backslashes are character escapes */
701: if ((c=rcvchar())==-1)
702: wait(RCV), c=rcvchar();
703: }
704:
705: return c&0xff;
706: }
707:
708: ignorerest()
709: {
710: while (hostchar() != -1)
711: ;
712: atend = 0;
713: }
714:
715:
716: #ifdef mc68000
717: ringbell ()
718: {
719: *((char *)(384*1024L+062)) = 2;
720: }
721: #endif mc68000
722:
723: /*
724: * The rest of jerqmon.c contains routines to create and update the
725: * communications window.
726: */
727: #define INSET 4
728: #define C_NEW 2
729:
730: makecw()
731: {
732: register Rectangle r;
733: register unsigned char *pout;
734:
735: /* first see if the process already exists */
736: if (cwp != 0 && cwp->state != 0)
737: return 0;
738: else
739: cwp = 0;
740:
741: /* create process */
742: r = Drect;
743: if(!(cwp=newproc((struct Proc *)0)))
744: return -1;
745: cwp->rect=inset(r, INSET);
746: if( !rectclip(&cwp->rect,Jrect) || !(cwp->layer=newlayer(r))){
747: cwp->state=0;
748: return -1;
749: }
750:
751: /* give it a window */
752: #ifndef mc68000
753: muxnewwind(cwp, C_NEW);
754: #else
755: mpxnewwind(cwp, C_NEW);
756: #endif mc68000
757:
758: /* wait for a prompt */
759: pout = cwp->cbufpout;
760: do sleep( 60 ); while( pout == cwp->cbufpout );
761: ringbell();
762:
763: return 0;
764: }
765:
766: /*
767: * Write a string to the communications window. Create the
768: * window if it has disappeared.
769: */
770: writecw(c)
771: register int c;
772: {
773: if (makecw() < 0) {
774: drawmail(node[0]);
775: getmail(node[0], "can't open comm window\n");
776: drawmail(node[0]);
777: return;
778: }
779: do {
780: if (cwp->state) {
781: upfront(cwp->layer);
782: while (cwp->nchars < CBSIZE*3) {
783: *(cwp->cbufpin++) = c != -1 ? c : '\n';
784: cwp->nchars++;
785: if (cwp->cbufpin >= &(cwp->cbuf[CBSIZE*3]))
786: cwp->cbufpin = cwp->cbuf;
787: if (c == -1)
788: break;
789: c = hostchar();
790: }
791: cwp->state |= WAKEUP;
792: sleep (10);
793: } else
794: return;
795: } while (c != -1);
796: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.