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

Annotation of src/usr.bin/mg/main.c, Revision 1.96

1.96    ! op          1: /*     $OpenBSD: main.c,v 1.95 2023/04/14 15:34:08 tb Exp $    */
1.40      kjell       2:
                      3: /* This file is in the public domain. */
1.6       niklas      4:
1.1       deraadt     5: /*
1.5       millert     6:  *     Mainline.
1.1       deraadt     7:  */
1.5       millert     8:
1.75      bcallah     9: #include <sys/queue.h>
                     10: #include <err.h>
                     11: #include <limits.h>
                     12: #include <locale.h>
                     13: #include <signal.h>
                     14: #include <stdio.h>
                     15: #include <stdlib.h>
                     16: #include <string.h>
1.89      lum        17: #include <termios.h>
1.75      bcallah    18: #include <unistd.h>
1.89      lum        19: #include <util.h>
1.75      bcallah    20:
1.38      db         21: #include "def.h"
                     22: #include "kbd.h"
                     23: #include "funmap.h"
                     24: #include "macro.h"
1.24      vincent    25:
1.86      lum        26: #ifdef  MGLOG
                     27: #include "log.h"
                     28: #endif
                     29:
1.5       millert    30: int             thisflag;                      /* flags, this command  */
                     31: int             lastflag;                      /* flags, last command  */
                     32: int             curgoal;                       /* goal column          */
1.36      deraadt    33: int             startrow;                      /* row to start         */
1.71      lum        34: int             doaudiblebell;                 /* audible bell toggle  */
                     35: int             dovisiblebell;                 /* visible bell toggle  */
1.82      lum        36: int             dblspace;                      /* sentence end #spaces */
1.85      lum        37: int             allbro;                        /* all buffs read-only  */
1.89      lum        38: int             batch;                         /* for regress tests    */
1.55      deraadt    39: struct buffer  *curbp;                         /* current buffer       */
1.53      kjell      40: struct buffer  *bheadp;                        /* BUFFER list head     */
                     41: struct mgwin   *curwp;                         /* current window       */
                     42: struct mgwin   *wheadp;                        /* MGWIN listhead       */
1.90      lum        43: struct vhead    varhead;                       /* Variable list head   */
1.5       millert    44: char            pat[NPAT];                     /* pattern              */
1.1       deraadt    45:
1.66      lum        46: static void     edinit(struct buffer *);
1.89      lum        47: static void     pty_init(void);
1.53      kjell      48: static __dead void usage(void);
                     49:
                     50: extern char    *__progname;
1.62      lum        51: extern void     closetags(void);
1.53      kjell      52:
                     53: static __dead void
1.95      tb         54: usage(void)
1.53      kjell      55: {
1.89      lum        56:        fprintf(stderr, "usage: %s [-nR] [-b file] [-f mode] [-u file] "
                     57:            "[+number] [file ...]\n",
1.53      kjell      58:            __progname);
                     59:        exit(1);
                     60: }
1.1       deraadt    61:
1.2       deraadt    62: int
1.19      vincent    63: main(int argc, char **argv)
1.1       deraadt    64: {
1.93      op         65:        FILE            *ffp;
                     66:        char             file[NFILEN];
1.88      lum        67:        char            *cp, *conffile = NULL, *init_fcn_name = NULL;
1.89      lum        68:        char            *batchfile = NULL;
1.66      lum        69:        PF               init_fcn = NULL;
                     70:        int              o, i, nfiles;
1.85      lum        71:        int              nobackups = 0;
1.66      lum        72:        struct buffer   *bp = NULL;
1.78      deraadt    73:
1.83      semarie    74:        if (pledge("stdio rpath wpath cpath fattr chown getpw tty proc exec",
                     75:            NULL) == -1)
1.78      deraadt    76:                err(1, "pledge");
1.24      vincent    77:
1.89      lum        78:        while ((o = getopt(argc, argv, "nRb:f:u:")) != -1)
1.24      vincent    79:                switch (o) {
1.89      lum        80:                case 'b':
                     81:                        batch = 1;
                     82:                        batchfile = optarg;
                     83:                        break;
1.81      lum        84:                case 'R':
1.85      lum        85:                        allbro = 1;
1.81      lum        86:                        break;
1.35      henning    87:                case 'n':
                     88:                        nobackups = 1;
                     89:                        break;
1.24      vincent    90:                case 'f':
                     91:                        if (init_fcn_name != NULL)
                     92:                                errx(1, "cannot specify more than one "
                     93:                                    "initial function");
                     94:                        init_fcn_name = optarg;
                     95:                        break;
1.88      lum        96:                case 'u':
                     97:                        conffile = optarg;
                     98:                        break;
1.24      vincent    99:                default:
1.53      kjell     100:                        usage();
1.24      vincent   101:                }
1.89      lum       102:
                    103:        if (batch && (conffile != NULL)) {
                    104:                 fprintf(stderr, "%s: -b and -u are mutually exclusive.\n",
                    105:                     __progname);
                    106:                 exit(1);
                    107:        }
                    108:        if (batch) {
                    109:                pty_init();
                    110:                conffile = batchfile;
                    111:        }
1.93      op        112:        if ((ffp = startupfile(NULL, conffile, file, sizeof(file))) == NULL &&
                    113:            conffile != NULL) {
1.94      op        114:                fprintf(stderr, "%s: Problem with file: %s\n", __progname,
1.89      lum       115:                    conffile);
1.94      op        116:                exit(1);
1.89      lum       117:        }
                    118:
1.24      vincent   119:        argc -= optind;
                    120:        argv += optind;
1.70      naddy     121:
                    122:        setlocale(LC_CTYPE, "");
1.1       deraadt   123:
1.12      art       124:        maps_init();            /* Keymaps and modes.           */
1.11      art       125:        funmap_init();          /* Functions.                   */
1.86      lum       126:
                    127: #ifdef  MGLOG
                    128:        if (!mgloginit())
                    129:                errx(1, "Unable to create logging environment.");
                    130: #endif
1.19      vincent   131:
1.13      art       132:        /*
                    133:         * This is where we initialize standalone extensions that should
                    134:         * be loaded dynamically sometime in the future.
                    135:         */
                    136:        {
                    137:                extern void grep_init(void);
1.58      kjell     138:                extern void cmode_init(void);
1.42      kjell     139:                extern void dired_init(void);
1.13      art       140:
1.42      kjell     141:                dired_init();
1.13      art       142:                grep_init();
1.58      kjell     143:                cmode_init();
1.13      art       144:        }
1.5       millert   145:
1.24      vincent   146:        if (init_fcn_name &&
                    147:            (init_fcn = name_function(init_fcn_name)) == NULL)
                    148:                errx(1, "Unknown function `%s'", init_fcn_name);
                    149:
                    150:        vtinit();               /* Virtual terminal.            */
                    151:        dirinit();              /* Get current directory.       */
1.66      lum       152:        edinit(bp);             /* Buffers, windows.            */
1.24      vincent   153:        ttykeymapinit();        /* Symbols, bindings.           */
1.71      lum       154:        bellinit();             /* Audible and visible bell.    */
1.82      lum       155:        dblspace = 1;           /* two spaces for sentence end. */
1.24      vincent   156:
1.4       millert   157:        /*
                    158:         * doing update() before reading files causes the error messages from
                    159:         * the file I/O show up on the screen.  (and also an extra display of
                    160:         * the mode line if there are files specified on the command line.)
1.1       deraadt   161:         */
1.71      lum       162:        update(CMODE);
1.5       millert   163:
1.65      lum       164:        /* user startup file. */
1.93      op        165:        if (ffp != NULL) {
                    166:                (void)load(ffp, file);
                    167:                ffclose(ffp, NULL);
                    168:        }
1.65      lum       169:
1.96    ! op        170:        if (batch) {
        !           171:                vttidy();
1.89      lum       172:                return (0);
1.96    ! op        173:        }
1.89      lum       174:
1.77      jasper    175:        /*
1.65      lum       176:         * Now ensure any default buffer modes from the startup file are
                    177:         * given to any files opened when parsing the startup file.
                    178:         * Note *scratch* will also be updated.
                    179:         */
                    180:        for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
                    181:                bp->b_flag = defb_flag;
                    182:                for (i = 0; i <= defb_nmodes; i++) {
                    183:                        bp->b_modes[i] = defb_modes[i];
                    184:                }
                    185:        }
1.59      kjell     186:
                    187:        /* Force FFOTHARG=1 so that this mode is enabled, not simply toggled */
                    188:        if (init_fcn)
                    189:                init_fcn(FFOTHARG, 1);
                    190:
1.35      henning   191:        if (nobackups)
                    192:                makebkfile(FFARG, 0);
1.27      vincent   193:
                    194:        for (nfiles = 0, i = 0; i < argc; i++) {
                    195:                if (argv[i][0] == '+' && strlen(argv[i]) >= 2) {
1.43      deraadt   196:                        long long lval;
1.30      pvalchev  197:                        const char *errstr;
1.23      deraadt   198:
1.32      vincent   199:                        lval = strtonum(&argv[i][1], INT_MIN, INT_MAX, &errstr);
1.33      vincent   200:                        if (argv[i][1] == '\0' || errstr != NULL)
1.23      deraadt   201:                                goto notnum;
1.30      pvalchev  202:                        startrow = lval;
1.24      vincent   203:                } else {
1.23      deraadt   204: notnum:
1.52      jason     205:                        cp = adjustname(argv[i], FALSE);
1.24      vincent   206:                        if (cp != NULL) {
1.38      db        207:                                if (nfiles == 1)
1.27      vincent   208:                                        splitwind(0, 1);
1.38      db        209:
1.76      lum       210:                                if (fisdir(cp) == TRUE) {
                    211:                                        (void)do_dired(cp);
1.77      jasper    212:                                        continue;
1.76      lum       213:                                }
1.39      beck      214:                                if ((curbp = findbuffer(cp)) == NULL) {
                    215:                                        vttidy();
                    216:                                        errx(1, "Can't find current buffer!");
                    217:                                }
1.24      vincent   218:                                (void)showbuffer(curbp, curwp, 0);
1.44      deraadt   219:                                if (readin(cp) != TRUE)
1.34      jfb       220:                                        killbuffer(curbp);
1.38      db        221:                                else {
1.59      kjell     222:                                        /* Ensure enabled, not just toggled */
1.34      jfb       223:                                        if (init_fcn_name)
1.59      kjell     224:                                                init_fcn(FFOTHARG, 1);
1.34      jfb       225:                                        nfiles++;
                    226:                                }
1.85      lum       227:                                if (allbro)
1.81      lum       228:                                        curbp->b_flag |= BFREADONLY;
1.24      vincent   229:                        }
1.22      vincent   230:                }
1.1       deraadt   231:        }
1.29      vincent   232:
                    233:        if (nfiles > 2)
                    234:                listbuffers(0, 1);
1.5       millert   235:
                    236:        /* fake last flags */
                    237:        thisflag = 0;
1.4       millert   238:        for (;;) {
1.50      kjell     239:                if (epresf == KCLEAR)
1.4       millert   240:                        eerase();
1.50      kjell     241:                if (epresf == TRUE)
                    242:                        epresf = KCLEAR;
1.17      deraadt   243:                if (winch_flag) {
1.49      otto      244:                        do_redraw(0, 0, TRUE);
1.17      deraadt   245:                        winch_flag = 0;
                    246:                }
1.71      lum       247:                update(CMODE);
1.4       millert   248:                lastflag = thisflag;
                    249:                thisflag = 0;
1.5       millert   250:
1.4       millert   251:                switch (doin()) {
                    252:                case TRUE:
                    253:                        break;
1.1       deraadt   254:                case ABORT:
1.5       millert   255:                        ewprintf("Quit");
1.48      kjell     256:                        /* FALLTHRU */
1.1       deraadt   257:                case FALSE:
                    258:                default:
1.4       millert   259:                        macrodef = FALSE;
                    260:                }
1.1       deraadt   261:        }
                    262: }
                    263:
                    264: /*
1.66      lum       265:  * Initialize default buffer and window. Default buffer is called *scratch*.
1.1       deraadt   266:  */
1.7       art       267: static void
1.66      lum       268: edinit(struct buffer *bp)
1.4       millert   269: {
1.45      deraadt   270:        struct mgwin    *wp;
1.1       deraadt   271:
                    272:        bheadp = NULL;
1.66      lum       273:        bp = bfind("*scratch*", TRUE);          /* Text buffer.          */
1.63      lum       274:        if (bp == NULL)
                    275:                panic("edinit");
                    276:
1.26      vincent   277:        wp = new_window(bp);
1.21      vincent   278:        if (wp == NULL)
1.66      lum       279:                panic("edinit: Out of memory");
1.63      lum       280:
1.66      lum       281:        curbp = bp;                             /* Current buffer.       */
1.1       deraadt   282:        wheadp = wp;
1.4       millert   283:        curwp = wp;
1.5       millert   284:        wp->w_wndp = NULL;                      /* Initialize window.    */
1.54      kjell     285:        wp->w_linep = wp->w_dotp = bp->b_headp;
1.38      db        286:        wp->w_ntrows = nrow - 2;                /* 2 = mode, echo.       */
1.61      kjell     287:        wp->w_rflag = WFMODE | WFFULL;          /* Full.                 */
1.89      lum       288: }
                    289:
                    290: /*
                    291:  * Create pty for batch mode.
                    292:  */
                    293: static void
                    294: pty_init(void)
                    295: {
                    296:        struct winsize   ws;
                    297:        int              master;
                    298:        int              slave;
                    299:
                    300:        memset(&ws, 0, sizeof(ws));
                    301:        ws.ws_col = 80,
                    302:        ws.ws_row = 24;
1.92      op        303:
1.89      lum       304:        openpty(&master, &slave, NULL, NULL, &ws);
                    305:        login_tty(slave);
                    306:
                    307:        return;
1.1       deraadt   308: }
                    309:
                    310: /*
1.5       millert   311:  * Quit command.  If an argument, always quit.  Otherwise confirm if a buffer
1.87      lum       312:  * has been changed and not written out.  Normally bound to "C-x C-c".
1.1       deraadt   313:  */
1.5       millert   314: int
1.20      vincent   315: quit(int f, int n)
1.1       deraadt   316: {
1.5       millert   317:        int      s;
1.1       deraadt   318:
1.4       millert   319:        if ((s = anycb(FALSE)) == ABORT)
1.38      db        320:                return (ABORT);
1.69      lum       321:        if (s == FIOERR || s == UERROR)
1.68      lum       322:                return (FALSE);
1.1       deraadt   323:        if (s == FALSE
1.41      kjell     324:            || eyesno("Modified buffers exist; really exit") == TRUE) {
1.1       deraadt   325:                vttidy();
1.62      lum       326:                closetags();
1.73      florian   327:                exit(0);
1.1       deraadt   328:        }
1.38      db        329:        return (TRUE);
1.1       deraadt   330: }
                    331:
                    332: /*
1.10      mickey    333:  * User abort.  Should be called by any input routine that sees a C-g to abort
1.5       millert   334:  * whatever C-g is aborting these days. Currently does nothing.
1.1       deraadt   335:  */
1.4       millert   336: int
1.20      vincent   337: ctrlg(int f, int n)
1.1       deraadt   338: {
1.24      vincent   339:        return (ABORT);
1.1       deraadt   340: }