[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.5

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