[BACK]Return to log.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/log.c, Revision 1.7

1.7     ! lum         1: /*     $OpenBSD: log.c,v 1.6 2019/06/14 14:27:42 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
                     17:  * is subjet to bit-rot. However, I know myself and others have
                     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>
                     49:
                     50: #include "def.h"
                     51: #include "log.h"
                     52: #include "funmap.h"
                     53:
1.2       lum        54: char   *mglogfiles_create(char *);
                     55: int     mglog_lines(PF);
                     56: int     mglog_undo(void);
1.7     ! lum        57: int     mglog_window(void);
1.2       lum        58:
                     59: char           *mglogdir;
                     60: extern char    *mglogpath_lines;
                     61: extern char    *mglogpath_undo;
1.7     ! lum        62: extern char    *mglogpath_window;
1.2       lum        63: int             mgloglevel;
1.1       lum        64:
                     65: int
                     66: mglog(PF funct)
                     67: {
1.2       lum        68:        if(!mglog_lines(funct))
                     69:                ewprintf("Problem logging lines");
                     70:        if(!mglog_undo())
                     71:                ewprintf("Problem logging undo");
1.7     ! lum        72:        if(!mglog_window())
        !            73:                ewprintf("Problem logging window");
1.2       lum        74:
                     75:        return (TRUE);
                     76: }
                     77:
                     78:
                     79: int
1.7     ! lum        80: mglog_window(void)
        !            81: {
        !            82:        struct mgwin    *wp;
        !            83:        struct stat      sb;
        !            84:        FILE            *fd;
        !            85:        int              i;
        !            86:
        !            87:        if(stat(mglogpath_window, &sb))
        !            88:                return (FALSE);
        !            89:        fd = fopen(mglogpath_window, "a");
        !            90:
        !            91:        for (wp = wheadp, i = 0; wp != NULL; wp = wp->w_wndp, ++i) {
        !            92:                if (fprintf(fd,
        !            93:                    "%d wh%p wlst%p wbfp%p wlp%p wdtp%p wmkp%p wdto%d wmko%d" \
        !            94:                    " wtpr%d wntr%d wfrm%d wrfl%c wflg%c wwrl%p wdtl%d" \
        !            95:                    " wmkl%d\n",
        !            96:                    i,
        !            97:                    wp,
        !            98:                    &wp->w_list,
        !            99:                    wp->w_bufp,
        !           100:                    wp->w_linep,
        !           101:                    wp->w_dotp,
        !           102:                    wp->w_markp,
        !           103:                    wp->w_doto,
        !           104:                    wp->w_marko,
        !           105:                    wp->w_toprow,
        !           106:                    wp->w_ntrows,
        !           107:                    wp->w_frame,
        !           108:                    wp->w_rflag,
        !           109:                    wp->w_flag,
        !           110:                    wp->w_wrapline,
        !           111:                    wp->w_dotline,
        !           112:                    wp->w_markline) == -1) {
        !           113:                        fclose(fd);
        !           114:                        return (FALSE);
        !           115:                }
        !           116:        }
        !           117:        fclose(fd);
        !           118:        return (TRUE);
        !           119: }
        !           120:
        !           121: int
1.2       lum       122: mglog_undo(void)
                    123: {
                    124:        struct undo_rec *rec;
                    125:        struct stat      sb;
                    126:        FILE            *fd;
                    127:        char             buf[4096], tmp[1024];
                    128:        int              num;
                    129:        char            *jptr;
                    130:
                    131:        jptr = "^J"; /* :) */
                    132:
                    133:        if(stat(mglogpath_undo, &sb))
                    134:                return (FALSE);
                    135:        fd = fopen(mglogpath_undo, "a");
                    136:
                    137:        /*
                    138:         * From undo_dump()
                    139:         */
                    140:        num = 0;
                    141:        TAILQ_FOREACH(rec, &curbp->b_undo, next) {
                    142:                num++;
                    143:                if (fprintf(fd, "%d:\t %s at %d ", num,
                    144:                    (rec->type == DELETE) ? "DELETE":
                    145:                    (rec->type == DELREG) ? "DELREGION":
                    146:                    (rec->type == INSERT) ? "INSERT":
                    147:                    (rec->type == BOUNDARY) ? "----" :
                    148:                    (rec->type == MODIFIED) ? "MODIFIED": "UNKNOWN",
                    149:                    rec->pos) == -1) {
                    150:                        fclose(fd);
                    151:                        return (FALSE);
                    152:                }
                    153:                if (rec->content) {
                    154:                        (void)strlcat(buf, "\"", sizeof(buf));
                    155:                        snprintf(tmp, sizeof(tmp), "%.*s",
                    156:                            *rec->content == '\n' ? 2 : rec->region.r_size,
                    157:                            *rec->content == '\n' ? jptr : rec->content);
                    158:                        (void)strlcat(buf, tmp, sizeof(buf));
                    159:                        (void)strlcat(buf, "\"", sizeof(buf));
                    160:                }
                    161:                snprintf(tmp, sizeof(tmp), " [%d]", rec->region.r_size);
                    162:                if (strlcat(buf, tmp, sizeof(buf)) >= sizeof(buf)) {
                    163:                        dobeep();
                    164:                        ewprintf("Undo record too large. Aborted.");
                    165:                        return (FALSE);
                    166:                }
                    167:                if (fprintf(fd, "%s\n", buf) == -1) {
                    168:                        fclose(fd);
                    169:                        return (FALSE);
                    170:                }
                    171:                tmp[0] = buf[0] = '\0';
                    172:        }
                    173:        if (fprintf(fd, "\t [end-of-undo]\n\n") == -1) {
                    174:                fclose(fd);
                    175:                return (FALSE);
                    176:        }
                    177:        fclose(fd);
                    178:
                    179:        return (TRUE);
                    180: }
                    181:
                    182: int
                    183: mglog_lines(PF funct)
                    184: {
1.1       lum       185:        struct line     *lp;
                    186:        struct stat      sb;
1.5       lum       187:        char            *curline, *tmp, o;
1.1       lum       188:        FILE            *fd;
                    189:        int              i;
                    190:
                    191:        i = 0;
                    192:
1.2       lum       193:        if(stat(mglogpath_lines, &sb))
1.1       lum       194:                return (FALSE);
                    195:
1.2       lum       196:        fd = fopen(mglogpath_lines, "a");
1.1       lum       197:        if (fprintf(fd, "%s\n", function_name(funct)) == -1) {
                    198:                fclose(fd);
                    199:                return (FALSE);
                    200:        }
                    201:        lp = bfirstlp(curbp);
                    202:
                    203:        for(;;) {
                    204:                i++;
                    205:                curline = " ";
1.5       lum       206:                o = ' ';
                    207:                if (i == curwp->w_dotline) {
1.1       lum       208:                        curline = ">";
1.5       lum       209:                        if (lp->l_used > 0 && curwp->w_doto < lp->l_used)
                    210:                                o = lp->l_text[curwp->w_doto];
                    211:                        else
                    212:                                o = '-';
                    213:                }
                    214:                if (lp->l_size == 0)
                    215:                        tmp = " ";
                    216:                else
                    217:                        tmp = lp->l_text;
                    218:
1.6       lum       219:                /* segv on fprintf below with long lines */
1.5       lum       220:                if (fprintf(fd, "%s%p b^%p f.%p %d %d\t%c|%s\n", curline,
1.1       lum       221:                    lp, lp->l_bp, lp->l_fp,
1.5       lum       222:                    lp->l_size, lp->l_used, o, tmp) == -1) {
1.1       lum       223:                        fclose(fd);
                    224:                        return (FALSE);
                    225:                }
                    226:                lp = lforw(lp);
                    227:                if (lp == curbp->b_headp) {
                    228:                        if (fprintf(fd, " %p b^%p f.%p [bhead]\n(EOB)\n",
                    229:                            lp, lp->l_bp, lp->l_fp) == -1) {
                    230:                                fclose(fd);
                    231:                                return (FALSE);
                    232:                        }
1.2       lum       233:                        if (fprintf(fd, "lines:raw:%d buf:%d wdot:%d\n\n",
1.3       lum       234:                            i, curbp->b_lines, curwp->w_dotline) == -1) {
1.1       lum       235:                                fclose(fd);
                    236:                                return (FALSE);
                    237:                        }
                    238:                        break;
                    239:                }
                    240:        }
                    241:        fclose(fd);
                    242:
                    243:        return (TRUE);
                    244: }
                    245:
                    246:
                    247: /*
1.2       lum       248:  * Make sure logging to log files can happen.
1.1       lum       249:  */
                    250: int
                    251: mgloginit(void)
                    252: {
                    253:        struct stat      sb;
                    254:        mode_t           dir_mode, f_mode, oumask;
1.7     ! lum       255:        char            *mglogfile_lines, *mglogfile_undo, *mglogfile_window;
1.1       lum       256:
                    257:        mglogdir = "./log/";
1.2       lum       258:        mglogfile_lines = "line.log";
                    259:        mglogfile_undo = "undo.log";
1.7     ! lum       260:        mglogfile_window = "window.log";
1.2       lum       261:
                    262:        /*
                    263:         * Change mgloglevel for desired level of logging.
                    264:         * log.h has relevant level info.
                    265:         */
                    266:        mgloglevel = 1;
1.1       lum       267:
                    268:        oumask = umask(0);
                    269:        f_mode = 0777& ~oumask;
                    270:        dir_mode = f_mode | S_IWUSR | S_IXUSR;
                    271:
                    272:        if(stat(mglogdir, &sb)) {
                    273:                if (mkdir(mglogdir, dir_mode) != 0)
                    274:                        return (FALSE);
                    275:                if (chmod(mglogdir, f_mode) < 0)
                    276:                        return (FALSE);
                    277:        }
1.2       lum       278:        mglogpath_lines = mglogfiles_create(mglogfile_lines);
                    279:        if (mglogpath_lines == NULL)
1.1       lum       280:                return (FALSE);
1.2       lum       281:        mglogpath_undo = mglogfiles_create(mglogfile_undo);
                    282:        if (mglogpath_undo == NULL)
1.7     ! lum       283:                return (FALSE);
        !           284:        mglogpath_window = mglogfiles_create(mglogfile_window);
        !           285:        if (mglogpath_window == NULL)
1.1       lum       286:                return (FALSE);
                    287:
1.2       lum       288:        return (TRUE);
                    289: }
                    290:
                    291:
                    292: char *
                    293: mglogfiles_create(char *mglogfile)
                    294: {
                    295:        struct stat      sb;
                    296:        char             tmp[20], *tmp2;
                    297:        int              fd;
                    298:
                    299:        if (strlcpy(tmp, mglogdir, sizeof(tmp)) >
                    300:            sizeof(tmp))
                    301:                return (NULL);
                    302:        if (strlcat(tmp, mglogfile, sizeof(tmp)) >
                    303:            sizeof(tmp))
                    304:                return (NULL);
                    305:        if ((tmp2 = strndup(tmp, 20)) == NULL)
                    306:                return (NULL);
                    307:
                    308:        if(stat(tmp2, &sb))
                    309:                fd = open(tmp2, O_RDWR | O_CREAT | O_TRUNC, 0644);
1.1       lum       310:        else
1.2       lum       311:                fd = open(tmp2, O_RDWR | O_TRUNC, 0644);
1.1       lum       312:
                    313:        if (fd == -1)
1.2       lum       314:                return (NULL);
1.1       lum       315:
                    316:        close(fd);
                    317:
1.2       lum       318:        return (tmp2);
1.1       lum       319: }