Annotation of src/usr.bin/mg/log.c, Revision 1.2
1.2 ! lum 1: /* $OpenBSD: log.c,v 1.1 2019/06/10 06:52:44 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.
14: */
15:
16: #include <sys/queue.h>
17: #include <sys/stat.h>
18: #include <ctype.h>
19: #include <fcntl.h>
20: #include <signal.h>
21: #include <stdio.h>
22: #include <stdlib.h>
23: #include <string.h>
24: #include <unistd.h>
25:
26: #include "def.h"
27: #include "log.h"
28: #include "funmap.h"
29:
1.2 ! lum 30: char *mglogfiles_create(char *);
! 31: int mglog_lines(PF);
! 32: int mglog_undo(void);
! 33:
! 34: char *mglogdir;
! 35: extern char *mglogpath_lines;
! 36: extern char *mglogpath_undo;
! 37: int mgloglevel;
1.1 lum 38:
39: int
40: mglog(PF funct)
41: {
1.2 ! lum 42: if(!mglog_lines(funct))
! 43: ewprintf("Problem logging lines");
! 44: if(!mglog_undo())
! 45: ewprintf("Problem logging undo");
! 46:
! 47: return (TRUE);
! 48: }
! 49:
! 50:
! 51: int
! 52: mglog_undo(void)
! 53: {
! 54: struct undo_rec *rec;
! 55: struct stat sb;
! 56: FILE *fd;
! 57: char buf[4096], tmp[1024];
! 58: int num;
! 59: char *jptr;
! 60:
! 61: jptr = "^J"; /* :) */
! 62:
! 63: if(stat(mglogpath_undo, &sb))
! 64: return (FALSE);
! 65: fd = fopen(mglogpath_undo, "a");
! 66:
! 67: /*
! 68: * From undo_dump()
! 69: */
! 70: num = 0;
! 71: TAILQ_FOREACH(rec, &curbp->b_undo, next) {
! 72: num++;
! 73: if (fprintf(fd, "%d:\t %s at %d ", num,
! 74: (rec->type == DELETE) ? "DELETE":
! 75: (rec->type == DELREG) ? "DELREGION":
! 76: (rec->type == INSERT) ? "INSERT":
! 77: (rec->type == BOUNDARY) ? "----" :
! 78: (rec->type == MODIFIED) ? "MODIFIED": "UNKNOWN",
! 79: rec->pos) == -1) {
! 80: fclose(fd);
! 81: return (FALSE);
! 82: }
! 83: if (rec->content) {
! 84: (void)strlcat(buf, "\"", sizeof(buf));
! 85: snprintf(tmp, sizeof(tmp), "%.*s",
! 86: *rec->content == '\n' ? 2 : rec->region.r_size,
! 87: *rec->content == '\n' ? jptr : rec->content);
! 88: (void)strlcat(buf, tmp, sizeof(buf));
! 89: (void)strlcat(buf, "\"", sizeof(buf));
! 90: }
! 91: snprintf(tmp, sizeof(tmp), " [%d]", rec->region.r_size);
! 92: if (strlcat(buf, tmp, sizeof(buf)) >= sizeof(buf)) {
! 93: dobeep();
! 94: ewprintf("Undo record too large. Aborted.");
! 95: return (FALSE);
! 96: }
! 97: if (fprintf(fd, "%s\n", buf) == -1) {
! 98: fclose(fd);
! 99: return (FALSE);
! 100: }
! 101: tmp[0] = buf[0] = '\0';
! 102: }
! 103: if (fprintf(fd, "\t [end-of-undo]\n\n") == -1) {
! 104: fclose(fd);
! 105: return (FALSE);
! 106: }
! 107: fclose(fd);
! 108:
! 109: return (TRUE);
! 110: }
! 111:
! 112: int
! 113: mglog_lines(PF funct)
! 114: {
1.1 lum 115: struct line *lp;
116: struct stat sb;
117: char *curline;
118: FILE *fd;
119: int i;
120:
121: i = 0;
122:
1.2 ! lum 123: if(stat(mglogpath_lines, &sb))
1.1 lum 124: return (FALSE);
125:
1.2 ! lum 126: fd = fopen(mglogpath_lines, "a");
1.1 lum 127: if (fprintf(fd, "%s\n", function_name(funct)) == -1) {
128: fclose(fd);
129: return (FALSE);
130: }
131: lp = bfirstlp(curbp);
132:
133: for(;;) {
134: i++;
135: curline = " ";
136: if (i == curwp->w_dotline)
137: curline = ">";
138: if (fprintf(fd, "%s%p b^%p f.%p %d %d\t|%s\n", curline,
139: lp, lp->l_bp, lp->l_fp,
140: lp->l_size, lp->l_used, lp->l_text) == -1) {
141: fclose(fd);
142: return (FALSE);
143: }
144: lp = lforw(lp);
145: if (lp == curbp->b_headp) {
146: if (fprintf(fd, " %p b^%p f.%p [bhead]\n(EOB)\n",
147: lp, lp->l_bp, lp->l_fp) == -1) {
148: fclose(fd);
149: return (FALSE);
150: }
1.2 ! lum 151: if (fprintf(fd, "lines:raw:%d buf:%d wdot:%d\n\n",
1.1 lum 152: i, curbp->b_lines, curwp->w_dotline)) {
153: fclose(fd);
154: return (FALSE);
155: }
156: break;
157: }
158: }
159: fclose(fd);
160:
161: return (TRUE);
162: }
163:
164:
165: /*
1.2 ! lum 166: * Make sure logging to log files can happen.
1.1 lum 167: */
168: int
169: mgloginit(void)
170: {
171: struct stat sb;
172: mode_t dir_mode, f_mode, oumask;
1.2 ! lum 173: char *mglogfile_lines, *mglogfile_undo;
1.1 lum 174:
175: mglogdir = "./log/";
1.2 ! lum 176: mglogfile_lines = "line.log";
! 177: mglogfile_undo = "undo.log";
! 178:
! 179: /*
! 180: * Change mgloglevel for desired level of logging.
! 181: * log.h has relevant level info.
! 182: */
! 183: mgloglevel = 1;
1.1 lum 184:
185: oumask = umask(0);
186: f_mode = 0777& ~oumask;
187: dir_mode = f_mode | S_IWUSR | S_IXUSR;
188:
189: if(stat(mglogdir, &sb)) {
190: if (mkdir(mglogdir, dir_mode) != 0)
191: return (FALSE);
192: if (chmod(mglogdir, f_mode) < 0)
193: return (FALSE);
194: }
1.2 ! lum 195: mglogpath_lines = mglogfiles_create(mglogfile_lines);
! 196: if (mglogpath_lines == NULL)
1.1 lum 197: return (FALSE);
1.2 ! lum 198: mglogpath_undo = mglogfiles_create(mglogfile_undo);
! 199: if (mglogpath_undo == NULL)
1.1 lum 200: return (FALSE);
201:
1.2 ! lum 202: return (TRUE);
! 203: }
! 204:
! 205:
! 206: char *
! 207: mglogfiles_create(char *mglogfile)
! 208: {
! 209: struct stat sb;
! 210: char tmp[20], *tmp2;
! 211: int fd;
! 212:
! 213: if (strlcpy(tmp, mglogdir, sizeof(tmp)) >
! 214: sizeof(tmp))
! 215: return (NULL);
! 216: if (strlcat(tmp, mglogfile, sizeof(tmp)) >
! 217: sizeof(tmp))
! 218: return (NULL);
! 219: if ((tmp2 = strndup(tmp, 20)) == NULL)
! 220: return (NULL);
! 221:
! 222: if(stat(tmp2, &sb))
! 223: fd = open(tmp2, O_RDWR | O_CREAT | O_TRUNC, 0644);
1.1 lum 224: else
1.2 ! lum 225: fd = open(tmp2, O_RDWR | O_TRUNC, 0644);
1.1 lum 226:
227: if (fd == -1)
1.2 ! lum 228: return (NULL);
1.1 lum 229:
230: close(fd);
231:
1.2 ! lum 232: return (tmp2);
1.1 lum 233: }