|
|
1.1 root 1: /* EMACS_MODES: c !fill */
2:
3: /* Expand global variables here */
4:
5: #define OWNER 1
6:
7: #include <sys/types.h>
8: #include <sys/stat.h>
9: #include <signal.h>
10: #include <setjmp.h>
11: #include "emacs_io.h"
12: #include "emacs_gb.h"
13: #include "emacs_main.h"
14:
15: #ifdef ux3
16: #include <fcntl.h>
17: #endif
18:
19: /* screen editor for unix */
20:
21:
22:
23: /* Main Loop */
24:
25: /* interprets characters, setting arguments and meta. When a
26: * 'virtual character' is entered, it is executed via the do_it array */
27:
28: char *cprompt[2] = {"M-","^X"};
29:
30:
31: /* VARARGS */
32:
33: edit(edisp,echar,earg)
34:
35: int edisp; /* disposition flag */
36: int echar; /* optional character for disp = 2*/
37: int earg; /* optional argument for disp = 3*/
38: {
39: register int c; /* virtual character being interpreted */
40:
41: register int realc; /* last real character read */
42: int metf;
43: int dochar;
44: register int arg;
45: int eresult; /* result of last command */
46:
47: /* Keywords: user-interface argument-processing:40 macro-programming:30 */
48: /* Keywords: key-bindings:30 display-update:5 */
49:
50: #ifdef pdp11
51: #define BUFMAX 077000 /* Buffer file size at which to GC */
52: #else
53: #define BUFMAX 0777000 /* Bigger for VAX, since not constrainted by address space */
54: #endif
55:
56: for (;;) {
57: arg = 1;
58: metf = 0;
59: numarg = 0;
60: if (BUFEND > BUFMAX) collect(); /* garbage collection */
61: if (edisp == 2) { /* execute command */
62: if ((echar < 0) || (echar > 0600)) echar = CTRLG;
63: c = echar;
64: arg = earg;
65: edisp = 0; /* do one command */
66: goto dispose;
67: }
68:
69: re_get:
70: if (infrn >= 0) {
71:
72: if (SAVEMD) {
73: if (NSCHAR++>SAVECHAR) {
74: IGNORE(fsave(0));
75: NSCHAR=0;
76: }
77: }
78: if (etrace == 0) disup(); /* update display */
79: if ((VERBOSE) && (MOREIN == 0) && ((numarg) || (metf))){
80: if (metf) {
81: if (numarg) {
82: if (numarg == 8) prompt1("%o %s: ",arg,cprompt[metf>>8]);
83: else prompt1("%d %s: ",arg,cprompt[metf>>8]);
84: } else {
85: prompt1("%s: ",cprompt[metf>>8]);
86: }
87: } else {
88: if (numarg == 8) prompt1 ("%o: ", arg);
89: else prompt1("%d: ", arg);
90: }
91: c = (getchar()) + metf;
92: unprompt();
93: } else c = (getchar()) + metf;
94: #ifdef CMON
95: if (infrn == 0) cmcnt[c]++; /* count command statistics */
96: #endif
97: dochar = map_it[c];
98: } else {
99:
100: /* The following code for macros bypasses the normal getchar for speed! */
101:
102: c = metf + Mgetchar();
103:
104: dispose: /* dispose of character command */
105: dochar = doit[c];
106: if (dochar == 0) { /* no default binding, check for macro */
107: dochar = map_it[c];
108: if (dochar < ISIZE) dochar = 0; /* Only for macros */
109: }
110: }
111:
112:
113: if (dochar >= ISIZE) {
114: eresult = xmac(dochar-ISIZE,arg,c);
115: } else if (dochar >= NIFUNC) {
116: eresult = (*runit[dochar-NIFUNC]) (arg,c);
117: } else {
118: metf = c & META;
119: realc = c & META-1; /* set up real character and meta flags; */
120: switch(dochar) {
121:
122: case CMETA:
123: metf=META;
124: goto re_get;
125: case CCTLX:
126: metf = CTLX;
127: goto re_get;
128: case CEXIT:
129: return(arg);
130: case CLRES:
131: arg = eresult;
132: numarg = 10;
133: goto re_get;
134: case CCTLU:
135: arg *= 4;
136: if (numarg == 0) numarg = 1;
137: goto re_get;
138: case CMARG:
139: if ((arg >= 0) && (arg < NMVAR) && (marg != NULL)) {
140: arg = marg[arg];
141: numarg = 10;
142: }
143: goto re_get;
144: case CMNUS:
145: if ((numarg == 1) || (metf && (numarg == 0))) {
146: arg = -1;
147: metf = 0;
148: numarg = -1;
149: goto re_get;
150: }
151: eresult = insertc(arg,c);
152: break; /* other minus's insert */
153: case CNUMB:
154: if (metf || numarg) {
155: metf = 0;
156: if (numarg>1) {
157: arg = arg*numarg+realc-'0';
158: if (arg < 0) arg -= 2*(realc-'0');
159: } else {
160: arg = realc-'0';
161: if (numarg < 0) {
162: arg = -arg;
163: }
164: numarg = (realc == '0') ? 8:10;
165: }
166: goto re_get;
167: }
168: eresult = insertc(arg,c);
169: break; /* some numbers self insert */
170: case CBEEP: beep();
171: }
172:
173: }
174: if (etrace) {
175: int tc;
176:
177: if (c & 0400) {
178: putout ("^X%c %d %d",c-0400,arg,eresult);
179: } else {
180: putout ("%c %d %d",c,arg,eresult);
181: }
182: mflush(stdout); /* Force output! */
183: read(0,&tc,1); /* pause */
184: switch(tc&0177) {
185:
186: case 'e':
187: etrace = 0;
188: recurse(1); /* Recursively edit */
189: etrace = 1;
190: break;
191: case '?':
192: {
193: char hbuf[128];
194:
195: helpin(c,hbuf);
196: putout(hbuf);
197: break;
198: }
199:
200: case CTRLG:
201: case CTRLZ:
202: return(eresult); /* Bomb out of here */
203: }
204: }
205: if (edisp == 0) return(eresult);
206: }
207: }
208:
209: trce()
210: {
211: /* Keywords: commands macro-programming */
212:
213: mtop();
214: putout("Command Argument Result");
215: etrace = 1;
216: edit(0);
217: etrace = 0;
218: }
219:
220: /* issrch - is character a search invocation */
221:
222: /* returns 1 for ^S, -1 for ^R, and 0 for others */
223:
224: issrch(chr)
225: int chr;
226:
227: {
228: /* Keywords: searching key-bindings */
229:
230: if (map_it[chr] == 27) return(1);
231: if (map_it[chr] == 26) return(-1);
232: return(0);
233: }
234: isquote(chr)
235: int chr;
236: {
237: /* Keywords: key-bindings quoting */
238: if (map_it[chr] == 25) return(1);
239: return(0);
240: }
241:
242: /* xqt -- execute a command through argument 0. */
243:
244: /* the character command designated by macro argument 0 is run with the */
245: /* current argument */
246:
247: xqt(arg)
248:
249: int arg;
250: {
251: /* Keywords: commands macro-programming:40 */
252:
253: int res;
254: if (marg == NULL) return(0);
255: pushin(NULL); /* if command needs input, from tty */
256: res = edit(2,marg[0],arg); /* run command */
257: inpop();
258: return(res);
259: }
260: /* ckmail -- check for user mail */
261:
262: ckmail()
263: {
264: /* Keywords: user-interface:50 mail-processing unix-interface */
265:
266: extern int CKMAIL;
267: #ifndef PC
268: register char *cp;
269: struct stat statb;
270: static time_t mailtime;
271:
272:
273: if (cp = getenv("MAIL")) {
274: if ((stat(cp,&statb)>=0) && (statb.st_size>30) ) {
275: if (statb.st_mtime != mailtime) {
276: newmail = -1;
277: mailtime = statb.st_mtime;
278: } else {
279: newmail = 1;
280: }
281: } else {
282: if (newmail) disptime = 1; /* Force redisplay of mail/time line */
283: newmail = 0;
284: }
285: }
286: #endif
287: mailcnt = CKMAIL;
288: }
289:
290:
291: /* dtime -- display the time on the screen */
292:
293: long clock;
294:
295: dtime(flag)
296:
297: int flag;
298: {
299: /* Keywords: user-interface:50 time-processing unix-interface */
300:
301: #ifndef PC
302: register char *tp;
303:
304:
305:
306: if (timemd) {
307: time(&clock); /* get time */
308: if ((clock-oclock > 60) || flag) {
309: tp = ctime(&clock); /* convert */
310: tp[16] = 0; /* wipe out newline */
311: disptime = 1;
312: }
313: }
314: #endif PC
315: }
316:
317: /* break interrupt handler */
318:
319: bkfg()
320: {
321: /* Keywords: break-handling unix-interface user-interface:10 */
322:
323: signal(SIGINT,bkfg);
324: #ifdef bsd
325: dclear(); /* Berkeley flushes tty output on break */
326: #endif
327: brkflg++; /* just flag what happened */
328: }
329:
330:
331:
332: /* init -- initialize editor data */
333:
334: /* initializes EMACS, goes into raw mode, creates the buffer main, and
335: * reads in the file specified by the argument to the emacs command */
336:
337:
338: init()
339:
340: {
341: register int i;
342:
343: /* Keywords: unix-interface internal-initialization filenames:10 */
344:
345: procbuf = -1; /* Initialize global */
346: uncook();
347: for (i = 0; i < 16; i++) signal(i,eabort); /* trap various problems */
348:
349: /* some signals cause attempt to save */
350:
351: signal (SIGTERM,crash);
352: signal (SIGHUP,crash);
353: signal (SIGINT,bkfg);
354: signal (SIGPIPE,SIG_IGN);
355: for (i = 0; i < 128; i++) casem[i] = i; /* search map */
356: ioinit();
357: curln = 1;
358: column = 0;
359: IGNORE(chgbuf("Main"));
360:
361: /* The following must take place after I/O is initialized and the
362: * terminal is in raw mode but before any initializations that
363: * use the emacs home directory */
364:
365: strcpy(em_dir,expenv(emd_source)); /* expand emacs home directory */
366: }
367: brkit() /* break interrupt handler */
368: {
369: int res;
370: /* Keywords: unix-interface break-handling user-interface:50 */
371:
372: brkflg=0;
373: bkagain:res = error(WARN,74); /* BREAK!! */
374:
375: if (res > 0) return;
376:
377: if (res == 0) {
378: /* recursive edit time */
379: recurse(1); /* Hope that this works out OK */
380: goto bkagain;
381: }
382:
383: marg=NULL; /* wipe out macro backtrace */
384: myname = svname; /* save name */
385: longjmp(retjmp,1); /* EXIT!!! */
386: }
387:
388: main(argc, argv)
389:
390: int argc;
391: char *argv [];
392:
393: {
394: char itbuf[128];
395: #ifdef DIRED
396: extern int LNOMOD;
397: extern int FILLMD;
398: extern int OVERW;
399: extern int NODEL;
400: #endif
401: extern int fbkno, macptr;
402: int line;
403: register char *ap;
404: char *cp;
405: int tset;
406:
407: #ifdef MONITOR
408:
409: #define MONSIZ 5000
410: short monbuf[MONSIZ];
411: extern int etext;
412:
413: monitor(2,&etext,monbuf,MONSIZ,0); /* profile on */
414: #endif
415:
416: /* Keywords: command-line-processing:90 user-interface:10 */
417: /* Keywords: internal-initialization terminal-initialization:30 */
418: /* Keywords: dired:20 */
419:
420: /* find our name */
421:
422: #ifdef PC
423: myname = "PC EMACS";
424: #else
425: for (ap= myname = argv[0]; *ap; ap++) {
426: if (*ap>0140) *ap = (*ap) - 040;
427: if (*ap == '/') myname = ap+1; /* Seek to last '/' */
428: }
429: #endif PC
430: svname=myname; /* save myname */
431:
432: NPTRS = 0; /* no memory */
433:
434:
435: /* special initialization for DIRED */
436:
437: #ifdef DIRED
438:
439: #define CTX(xchar) ((xchar)+0400)
440:
441: LNOMOD = 0;
442: FILLMD = 0;
443: OVERW = 1;
444: NODEL = 1;
445:
446: doit['d'] = doit['D'] = 81;
447: doit[CTRLD] = doit[CTRLK] = doit[RUBOUT] =80;
448: doit['u'] = doit['U'] = 82;
449: doit['e'] = doit['E'] = 83;
450:
451: #endif
452: mapch(0); /* initialize key bindings */
453: fbkno = macptr = 0; /* no macros */
454: #ifndef PC
455: myuid = getuid(); /* get my user ID */
456: mypid = getpid();
457: mymask = umask(0);
458: umask(mymask&077); /* Make sure I can read/write my own files */
459:
460: #endif PC
461: #ifdef CRYPTO
462:
463: /* Set up for encrypting the buffer */
464:
465: time (&bufkey);
466: tset = myuid & 077777; /* Make sure it's +! */
467: while (tset) {
468: bufkey = bufkey * bufkey + tset;
469: tset = tset >> 1;
470: }
471: #endif
472: init(); /* initialize */
473: #ifdef PC
474: sttype(NULL);
475: tset = 1;
476: #else
477: if ((cp=getenv("TERM"))!= NULL) {
478: sttype(cp); /* set up for terminal */
479: tset = 1;
480: } else {
481: sttype(NULL); /* default terminal type */
482: tset = 0;
483: }
484: #endif
485: nsharg = argc-1;
486: sharg = argv+1; /* pointer to first argument */
487:
488: if (setjmp(retjmp)) goto main_loop;
489:
490: if (nsharg && streq(*sharg,".i")) {
491: **sharg = '-'; /* user's init only */
492: } else {
493: #ifdef PC
494: if (infile("c:emacs.ini")<=0) {
495: infile("emacs.ini");
496: }
497: #else
498: #ifdef DIRED
499: if (infile("$HOME/.dired_init")<=0) { /* run user's init file */
500: #else
501: if (infile("$HOME/.emacs_init")<=0) { /* run user's init file */
502: seprintf(itbuf,"%s/.emacs_init",em_dir);
503: infile (itbuf); /* run default init file */
504: #endif
505: }
506: #endif
507: }
508: if (nsharg && streq(*sharg,"-i")) {
509: sharg+=2;
510: nsharg-=2;
511: infile(sharg[-1]);
512: }
513: if (tset == 0) ttype();
514: line = 0;
515: #ifdef DIRED
516: if ((nsharg) && (**sharg == '-')) {
517: strcpy(dired_args+3,((*sharg)+1));
518: nsharg;
519: sharg++;
520: }
521: #else
522: if (nsharg&& (**sharg == '+')) {
523: cp = nscan(((*sharg)+1),&line);
524: sharg++;
525: nsharg--;
526: }
527: #ifdef CRYPTO
528: if (nsharg && (streq(*sharg,"-x"))) {
529: sharg++;
530: nsharg--;
531: setkey(1,1); /* Ask user for key */
532: }
533: #endif
534: #endif
535: if (nsharg) {
536: readin(*sharg,1);
537: nsharg--;
538: sharg++;
539: #ifdef DIRED
540: } else readin (".",1);
541: #else
542: }
543: if (line) absgoto(line);
544: #endif
545: main_loop:setjmp(retjmp); /* establish return point */
546: #ifdef PC
547: prompt(MODLN+1,"Proprietary and a Trade Secret of Bell Laboratories, No Unauthorized Copying");
548: #endif
549: while (1) {
550: edit(1);
551: gquit(); /* quit if done */
552: }
553: }
554:
555: /* mapch -- map a character */
556:
557: mapch(arg)
558: int arg;
559: {
560: register int fromc;
561: register int toc;
562: register char *fromp;
563: char *fromac;
564: extern char *maclook();
565:
566: if (arg == 0) {
567: for (toc = 0; toc < NCHARS; toc++) map_it[toc] = doit[toc];
568: return;
569: }
570: /* Keywords: commands key-bindings user-interface */
571:
572: toc = gechar("Map character");
573: switch(arg) {
574:
575: case 1:
576:
577: fromc = gechar("To command");
578: mapkey(toc,fromc);
579: break;
580: case 2:
581: case 4:
582: fromp = getname ("To macro: ");
583: if (fromac = maclook(fromp)) {
584: map_it[toc] = (fromac-&bbuf[0][0]+ISIZE);
585: } else error(WARN,51,fromp); /* Macro not found */
586: break;
587: }
588: }
589:
590: mapkey(toc,fromc)
591: int toc;
592: int fromc;
593:
594: /* Keywords: key_bindings user_interface:10 */
595: {
596: map_it[toc] = doit[fromc];
597: }
598:
599: #ifdef ASSKEY
600: asskey(string,key)
601: char *string;
602: int key;
603:
604:
605: /* Keywords: key_bindings:50 terminal_initialization terminal_parameters */
606:
607: {
608: int tokey;
609:
610: if (string == NULL) return;
611: tokey = *string++;
612: if (tokey == ESC) {
613: tokey = 0200 + *string++;
614: }
615: if (tokey == CTRLX) {
616: tokey == 0400 + *string++;
617: }
618: if (*string) return;
619:
620: if (map_it[tokey]) return;
621: mapkey(tokey,key);
622: }
623: #endif
624:
625: #ifdef PC
626: mapk(arg)
627: int arg;
628: {
629: char *cp;
630: extern char *rrxtab;
631: int c;
632: /* Keywords: commands key-bindings PC-only */
633: cp = &rrxtab[2*arg];
634: c = gechar("command");
635: if (c & 0400) {
636: *cp++ = '';
637: c-=0400;
638: }
639: if (c & META) {
640: *cp++ = 033;
641: c -= META;
642: }
643: *cp = c;
644: }
645: #endif
646: /* help prompts for a character, and displays the function of that
647: character. * displays all non self inserting and defined character
648: commands, ^X prompts for another character to describe a ^X sequence */
649:
650: help() /* help function */
651:
652: {
653: register int c;
654: register int x;
655: char hbuf[HELSIZE];
656:
657: /* Keywords: help-messages commands user-interface character-display:10 */
658:
659: prompt1("M-?: ");
660: c = getchar();
661: if (c == ESC) c = (getchar()) + META;
662: mtop();
663: if (c == '*') {
664: for (c = 0; c < 0377; c++) {
665: if ((x=map_it[c]) && (x != HINSERT)) {
666: helpin(c,hbuf);
667: if(putout("The character '%c' %s",c, hbuf)) return;
668: }
669: }
670: } else {
671: helpin(c,hbuf);
672: putout("The character '%c' %s",c, hbuf);
673: }
674: putout (endput);
675: if (c != 030) {
676: IGNORE(contin());
677: if (helfile>0) close(helfile);
678: helfile = 0;
679: return;
680: }
681: c = getchar();
682: if (c != '*') {
683: helpin(c+CTLX,hbuf);
684: putout ("The sequence '^X%c' %s", c, hbuf);
685: } else for (c =0; c<128; c++) {
686: if (map_it[c+CTLX]) {
687: helpin(c+CTLX,hbuf);
688: if(putout ("The sequence '^X%c' %s", c, hbuf)) return;
689: }
690: }
691: putout (endput);
692: IGNORE(contin());
693: if (helfile>0) {
694: close(helfile);
695: helfile = 0;
696: }
697: return;
698: }
699:
700: /* wall chart -- produce a wall chart of all emacs characters */
701:
702:
703: wallc()
704: {
705: register int i;
706: register int x;
707: int oldln,oldcol;
708: int oldtab;
709: char hbuf[HELSIZE];
710:
711: /* Keywords: help-messages commands insertion character-display:10 */
712:
713:
714: oldtab = TABMD;
715: oldln = curln;
716: oldcol = column;
717: TABMD = 0; /* flush C mode */
718: putin(myname);
719: putin(" version ");
720: putin(version);
721: putin(" Date: ");
722: putin(hdate);
723: nl(2);
724: for (i = 0; i < NCHARS; i++) {
725:
726: if (i == CTLX) {
727: nl(1);
728: putin("Control-X commands:");
729: nl(2);
730: }
731: if ((x=map_it[i])&& (x != 9)){
732:
733: if (i&CTLX) {
734: cput(CTRLX);
735: cput(i-CTLX);
736: } else {
737: cput(i);
738: }
739: put(':');
740: put(' ');
741: helpin(i,hbuf);
742: putin(hbuf);
743: nl(1);
744: }
745: }
746: if (helfile>0) {
747: close(helfile);
748: helfile = 0;
749: }
750: unins(oldln,oldcol);
751: TABMD = oldtab;
752: }
753:
754:
755: /* print an error message and wait for response. ^Z exits emacs
756: * immediately, ^G tries to stop the current command by returning 1
757: * from error, any other character just continues (returns 0)*/
758:
759: /*VARARGS1*/
760:
761: error(sev,enumb,arg1,arg2,arg3)
762:
763: int sev;
764: int enumb;
765: int arg1;
766: int arg2;
767: int arg3;
768:
769: {
770: char c;
771: int cc;
772: long skadd;
773: char string[HELSIZE];
774: char errpath[128];
775: int errfile;
776: /* Keywords: error-messages unix-interface user-interface */
777:
778: unprompt(); /* remove spurious messages */
779: if (SCRWID==0) sttype(NULL); /* Fix Null terminal type */
780:
781: #ifdef PC
782: if (enumb == 0) enumb = 13;
783: errfile = open("a:error.blk",4); /* open errmsg file */
784: if (errfile < 0) errfile = open("b:error.blk",4);
785: #else
786: seprintf(errpath,"%s/errfile",em_dir);
787: errfile = open(errpath,0); /* open errmsg file */
788: #endif PC
789: skadd = (long) (enumb-1) * HELSIZE; /* 0 is no error */
790:
791:
792: if (errfile>0) {
793: do {
794: lseek(errfile,skadd,0);
795: cc = read(errfile,string,HELSIZE);
796: } while ((cc != HELSIZE) && (errno == 4));
797: close(errfile);
798: } else {
799: seprintf(string,"Can't access %s/errfile for error %d",em_dir,enumb);
800: }
801: mtop();
802: putout(string,arg1,arg2,arg3);
803: putout(endput);
804: beep();
805: mflush(stdout); /* flush output */
806: reread:
807: #ifdef PC
808: rawread(&c);
809: #else
810: cc = 0;
811: if (no_io) {
812: c = CTRLZ;
813: } else {
814:
815: while (read(0,&c,1) !=1) { /* always from tty */
816: c=CTRLZ; /* Default to quit */
817: if (++cc > 60) break; /* Quit after 1 hour */
818: }
819: }
820: #endif
821: if ((c&0177) == CTRLBRAK) eabort(0); /* crash dump */
822: if (sev == FATAL) crash(0);
823: switch(c&0177) {
824:
825: case CTRLG:
826: case RUBOUT:
827: while (infrn) inpop(); /* get out of any init files */
828: return(-1);
829: case 'n':
830: return(1); /* CTRL -G */
831: case CTRLZ: gquit(); /* get out of emacs */
832:
833: case CTRLS:
834: case CTRLQ:
835: goto reread; /* Ignore ^S/^Q from terminal */
836:
837: default: return(0); /* normal return */
838: }
839: }
840:
841:
842: char *
843: hmap(helno)
844: /* Keywords help-messages macro-programming user-interface:10 */
845:
846: int helno;
847: {
848: register char *macp;
849: macp = &(bbuf[0][helno-2]);
850: while (*(--macp));
851: return(macp+1);
852: }
853:
854: helpin(helno,hbuf)
855:
856: register int helno;
857: register char *hbuf;
858:
859: {
860: /* Keywords: help-messages unix-interface */
861:
862: register int cc;
863: long skadd;
864: char helname[128];
865:
866: helno = map_it[helno];
867: if (helno>ISIZE) {
868: strcpy(hbuf,hmap(helno-ISIZE));
869: return;
870: }
871: if (helfile == 0) {
872: #ifdef PC
873: helfile = open ("a:help.blk",4);
874: if (helfile < 0) helfile = open ("b:help.blk",4);
875: #else
876: seprintf(helname,"%s/helpfile",em_dir); /* construct path */
877: helfile = open (helname,0);
878: if (helfile < 0) {
879: helfile = 0;
880: seprintf(hbuf,"Can't open help message file: %s",helname);
881: }
882: #endif PC
883: }
884: skadd = (long) (helno) * HELSIZE;
885: #ifdef PC
886: if (helfile > 0) {
887: lseek(helfile,skadd,0);
888: cc = read(helfile,hbuf,HELSIZE);
889: }
890: #else
891: do {
892: lseek(helfile,skadd,0);
893: cc = read(helfile,hbuf,HELSIZE);
894: } while ((cc != HELSIZE) && (errno == 4));
895: #endif PC
896: }
897:
898:
899: statout()
900:
901: {
902: #ifndef PC
903: char stbuf[256];
904: register int fid;
905: register int i;
906: char fbuf[128];
907: /* Keywords: user-interface:10 statistics exit-processing */
908:
909: struct tstruct {
910: long usrtime;
911: long systime;
912: long xt1;
913: long xt2;
914: } tbf;
915:
916: times(&tbf);
917:
918: seprintf(stbuf,"%d %D %D %d %D %d %d %d %d %d\n",
919: myuid,tbf.usrtime,tbf.systime,ninch,noutc,
920: nmkline,nbread,nbwrite,nbseek,TERMIQ);
921: seprintf(fbuf,"%s/s%s",em_dir,version);
922:
923: #ifdef ux3
924: fid = open(fbuf,O_WRONLY+O_APPEND);
925: if (fid) {
926: #else
927: fid = open(fbuf,1);
928: if (fid) {
929: lseek(fid,0L,2);
930: #endif ux3
931: write(fid,stbuf,lng(stbuf));
932: close(fid);
933: }
934: #ifdef CMON
935: seprintf(fbuf,"%s/cmcnt",emd_source);
936: fid = open (fbuf,1);
937: if (fid>=0) {
938: lseek(fid,0L,2);
939: write(fid,cmcnt,sizeof(cmcnt));
940: close(fid);
941: }
942: #endif CMON
943: #ifdef MONITOR
944: monitor(0);
945: #endif MONITOR
946: #endif PC
947: }
948: #ifdef DIRED
949:
950: char *
951:
952: fxname(line,fbuf)
953:
954: int line;
955: char *fbuf;
956: /* Keywords: dired user-interface file-selection */
957:
958: {
959: register char *xp;
960: register char *lp;
961: register char *fp;
962:
963: lp = mkline(line)+leng(line)-1;
964: while (*lp == ' ') lp--;
965: fp = lp;
966: while ((*fp != ' ') || ((fp[-3] != ':') && (fp[-3] != '9'))) fp--;
967: xp = fbuf;
968: while (fp != lp) *xp++= *(++fp);
969: *xp = 0;
970: return(fbuf);
971: }
972: dcdel(count,arg)
973: /* Keywords: dired commands deletion */
974:
975: {
976: if ((diron == 0) || (column)) insertc(count,arg); /* not at BOL */
977: else ddel(count);
978: }
979:
980: /* delete an entry */
981:
982: ddel(count,arg)
983:
984: register int count,arg;
985: /* Keywords: dired commands deletion */
986:
987: {
988: if (diron) {
989: while (count--) {
990: move(curln,0);
991: if (*clptr != EOL) insertc(1,'D');
992: if (curln<nlines)move(curln+1,0);
993: }
994: } else {
995: switch(arg) {
996: case CTRLD:
997: fdel(count,arg);
998: break;
999: case CTRLH:
1000: case RUBOUT:
1001: bdel(count,arg);
1002: break;
1003: case CTRLK:
1004: ekill(count,arg);
1005: break;
1006: default: beep(); /* I don't know how we got here */
1007: }
1008: }
1009: }
1010:
1011: dundel(count,arg)
1012:
1013: /* Keyword dired commands undoing */
1014:
1015: register int count;
1016: {
1017: if ((diron == 0) || column) {
1018: return(insertc(count,arg));
1019: }
1020: while (count--) {
1021: if (*clptr != EOL) insertc(1,' ');
1022: if (curln<nlines) move(curln+1,0);
1023: }
1024: }
1025:
1026: dview(count,arg)
1027: /* Keywords: dired commands recursive-editing */
1028:
1029: {
1030:
1031: char fxb[64];
1032: char dxb[128];
1033: int obuf,nbuf;
1034:
1035: if (column || (diron == 0)) insertc(count,arg);
1036: else {
1037: seprintf(dxb,"%s/%s",fname(),fxname(curln,fxb));
1038: obuf = curbf;
1039: if (chgbuf(dxb) && readin(dxb,1)) {
1040: nbuf = curbf;
1041: recurse(1);
1042: if (nbuf != curbf) chbuf(nbuf);
1043: if (diron) fsave(0);
1044: }
1045: if (obuf != curbf) {
1046: nbuf = curbf;
1047: chbuf(obuf);
1048: klbfr(nbuf);
1049: }
1050: }
1051: };
1052:
1053: catstr(dp,sp1,sp2)
1054:
1055: /* concatenate */
1056:
1057: /* Keywords: string-handling */
1058:
1059: register char *dp;
1060: register char *sp1;
1061: register char *sp2;
1062:
1063: {
1064: while (*dp++ = *sp1++);
1065: *(dp-1)='/';
1066: while (*dp++ = *sp2++);
1067: }
1068: dclean()
1069: /* Keywords: dired exit-processing:10 user-interface:40 deletion:30 unix-interface */
1070:
1071: {
1072: register int i;
1073: register char *lp;
1074: register int status;
1075: char *cp;
1076: int ndel;
1077: char obuf[16];
1078: int ouid,guid;
1079: char *cp1,*cp2;
1080: extern int cstatus;
1081: char nbuf[256];
1082:
1083:
1084: if (streq(fname(),".passwd")) return; /* don't edit .passwd! */
1085: ndel = 0;
1086: for (i = 1; i <= nlines; i++) {
1087: lp = mkline(i);
1088: if ((*lp == 'D') || (lp[1] == 'M')|| (lp[2] == 'O')){
1089: if (ndel == 0) {
1090: clear();
1091: putout ("Editing the following files from directory %s:", fname());
1092: putout ("");
1093: }
1094: putout ("%c%c%c %s",lp[0],lp[1],lp[2],fxname(i,nbuf));
1095: ndel++;
1096: }
1097: }
1098: if (ndel == 0) return;
1099: i = gyn("OK?");
1100: if (i==0) return(0);
1101: if (i<0) quit();
1102:
1103: cp = mstrcpy(nbuf,fname());
1104: *cp++ = '/';
1105: for (i = 1; i < nlines; i++) {
1106: lp = mkline(i);
1107: if (*lp == 'D') {
1108: fxname(i,cp);
1109: if (lp[4] == 'd') {
1110: char xbuf[256];
1111:
1112: seprintf(xbuf,"rm -fr %s",nbuf);
1113: unx(xbuf,4); /* Run rm command on it */
1114: status = cstatus;
1115: errno = 66; /* Can't remove directory */
1116: } else {
1117: status = unlink (nbuf);
1118: }
1119: if (status){
1120: error (WARN,errno,nbuf);
1121: } else {
1122: move(i,0);
1123: ekill(1); /* kill line */
1124: }
1125: } else {
1126: if (lp[1] == 'M') {
1127: fxname(i,cp);
1128: status = chmod (nbuf,mkmode(lp+5));
1129: if (status) {
1130: error (WARN,errno,nbuf);
1131: } else {
1132: move(i,1);
1133: insertc(1,' ');
1134: }
1135: }
1136: if (lp[2] == 'O') {
1137: fxname(i,cp);
1138: cp1 =obuf;
1139: cp2 = lp+19;
1140: while ((*cp1++ = *cp2++) != ' ');
1141: *(--cp1) = 0;
1142: if ((ouid = gtuid(obuf))== -1) goto badpw;
1143: lp = mkline(i);
1144: cp1 = obuf;
1145: cp2 = lp+28;
1146: while ((*cp1++ = *cp2++) != ' ');
1147: *(--cp1) = 0;
1148: if ((guid = gtuid(obuf))== -1) {
1149: badpw: error (WARN,67,obuf,nbuf);
1150: continue;
1151: }
1152: lp = mkline(i);
1153: status = chown(nbuf,ouid,guid);
1154: if (status) {
1155: error (WARN,errno,nbuf);
1156: } else {
1157: move(i,2);
1158: insertc(1,' ');
1159: }
1160: }
1161: }
1162: }
1163: unmod(1); /* buffer is now up to date */
1164: return(1);
1165: }
1166:
1167: /* mkmode -- translate from ls -l style mode representation to */
1168: /* a 16 bit mode number */
1169:
1170: /* mode bit table. one entry per character, contains characters followed */
1171: /* by bit number to turn on */
1172:
1173: char *modebits[10] = {
1174: "r\011",
1175: "w\010",
1176: "x\007s\014s\007",
1177: "r\006",
1178: "w\005",
1179: "x\004s\013s\004",
1180: "r\003",
1181: "w\002",
1182: "x\001t\012t\001",
1183: 0};
1184:
1185: mkmode(sp)
1186: char *sp;
1187:
1188: /* Keywords: dired file-modes user-interface:10 unix-interface:30 */
1189:
1190:
1191: {
1192: int newmode;
1193: char *mp;
1194: char **mep;
1195:
1196: newmode = 0;
1197: mep = modebits;
1198: while (mp = *mep++) {
1199: while (*mp) {
1200: if (*mp == *sp) {
1201: newmode |= (1<< (mp[1]-1));
1202: }
1203: mp+= 2;
1204: }
1205: sp++;
1206: }
1207: return(newmode);
1208: }
1209:
1210: /* gtuid -- get uid from user name */
1211:
1212: /* **** NOTE, we can't use getpwnam, because it uses standard I/O */
1213:
1214: gtuid(name)
1215:
1216: register char *name;
1217: /* Keywords: dired unix-interface:10 password-file user-id-processing */
1218:
1219: {
1220: int oldbf;
1221: unsigned uid;
1222: char xbuf[100];
1223: register char *cp;
1224: oldbf = curbf;
1225:
1226: chgbuf (".passwd");
1227: if (nlines < 10) {
1228: readin ("/etc/passwd",1);
1229: }
1230: seprintf (xbuf,"^%s:",name);
1231:
1232: if (rgsrch(1,0,xbuf,0,1)) {
1233: srch(kline,kcol,":",1);
1234: srch(kline,kcol+1,":",1);
1235: uid = 0;
1236: cp = mkline(kline)+kcol+1;
1237: while (*cp != ':') {
1238: uid = (uid*10)+(*cp-'0');
1239: cp++;
1240: }
1241: } else uid = -1;
1242: chbuf(oldbf);
1243: return(uid);
1244: }
1245: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.