Annotation of src/usr.bin/mg/log.c, Revision 1.12
1.12 ! lum 1: /* $OpenBSD: log.c,v 1.11 2019/07/18 10:50:24 lum Exp $ */
1.1 lum 2:
3: /*
4: * This file is in the public domain.
5: *
6: * Author: Mark Lumsden <mark@showcomplex.com>
7: *
8: */
9:
10: /*
11: * Record a history of an mg session for temporal debugging.
12: * Sometimes pressing a key will set the scene for a bug only visible
13: * dozens of keystrokes later. gdb has its limitations in this scenario.
1.4 lum 14: *
15: * Note this file is not compiled into mg by default, you will need to
16: * amend the 'Makefile' for that to happen. Because of this, the code
1.8 lum 17: * is subject to bit-rot. However, I know myself and others have
1.4 lum 18: * written similar functionally often enough, that recording the below
19: * in a code repository could aid the developement efforts of mg, even
20: * if it requires a bit of effort to get working. The current code is
21: * written in the spirit of debugging (quickly and perhaps not ideal,
22: * but it does what is required well enough). Should debugging become
23: * more formalised within mg, then I would expect that to change.
1.6 lum 24: *
25: * If you open a file with long lines to run through this debugging
26: * code, you may run into problems with the 1st fprintf statement in
27: * in the mglog_lines() function. mg sometimes segvs at a strlen call
28: * in fprintf - possibly something to do with the format string?
29: * "%s%p b^%p f.%p %d %d\t%c|%s\n"
30: * When I get time I will look into it. But since my debugging
31: * generally revolves around a file like:
32: *
33: * abc
34: * def
35: * ghk
36: *
37: * I don't experience this bug. Just note it for future investigation.
1.1 lum 38: */
39:
40: #include <sys/queue.h>
41: #include <sys/stat.h>
42: #include <ctype.h>
43: #include <fcntl.h>
44: #include <signal.h>
45: #include <stdio.h>
46: #include <stdlib.h>
47: #include <string.h>
48: #include <unistd.h>
1.12 ! lum 49: #include <stdarg.h>
1.1 lum 50:
51: #include "def.h"
1.9 lum 52: #include "key.h"
53: #include "kbd.h"
54: #include "funmap.h"
55: #include "chrdef.h"
56:
1.1 lum 57: #include "log.h"
58:
1.12 ! lum 59: static char *mglogfiles_create(FILE **, char *);
1.11 lum 60: static int mglog_lines(PF);
61: static int mglog_undo(void);
62: static int mglog_window(void);
63: static int mglog_key(KEYMAP *map);
1.2 lum 64:
1.12 ! lum 65: const char *mglogdir;
! 66: const char *mglogpath_lines;
! 67: const char *mglogpath_undo;
! 68: const char *mglogpath_window;
! 69: const char *mglogpath_key;
! 70: const char *mglogpath_interpreter;
! 71: const char *mglogpath_misc;
1.2 lum 72: int mgloglevel;
1.1 lum 73:
1.12 ! lum 74: FILE *fd_lines;
! 75: FILE *fd_undo;
! 76: FILE *fd_window;
! 77: FILE *fd_key;
! 78: FILE *fd_interpreter;
! 79: FILE *fd_misc;
! 80:
1.1 lum 81: int
1.12 ! lum 82: mglog(PF funct, void *map)
1.1 lum 83: {
1.2 lum 84: if(!mglog_lines(funct))
85: ewprintf("Problem logging lines");
86: if(!mglog_undo())
87: ewprintf("Problem logging undo");
1.7 lum 88: if(!mglog_window())
89: ewprintf("Problem logging window");
1.9 lum 90: if(!mglog_key(map))
91: ewprintf("Problem logging key");
1.2 lum 92:
93: return (TRUE);
94: }
95:
96:
1.11 lum 97: static int
1.9 lum 98: mglog_key(KEYMAP *map)
99: {
100: PF *pfp;
101:
102: if (ISWORD(*key.k_chars)) {
1.12 ! lum 103: fprintf(fd_key, "k_count:%d k_chars:%hd\tchr:%c\t", key.k_count,
! 104: *key.k_chars, CHARMASK(*key.k_chars));
1.9 lum 105: } else {
1.12 ! lum 106: fprintf(fd_key, "k_count:%d k_chars:%hd\t\t", key.k_count,
! 107: *key.k_chars);
1.9 lum 108: }
1.12 ! lum 109: fprintf(fd_key, "map:%p %d %d %p %hd %hd\n",
1.9 lum 110: map,
111: map->map_num,
112: map->map_max,
113: map->map_default,
114: map->map_element->k_base,
115: map->map_element->k_num
1.12 ! lum 116: );
! 117: for (pfp = map->map_element->k_funcp; *pfp != NULL; pfp++)
! 118: fprintf(fd_key, "%s ", function_name(*pfp));
1.9 lum 119:
1.12 ! lum 120: fprintf(fd_key, "\n\n");
! 121: fflush(fd_key);
1.9 lum 122: return (TRUE);
123: }
124:
1.11 lum 125: static int
1.7 lum 126: mglog_window(void)
127: {
128: struct mgwin *wp;
129: int i;
130:
131: for (wp = wheadp, i = 0; wp != NULL; wp = wp->w_wndp, ++i) {
1.12 ! lum 132: fprintf(fd_window,
1.7 lum 133: "%d wh%p wlst%p wbfp%p wlp%p wdtp%p wmkp%p wdto%d wmko%d" \
134: " wtpr%d wntr%d wfrm%d wrfl%c wflg%c wwrl%p wdtl%d" \
135: " wmkl%d\n",
136: i,
137: wp,
138: &wp->w_list,
139: wp->w_bufp,
140: wp->w_linep,
141: wp->w_dotp,
142: wp->w_markp,
143: wp->w_doto,
144: wp->w_marko,
145: wp->w_toprow,
146: wp->w_ntrows,
147: wp->w_frame,
148: wp->w_rflag,
149: wp->w_flag,
150: wp->w_wrapline,
151: wp->w_dotline,
1.12 ! lum 152: wp->w_markline
! 153: );
1.7 lum 154: }
1.12 ! lum 155: fflush(fd_window);
1.7 lum 156: return (TRUE);
157: }
158:
1.11 lum 159: static int
1.2 lum 160: mglog_undo(void)
161: {
162: struct undo_rec *rec;
163: char buf[4096], tmp[1024];
164: int num;
165: char *jptr;
166:
167: jptr = "^J"; /* :) */
168: /*
169: * From undo_dump()
170: */
171: num = 0;
172: TAILQ_FOREACH(rec, &curbp->b_undo, next) {
173: num++;
1.12 ! lum 174: fprintf(fd_undo, "%d:\t %s at %d ", num,
1.2 lum 175: (rec->type == DELETE) ? "DELETE":
176: (rec->type == DELREG) ? "DELREGION":
177: (rec->type == INSERT) ? "INSERT":
178: (rec->type == BOUNDARY) ? "----" :
179: (rec->type == MODIFIED) ? "MODIFIED": "UNKNOWN",
1.12 ! lum 180: rec->pos
! 181: );
1.2 lum 182: if (rec->content) {
183: (void)strlcat(buf, "\"", sizeof(buf));
184: snprintf(tmp, sizeof(tmp), "%.*s",
185: *rec->content == '\n' ? 2 : rec->region.r_size,
186: *rec->content == '\n' ? jptr : rec->content);
187: (void)strlcat(buf, tmp, sizeof(buf));
188: (void)strlcat(buf, "\"", sizeof(buf));
189: }
190: snprintf(tmp, sizeof(tmp), " [%d]", rec->region.r_size);
191: if (strlcat(buf, tmp, sizeof(buf)) >= sizeof(buf)) {
192: dobeep();
193: ewprintf("Undo record too large. Aborted.");
194: return (FALSE);
195: }
1.12 ! lum 196: fprintf(fd_undo, "%s\n", buf);
1.2 lum 197: tmp[0] = buf[0] = '\0';
198: }
1.12 ! lum 199: fprintf(fd_undo, "\t [end-of-undo]\n\n");
! 200: fflush(fd_undo);
1.2 lum 201:
202: return (TRUE);
203: }
204:
1.11 lum 205: static int
1.2 lum 206: mglog_lines(PF funct)
207: {
1.1 lum 208: struct line *lp;
1.5 lum 209: char *curline, *tmp, o;
1.1 lum 210: int i;
211:
212: i = 0;
213:
1.12 ! lum 214: fprintf(fd_lines, "%s\n", function_name(funct));
1.1 lum 215: lp = bfirstlp(curbp);
216:
217: for(;;) {
218: i++;
219: curline = " ";
1.5 lum 220: o = ' ';
221: if (i == curwp->w_dotline) {
1.1 lum 222: curline = ">";
1.5 lum 223: if (lp->l_used > 0 && curwp->w_doto < lp->l_used)
224: o = lp->l_text[curwp->w_doto];
225: else
226: o = '-';
227: }
228: if (lp->l_size == 0)
229: tmp = " ";
230: else
231: tmp = lp->l_text;
232:
1.6 lum 233: /* segv on fprintf below with long lines */
1.12 ! lum 234: fprintf(fd_lines, "%s%p b^%p f.%p %d %d\t%c|%s\n", curline,
1.1 lum 235: lp, lp->l_bp, lp->l_fp,
1.12 ! lum 236: lp->l_size, lp->l_used, o, tmp);
! 237:
1.1 lum 238: lp = lforw(lp);
239: if (lp == curbp->b_headp) {
1.12 ! lum 240: fprintf(fd_lines, " %p b^%p f.%p [bhead]\n(EOB)\n",
! 241: lp, lp->l_bp, lp->l_fp);
! 242:
! 243: fprintf(fd_lines, "lines:raw:%d buf:%d wdot:%d\n\n",
! 244: i, curbp->b_lines, curwp->w_dotline);
! 245:
1.1 lum 246: break;
247: }
248: }
1.12 ! lum 249: fflush(fd_lines);
1.1 lum 250:
251: return (TRUE);
252: }
253:
1.11 lum 254: /*
255: * See what the eval variable code is up to.
256: */
257: int
258: mglog_isvar(
259: const char* const argbuf,
260: const char* const argp,
261: const int sizof
262: )
263: {
264:
1.12 ! lum 265: fprintf(fd_interpreter, " argbuf:%s,argp:%s,sizof:%d<\n",
1.11 lum 266: argbuf,
267: argp,
1.12 ! lum 268: sizof);
! 269:
! 270: fflush(fd_interpreter);
1.11 lum 271: return (TRUE);
272: }
273:
274: /*
275: * See what the eval line code is up to.
276: */
277: int
278: mglog_execbuf(
279: const char* const pre,
280: const char* const excbuf,
281: const char* const argbuf,
282: const char* const argp,
283: const int last,
284: const int inlist,
285: const char* const cmdp,
286: const char* const p,
287: const char* const contbuf
288: )
289: {
1.12 ! lum 290: fprintf(fd_interpreter, "%sexcbuf:%s,argbuf:%s,argp:%s,last:%d,inlist:%d,"\
1.11 lum 291: "cmdp:%s,p:%s,contbuf:%s<\n",
292: pre,
293: excbuf,
294: argbuf,
295: argp,
296: last,
297: inlist,
298: cmdp,
299: p,
300: contbuf
1.12 ! lum 301: );
! 302: fflush(fd_interpreter);
! 303: return (TRUE);
! 304: }
! 305:
! 306: /*
! 307: * Misc. logging for various subsystems
! 308: */
! 309: int
! 310: mglog_misc(
! 311: const char *fmt,
! 312: ...
! 313: )
! 314: {
! 315: va_list ap;
! 316: int rc;
! 317:
! 318: va_start(ap, fmt);
! 319: rc = vfprintf(fd_misc, fmt, ap);
! 320: va_end(ap);
! 321: fflush(fd_misc);
! 322:
! 323: if (rc < 0)
1.11 lum 324: return (FALSE);
1.12 ! lum 325:
1.11 lum 326: return (TRUE);
327: }
1.1 lum 328:
1.12 ! lum 329:
! 330:
1.1 lum 331: /*
1.2 lum 332: * Make sure logging to log files can happen.
1.1 lum 333: */
334: int
335: mgloginit(void)
336: {
337: struct stat sb;
338: mode_t dir_mode, f_mode, oumask;
1.7 lum 339: char *mglogfile_lines, *mglogfile_undo, *mglogfile_window;
1.12 ! lum 340: char *mglogfile_key, *mglogfile_interpreter, *mglogfile_misc;
1.1 lum 341:
342: mglogdir = "./log/";
1.2 lum 343: mglogfile_lines = "line.log";
344: mglogfile_undo = "undo.log";
1.7 lum 345: mglogfile_window = "window.log";
1.9 lum 346: mglogfile_key = "key.log";
1.11 lum 347: mglogfile_interpreter = "interpreter.log";
1.12 ! lum 348: mglogfile_misc = "misc.log";
1.2 lum 349:
350: /*
351: * Change mgloglevel for desired level of logging.
352: * log.h has relevant level info.
353: */
354: mgloglevel = 1;
1.1 lum 355:
356: oumask = umask(0);
357: f_mode = 0777& ~oumask;
358: dir_mode = f_mode | S_IWUSR | S_IXUSR;
359:
360: if(stat(mglogdir, &sb)) {
361: if (mkdir(mglogdir, dir_mode) != 0)
362: return (FALSE);
1.10 deraadt 363: if (chmod(mglogdir, f_mode) == -1)
1.1 lum 364: return (FALSE);
365: }
1.12 ! lum 366: mglogpath_lines = mglogfiles_create(&fd_lines, mglogfile_lines);
1.2 lum 367: if (mglogpath_lines == NULL)
1.1 lum 368: return (FALSE);
1.12 ! lum 369: mglogpath_undo = mglogfiles_create(&fd_undo, mglogfile_undo);
1.2 lum 370: if (mglogpath_undo == NULL)
1.7 lum 371: return (FALSE);
1.12 ! lum 372: mglogpath_window = mglogfiles_create(&fd_window, mglogfile_window);
1.7 lum 373: if (mglogpath_window == NULL)
1.1 lum 374: return (FALSE);
1.12 ! lum 375: mglogpath_key = mglogfiles_create(&fd_key, mglogfile_key);
1.9 lum 376: if (mglogpath_key == NULL)
377: return (FALSE);
1.12 ! lum 378: mglogpath_interpreter = mglogfiles_create(&fd_interpreter,
! 379: mglogfile_interpreter);
1.11 lum 380: if (mglogpath_interpreter == NULL)
381: return (FALSE);
1.12 ! lum 382: mglogpath_misc = mglogfiles_create(&fd_misc, mglogfile_misc);
! 383: if (mglogpath_misc == NULL)
! 384: return (FALSE);
1.1 lum 385:
1.2 lum 386: return (TRUE);
387: }
388:
389:
1.11 lum 390: static char *
1.12 ! lum 391: mglogfiles_create(FILE ** fd, char *mglogfile)
1.2 lum 392: {
1.11 lum 393: char tmp[NFILEN], *tmp2;
1.2 lum 394:
395: if (strlcpy(tmp, mglogdir, sizeof(tmp)) >
396: sizeof(tmp))
397: return (NULL);
398: if (strlcat(tmp, mglogfile, sizeof(tmp)) >
399: sizeof(tmp))
400: return (NULL);
1.11 lum 401: if ((tmp2 = strndup(tmp, NFILEN)) == NULL)
1.2 lum 402: return (NULL);
403:
1.12 ! lum 404: if ((*fd = fopen(tmp2, "w")) == NULL)
1.2 lum 405: return (NULL);
1.1 lum 406:
1.2 lum 407: return (tmp2);
1.1 lum 408: }