/*************************************************************************** * Mud20 1.0 by Todd H. Johnson (Kregor) a derivative of the Open Gaming * * License by Wizards of the Coast. All comments referring to D20, OGL, * * and SRD refer to the System Reference Document for the Open Gaming * * system. Any inclusion of these derivatives must include credit to the * * Mud20 system, the full and complete Open Gaming LIcense, and credit to * * the respective authors. See ../doc/srd.txt for more information. * * * * Emud 2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem. * * * * MrMud 1.4 by David Bills, Dug Michael and Martin Gallwey * * * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe. * ***************************************************************************/ /*************************************************************************** debug.c: debugging functions here. implemented in emud by Manwe and Scandum, improved and optimized by Scandum, credits to Hypnos who invented this idea. ***************************************************************************/ #include <stdarg.h> #include "mud.h" #define MAX_STACK_CALL 200 #define MAX_STACK_CALL_LEN 200 char call_stack[MAX_STACK_CALL][MAX_STACK_CALL_LEN]; int call_index; void push_call(char *f, ...) { if (call_index >= MAX_STACK_CALL) { call_index = MAX_STACK_CALL / 2; log_printf("push_call: max stack size reached"); dump_stack(); call_index = 0; } strcpy(call_stack[call_index], f); call_index++; } void push_call_format(char *f, ...) { va_list ap; va_start(ap, f); if (call_index >= MAX_STACK_CALL) { call_index = MAX_STACK_CALL / 2; log_printf("push_call: max stack size reached"); dump_stack(); call_index = 0; } /* strcpy(call_stack[call_index], f); */ vsprintf(call_stack[call_index], f, ap); call_index++; va_end(ap); } void pop_call(void) { if (call_index != 0) { call_index--; } else { log_printf("pop_call: index is zero: %s", call_stack[0]); } } void do_stack( CHAR_DATA *ch, char *argument ) { int i; ch_printf_color(ch, "Stack of E-Mud (index = %d)\n\r\n\r", call_index); for (i = 0 ; i < call_index ; i++) { ch_printf_color(ch, "%03d: %s\n\r", i, call_stack[i]); } } void dump_stack(void) { int i; log_printf("Stack trace (index = %d)", call_index); for (i = 0 ; i < call_index ; i++) { log_printf("call_stack[%03d] = %s", i, call_stack[i]); } log_printf("End of stack"); } void build_dump_stack( int vnum ) { int i; log_build_printf(vnum, "Stack trace (index = %d)", call_index); for (i = 0 ; i < call_index ; i++) { log_build_printf(vnum, "call_stack[%03d] = %s", i, call_stack[i]); } log_build_printf(vnum, "End of stack"); } void dump_desc_characters() { DESCRIPTOR_DATA *d; push_call("dump_desc_characters()"); log_string("List of active descriptors: "); for (d = mud->f_desc ; d ; d = d->next) { log_printf("%d: %p->%p->name = %s", d->descriptor, d, d->character, d->character ? d->character->name : "unknown"); } log_string("End of list\n"); pop_call(); return; } void print_errno(int number) { push_call("print_errno(%p)",number); switch(number) { case EFAULT : log_string("EFAULT"); break; case EACCES : log_string("EACCES"); break; case EPERM : log_string("EPERM"); break; case ENAMETOOLONG : log_string("ENAMETOOLONG"); break; case ENOTDIR : log_string("ENOTDIR"); break; case ENOMEM : log_string("ENOMEM"); break; case EROFS : log_string("EROFS"); break; case ENOENT : log_string("ENOENT"); break; case EISDIR : log_string("EISDIR"); break; case EXDEV : log_string("EXDEV"); break; case ENOTEMPTY : log_string("ENOTEMPTY"); break; case EEXIST : log_string("EEXIST"); break; case EBUSY : log_string("EBUSY"); break; case EINVAL : log_string("EINVAL"); break; case EMLINK : log_string("EMLINK"); break; case ELOOP : log_string("ELOOP"); break; case ENOSPC : log_string("ENOSPC"); break; default : log_printf("ErrNo: %d",number);break; } pop_call(); return; } void open_reserve( void ) { FILE_DATA *fdp; push_call("open_reserve(void)"); fpReserve = fopen(NULL_FILE, "r"); if (fpReserve == NULL) { log_printf("open_reserve: Failed to open %s (%s)", NULL_FILE, "r"); print_errno(errno); } else { ALLOCMEM(fdp, FILE_DATA, 1); fdp->filename = STRALLOC(NULL_FILE); fdp->opentype = STRALLOC("r"); fdp->fp = fpReserve; LINK(fdp, mud->f_open_file, mud->l_open_file, next, prev); } pop_call(); return; } void close_reserve( void ) { FILE_DATA *fdp; push_call("close_reserve(void)"); for (fdp = mud->f_open_file ; fdp ; fdp = fdp->next) { if (fdp->fp == fpReserve) { fclose(fdp->fp); STRFREE(fdp->filename); STRFREE(fdp->opentype); UNLINK(fdp, mud->f_open_file, mud->l_open_file, next, prev); FREEMEM(fdp); pop_call(); return; } } if (fdp == NULL) { log_printf("close_reserve: file data not found"); dump_stack(); } pop_call(); return; } FILE *my_fopen(char *filename, char *opentype, bool silent) { char file_buf[100]; char open_buf[10]; FILE_DATA *fdp; FILE *fp; push_call("my_fopen(%p,%p,%p)",filename,opentype,silent); strcpy(file_buf, filename); strcpy(open_buf, opentype); fp = fopen(file_buf, open_buf); if (fp == NULL) { if (silent == FALSE) { log_printf("Failed to open: %s (%s)", file_buf, open_buf); print_errno(errno); } pop_call(); return NULL; } ALLOCMEM(fdp, FILE_DATA, 1); fdp->filename = STRALLOC(file_buf); fdp->opentype = STRALLOC(open_buf); fdp->fp = fp; LINK(fdp, mud->f_open_file, mud->l_open_file, next, prev); pop_call(); return fp; } void my_fclose(FILE *which) { FILE_DATA *fdp; push_call("my_fclose(%p)",which); for (fdp = mud->f_open_file ; fdp ; fdp = fdp->next) { if (fdp->fp == which) { fclose(fdp->fp); STRFREE(fdp->filename); STRFREE(fdp->opentype); UNLINK(fdp, mud->f_open_file, mud->l_open_file, next, prev); FREEMEM(fdp); pop_call(); return; } } if (fdp == NULL) { log_printf("my_fclose: No matching file found to remove from the lists"); dump_stack(); } pop_call(); return; } void my_fclose_all() { FILE_DATA *fdp, *fdp_next; push_call("my_fclose_all()"); for (fdp = mud->f_open_file ; fdp ; fdp = fdp_next) { fdp_next = fdp->next; log_printf("my_fclose_all(): closing file %s", fdp->filename); my_fclose(fdp->fp); } pop_call(); return; } void do_openfiles(CHAR_DATA *ch, char *argument) { FILE_DATA *fdp; push_call("do_openfiles(%p,%p)",ch,argument); ch_printf_color(ch, "Openfiles:\n\r"); for (fdp = mud->f_open_file ; fdp ; fdp = fdp->next) { ch_printf_color(ch, "Filename: %-20s Type: %s\n\r", fdp->filename, fdp->opentype); } pop_call(); return; } void do_version(CHAR_DATA *ch, char *argument) { FILE *vfp; char str_vers[40]; char str_date[40]; push_call("do_version(%p,%p)",ch,argument); if (strlen(argument) > 40) { argument[40] = '\0'; } if (ch->level < MAX_LEVEL || argument[0] == '\0') { vfp = my_fopen(VERSION_FILE, "r", FALSE); if (vfp) { fread(str_vers, sizeof(char), 40, vfp); fread(str_date, sizeof(char), 40, vfp); ch_printf_color(ch, " Current version: {168}%s {078}({178}%s{078})\n\r", str_vers, str_date); fread(str_vers, sizeof(char), 40, vfp); fread(str_date, sizeof(char), 40, vfp); ch_printf_color(ch, "Previous version: {168}%s {078}({178}%s{078})\n\r", str_vers, str_date); my_fclose(vfp); pop_call(); return; } else { send_to_char("It is unknown which version we are now running.\n\r",ch); pop_call(); return; } } else { if (!strncasecmp(argument, "set ", 3)) { char new_vers[40]; char new_date[40]; strcpy(new_vers, &argument[4]); if (new_vers[0] == '\0') { send_to_char("Usage: version set {<version number>}\n\r", ch); pop_call(); return; } vfp = my_fopen(VERSION_FILE, "r", FALSE); if (vfp) { fread(str_vers, sizeof(char), 40, vfp); fread(str_date, sizeof(char), 40, vfp); my_fclose(vfp); } else { ch_printf_color(ch, "Could not open %s to read old information!\n\r", VERSION_FILE); str_vers[0] = '\0'; str_date[0] = '\0'; } vfp = my_fopen(VERSION_FILE, "w", FALSE); if (vfp) { strftime(new_date, 40, "%d{078}-{178}%m{078}-{178}%Y", &mud->time); fwrite(new_vers, sizeof(char), 40, vfp); fwrite(new_date, sizeof(char), 40, vfp); fwrite(str_vers, sizeof(char), 40, vfp); fwrite(str_date, sizeof(char), 40, vfp); fflush(vfp); my_fclose(vfp); ch_printf_color(ch, "You set the version from %s to %s\n\r", str_vers, new_vers); log_printf("%s set the version from %s to %s", ch->name, str_vers, new_vers); pop_call(); return; } else { send_to_char("Failed to open the version file to write to.\n\r",ch); perror("Could not write version file to write to."); pop_call(); return; } } else { send_to_char("Syntax: version set <version number>\n\r",ch); pop_call(); return; } } pop_call(); return; } char *cut_at_eol(char *string) { int i=0; push_call("cut_at_eol(%p)",string); for(i=0;i<strlen(string);i++) { if(string[i] == '\n' || string[i] == '\r') { string[i] = '\0'; } } pop_call(); return string; }