📄 dbug.c
字号:
* static VOID DbugExit (why) * char *why; * * DESCRIPTION * * Prints error message using current process name, the reason for * aborting (typically out of memory), and exits with status 1. * This should probably be changed to use a status code * defined in the user's debugger include file. * */static void DbugExit (why)char *why;{ (void) fprintf (stderr, ERR_ABORT, _db_process_, why); (void) fflush (stderr); exit (1);}/* * FUNCTION * * DbugMalloc allocate memory for debugger runtime support * * SYNOPSIS * * static long *DbugMalloc (size) * int size; * * DESCRIPTION * * Allocate more memory for debugger runtime support functions. * Failure to to allocate the requested number of bytes is * immediately fatal to the current process. This may be * rather unfriendly behavior. It might be better to simply * print a warning message, freeze the current debugger state, * and continue execution. * */static char *DbugMalloc (size)int size;{ register char *new; if (!(new = malloc ((unsigned int) size))) DbugExit ("out of memory"); return (new);}/* * As strtok but two separators in a row are changed to one * separator (to allow directory-paths in dos). */static char *static_strtok (s1, separator)char *s1;pchar separator;{ static char *end = NULL; reg1 char *rtnval,*cpy; rtnval = NULL; if (s1 != NULL) end = s1; if (end != NULL && *end != EOS) { rtnval=cpy=end; do { if ((*cpy++ = *end++) == separator) { if (*end != separator) { cpy--; /* Point at separator */ break; } end++; /* Two separators in a row, skipp one */ } } while (*end != EOS); *cpy=EOS; /* Replace last separator */ } return (rtnval);}/* * FUNCTION * * BaseName strip leading pathname components from name * * SYNOPSIS * * static char *BaseName (pathname) * char *pathname; * * DESCRIPTION * * Given pointer to a complete pathname, locates the base file * name at the end of the pathname and returns a pointer to * it. * */static char *BaseName (pathname)char *pathname;{ register char *base; base = strrchr (pathname, FN_LIBCHAR); if (base++ == NullS) base = pathname; return (base);}/* * FUNCTION * * Writable test to see if a pathname is writable/creatable * * SYNOPSIS * * static BOOLEAN Writable (pathname) * char *pathname; * * DESCRIPTION * * Because the debugger might be linked in with a program that * runs with the set-uid-bit (suid) set, we have to be careful * about opening a user named file for debug output. This consists * of checking the file for write access with the real user id, * or checking the directory where the file will be created. * * Returns TRUE if the user would normally be allowed write or * create access to the named file. Returns FALSE otherwise. * */#ifndef Writablestatic BOOLEAN Writable (pathname)char *pathname;{ REGISTER BOOLEAN granted; REGISTER char *lastslash; granted = FALSE; if (EXISTS (pathname)) { if (WRITABLE (pathname)) { granted = TRUE; } } else { lastslash = strrchr (pathname, '/'); if (lastslash != NULL) { *lastslash = EOS; } else { pathname = "."; } if (WRITABLE (pathname)) { granted = TRUE; } if (lastslash != NULL) { *lastslash = '/'; } } return (granted);}#endif/* * FUNCTION * * ChangeOwner change owner to real user for suid programs * * SYNOPSIS * * static VOID ChangeOwner (pathname) * * DESCRIPTION * * For unix systems, change the owner of the newly created debug * file to the real owner. This is strictly for the benefit of * programs that are running with the set-user-id bit set. * * Note that at this point, the fact that pathname represents * a newly created file has already been established. If the * program that the debugger is linked to is not running with * the suid bit set, then this operation is redundant (but * harmless). * */#ifndef ChangeOwnerstatic void ChangeOwner (pathname)char *pathname;{ if (chown (pathname, getuid (), getgid ()) == -1) { (void) fprintf (stderr, ERR_CHOWN, _db_process_, pathname); perror (""); (void) fflush (stderr); }}#endif/* * FUNCTION * * _db_setjmp_ save debugger environment * * SYNOPSIS * * VOID _db_setjmp_ () * * DESCRIPTION * * Invoked as part of the user's DBUG_SETJMP macro to save * the debugger environment in parallel with saving the user's * environment. * */#ifdef HAVE_LONGJMPEXPORT void _db_setjmp_ (){ CODE_STATE *state; state=code_state(); state->jmplevel = state->level; state->jmpfunc = state->func; state->jmpfile = state->file;}/* * FUNCTION * * _db_longjmp_ restore previously saved debugger environment * * SYNOPSIS * * VOID _db_longjmp_ () * * DESCRIPTION * * Invoked as part of the user's DBUG_LONGJMP macro to restore * the debugger environment in parallel with restoring the user's * previously saved environment. * */EXPORT void _db_longjmp_ (){ CODE_STATE *state; state=code_state(); state->level = state->jmplevel; if (state->jmpfunc) { state->func = state->jmpfunc; } if (state->jmpfile) { state->file = state->jmpfile; }}#endif/* * FUNCTION * * DelayArg convert D flag argument to appropriate value * * SYNOPSIS * * static int DelayArg (value) * int value; * * DESCRIPTION * * Converts delay argument, given in tenths of a second, to the * appropriate numerical argument used by the system to delay * that that many tenths of a second. For example, on the * amiga, there is a system call "Delay()" which takes an * argument in ticks (50 per second). On unix, the sleep * command takes seconds. Thus a value of "10", for one * second of delay, gets converted to 50 on the amiga, and 1 * on unix. Other systems will need to use a timing loop. * */#ifdef AMIGA#define HZ (50) /* Probably in some header somewhere */#endifstatic int DelayArg (value)int value;{ uint delayarg = 0;#if (unix || xenix) delayarg = value / 10; /* Delay is in seconds for sleep () */#endif#ifdef AMIGA delayarg = (HZ * value) / 10; /* Delay in ticks for Delay () */#endif return (delayarg);}/* * A dummy delay stub for systems that do not support delays. * With a little work, this can be turned into a timing loop. */#if ! defined(Delay) && ! defined(AMIGA)static int Delay (ticks)int ticks;{ return ticks;}#endif/* * FUNCTION * * perror perror simulation for systems that don't have it * * SYNOPSIS * * static VOID perror (s) * char *s; * * DESCRIPTION * * Perror produces a message on the standard error stream which * provides more information about the library or system error * just encountered. The argument string s is printed, followed * by a ':', a blank, and then a message and a newline. * * An undocumented feature of the unix perror is that if the string * 's' is a null string (NOT a NULL pointer!), then the ':' and * blank are not printed. * * This version just complains about an "unknown system error". * */#ifndef HAVE_PERRORstatic void perror (s)char *s;{ if (s && *s != EOS) { (void) fprintf (stderr, "%s: ", s); } (void) fprintf (stderr, "<unknown system error>\n");}#endif /* HAVE_PERROR */ /* flush dbug-stream, free mutex lock & wait delay */ /* This is because some systems (MSDOS!!) dosn't flush fileheader */ /* and dbug-file isn't readable after a system crash !! */static void dbug_flush(){#ifndef THREAD if (stack->flags & FLUSH_ON_WRITE)#endif {#if defined(MSDOS) || defined(__WIN32__) if (_db_fp_ != stdout && _db_fp_ != stderr) { if (!(freopen(stack->name,"a",_db_fp_))) { (void) fprintf(stderr, ERR_OPEN, _db_process_); fflush(stderr); _db_fp_ = stdout; stack -> out_file = _db_fp_; stack -> flags|=FLUSH_ON_WRITE; } } else#endif { (void) fflush (_db_fp_); (void) Delay (stack -> delay); } } pthread_mutex_unlock(&THR_LOCK_dbug);} /* dbug_flush *//* * Here we need the definitions of the clock routine. Add your * own for whatever system that you have. */#ifdef HAVE_GETRUSAGE#include <sys/param.h>#include <sys/resource.h>extern int getrusage(int, struct rusage *);/* * Returns the user time in milliseconds used by this process so * far. */static unsigned long Clock (){ struct rusage ru; (void) getrusage (RUSAGE_SELF, &ru); return ((ru.ru_utime.tv_sec * 1000) + (ru.ru_utime.tv_usec / 1000));}#else#if defined(MSDOS) || defined(__WIN32__)static ulong Clock(){ return clock()*(1000/CLOCKS_PER_SEC);}#else#ifdef amigastruct DateStamp { /* Yes, this is a hack, but doing it right */ long ds_Days; /* is incredibly ugly without splitting this */ long ds_Minute; /* off into a separate file */ long ds_Tick;};static int first_clock = TRUE;static struct DateStamp begin;static struct DateStamp elapsed;static unsigned long Clock (){ register struct DateStamp *now; register unsigned long millisec = 0; extern VOID *AllocMem (); now = (struct DateStamp *) AllocMem ((long) sizeof (struct DateStamp), 0L); if (now != NULL) { if (first_clock == TRUE) { first_clock = FALSE; (void) DateStamp (now); begin = *now; } (void) DateStamp (now); millisec = 24 * 3600 * (1000 / HZ) * (now -> ds_Days - begin.ds_Days); millisec += 60 * (1000 / HZ) * (now -> ds_Minute - begin.ds_Minute); millisec += (1000 / HZ) * (now -> ds_Tick - begin.ds_Tick); (void) FreeMem (now, (long) sizeof (struct DateStamp)); } return (millisec);}#else#ifndef THREADstatic unsigned long Clock (){ return (0);}#endif#endif /* amiga */#endif /* MSDOS || __WIN32__ */#endif /* RUSAGE */#ifdef NO_VARARGS/* * Fake vfprintf for systems that don't support it. If this * doesn't work, you are probably SOL... */static int vfprintf (stream, format, ap)FILE *stream;char *format;va_list ap;{ int rtnval; ARGS_DCL; ARG0 = va_arg (ap, ARGS_TYPE); ARG1 = va_arg (ap, ARGS_TYPE); ARG2 = va_arg (ap, ARGS_TYPE); ARG3 = va_arg (ap, ARGS_TYPE); ARG4 = va_arg (ap, ARGS_TYPE); ARG5 = va_arg (ap, ARGS_TYPE); ARG6 = va_arg (ap, ARGS_TYPE); ARG7 = va_arg (ap, ARGS_TYPE); ARG8 = va_arg (ap, ARGS_TYPE); ARG9 = va_arg (ap, ARGS_TYPE); rtnval = fprintf (stream, format, ARGS_LIST); return (rtnval);}#endif /* NO_VARARGS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -