184 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* ELLE - Copyright 1982, 1987 by Ken Harrenstien, SRI International
 | ||
|  *	This software is quasi-public; it may be used freely with
 | ||
|  *	like software, but may NOT be sold or made part of licensed
 | ||
|  *	products without permission of the author.
 | ||
|  */
 | ||
| /*	EEERR - Error handling & testing routines
 | ||
|  */
 | ||
| 
 | ||
| #include "elle.h"
 | ||
| 
 | ||
| #if V6
 | ||
| #include "eesigs.h"
 | ||
| #else
 | ||
| #include <signal.h>
 | ||
| #endif
 | ||
| 
 | ||
| /* EFUN: "Hit Breakpoint" */
 | ||
| f_bkpt()
 | ||
| {	clean_exit();
 | ||
| 	bpt();
 | ||
|         set_tty();
 | ||
| }
 | ||
| bpt() {}		/* Put a DDT/ADB breakpoint here */
 | ||
| 
 | ||
| #if !(STRERROR)		/* If strerror() not supported, we provide it. */
 | ||
| extern int sys_nerr;		/* Max index into sys_errlist */
 | ||
| extern char *sys_errlist[];
 | ||
| 
 | ||
| char *
 | ||
| strerror(num)
 | ||
| int num;
 | ||
| {
 | ||
| 	static char badbuf[30];
 | ||
| 	if (num > 0 && num <= sys_nerr)
 | ||
| 		return (sys_errlist[num]);
 | ||
| 	sprintf(badbuf, "unknown error %d", num);
 | ||
| 	return badbuf;
 | ||
| }
 | ||
| #endif /* -STRERROR */
 | ||
| 
 | ||
| 
 | ||
| errsbm(type,adr,str,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)
 | ||
| register int type;	/* Type, flags */
 | ||
| int (*adr)();		/* Addr called from */
 | ||
| char *str;		/* Printf string */
 | ||
| {	register struct buffer *b;
 | ||
| 	int oldttystate;
 | ||
| 
 | ||
| 	oldttystate = clean_exit();	/* Ensure not in editing mode */
 | ||
| 	if(type == SBFERR)	/* File overwrite error?  A0 is FD */
 | ||
| 	  {	printf("WARNING - FILE CORRUPTED!\nBuffers affected:\n");
 | ||
| 		for(b = buf_head; b; b = b->b_next)
 | ||
| 		  {	if(sb_fdinp((SBBUF *)b, a0))
 | ||
| 				printf((b->b_fn ? "  %s: %s\n" : "  %s\n"),
 | ||
| 					b->b_name, b->b_fn);
 | ||
| 		  }
 | ||
| 		if (oldttystate > 0) set_tty();
 | ||
| 		return(1);	/* Try to continue normally */
 | ||
| 	  }
 | ||
| 	printf("%sERR: %o ", (type ? "SBX" : "SBM"), adr);
 | ||
| 	printf(str,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12);
 | ||
| 	askerr();
 | ||
| }
 | ||
| 
 | ||
| /*
 | ||
|  *  Bite_bag -- Try to save our rear ends after a catastrophe.
 | ||
|  *	This routine is mainly called from "interrupt"
 | ||
|  *	level when a memory fault or bus error occurs.
 | ||
|  *	We try to save the buffer to the file "ELLE.crash"
 | ||
|  *	in the current working directory.  If it loses, well
 | ||
|  *	then you have really lost.  Note: this routine does
 | ||
|  *	not reset the appropriate signal handler, so it is
 | ||
|  *	never re-entered.  If a fault repeats once in this
 | ||
|  *	code, then the world dies.
 | ||
|  */
 | ||
| 
 | ||
| bite_bag(fault)				/* We come here on any memory error */
 | ||
| int fault;
 | ||
| {
 | ||
| 	int ostate;
 | ||
| 	/* Some systems, such as BSD4.x and SUN, do not reset caught signals
 | ||
| 	 * to SIG_DFL.
 | ||
| 	 * This is a win, but isn't what vanilla UNIX code expects.
 | ||
| 	 * Since it doesn't hurt to do it explicitly, we always turn it off
 | ||
| 	 * explicitly...
 | ||
| 	 */
 | ||
| 	signal(fault, SIG_DFL);		/* Reinstate default handling */
 | ||
| 
 | ||
| 	ostate = clean_exit();		/* Fix up the terminal modes first! */
 | ||
| 	printf("ELLE stopped by fatal interrupt (%d)!\n\
 | ||
| Type S or W to try saving your work.\n",fault);
 | ||
| 	askerr();
 | ||
| 	if(ostate > 0) set_tty();
 | ||
| 	signal(fault, bite_bag);	/* If continued, re-enable signal */
 | ||
| }
 | ||
| 
 | ||
| /* HUP_EXIT - Called by a SIGHUP hangup signal.
 | ||
|  *	Tries to save all modified buffers before exiting.
 | ||
|  *	Note that the TTY is not touched at all, although the terminal mode
 | ||
|  *	flag is set just in case further error handling routines are invoked.
 | ||
|  */
 | ||
| hup_exit()
 | ||
| {	extern int trm_mode;		/* See e_disp.c */
 | ||
| 
 | ||
| 	trm_mode = -1;			/* Say TTY is now detached */
 | ||
| 	saveworld((struct buffer *)0, 0);	/* Save world, w/o feedback */
 | ||
| 	exit(1);
 | ||
| }
 | ||
| 
 | ||
| errint()		/* Routine provided for ADB jumps */
 | ||
| {	askerr();
 | ||
| }
 | ||
| char askh1[] = "\
 | ||
| A - Abort process\n\
 | ||
| B - Breakpoint (must have \"bpt:b\" set in ADB)\n\
 | ||
| C - Continue\n\
 | ||
| D - Diagnostic command mode\n";
 | ||
| char askh2[] = "\
 | ||
| S - Try to save current buffer\n\
 | ||
| W - Try to save world (all modified buffers)\n";
 | ||
| 
 | ||
| int bsaving = 0;	/* Set while in middle of saving buffer(s) */
 | ||
| 
 | ||
| askerr()
 | ||
| {	register struct buffer *b;
 | ||
| 	char linbuf[100];
 | ||
| 	char *asklin();
 | ||
| 	extern int (*funtab[])();	/* In E_CMDS.C */
 | ||
| 	int ostate;
 | ||
| 
 | ||
| 	ostate = clean_exit();		/* Clean up TTY if not already done */
 | ||
| reask:
 | ||
| 	printf("(A,B,C,D,S,W,?)");
 | ||
| 	switch(upcase(*asklin(linbuf)))
 | ||
| 	  {
 | ||
| 		case '?':
 | ||
| 			writez(1,askh1);	/* Too long for &$@! printf */
 | ||
| 			writez(1,askh2);	/* Too long for &$@! V6 C */
 | ||
| 			break;			/*    optimizer (/lib/c2) */
 | ||
| 		case 'A':
 | ||
| 			abort();
 | ||
| 			break;
 | ||
| 		case 'B':
 | ||
| 			bpt();
 | ||
| 			break;
 | ||
| 		case 'Q':
 | ||
| 		case 'C':
 | ||
| 			goto done;
 | ||
| 		case 'D':
 | ||
| 			if(funtab[FN_DEBUG])
 | ||
| 				(*funtab[FN_DEBUG])(-1);
 | ||
| 			else printf("Sorry, no diagnostics\n");
 | ||
| 			break;
 | ||
| 		case 'S':	/* Try to save current buffer only */
 | ||
| 			b = cur_buf;
 | ||
| 			goto savb;
 | ||
| 		case 'W':	/* Try to save all modified buffers */
 | ||
| 			b = 0;
 | ||
| 		savb:	if(bsaving++)
 | ||
| 			  {	printf("Already saving -- continued");
 | ||
| 				goto done;
 | ||
| 			  }
 | ||
| 			saveworld(b, 1);	/* Save, with feedback */
 | ||
| 			bsaving = 0;
 | ||
| 			break;
 | ||
| 	  }
 | ||
| 	goto reask;
 | ||
| done:
 | ||
| 	if(ostate > 0)
 | ||
| 		set_tty();
 | ||
| }
 | ||
| 
 | ||
| char *
 | ||
| asklin(acp)
 | ||
| char *acp;
 | ||
| {	register char *cp;
 | ||
| 	register int c;
 | ||
| 	cp = acp;
 | ||
| 	while((c = tgetc()) != LF)
 | ||
| 		*cp++ = c;
 | ||
| 	*cp++ = 0;
 | ||
| 	return(acp);
 | ||
| }
 | 
