Annotation of src/usr.bin/mg/main.c, Revision 1.94
1.94 ! op 1: /* $OpenBSD: main.c,v 1.93 2023/03/30 19:00:02 op 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
54: usage()
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.89 lum 170: if (batch)
171: return (0);
172:
1.77 jasper 173: /*
1.65 lum 174: * Now ensure any default buffer modes from the startup file are
175: * given to any files opened when parsing the startup file.
176: * Note *scratch* will also be updated.
177: */
178: for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
179: bp->b_flag = defb_flag;
180: for (i = 0; i <= defb_nmodes; i++) {
181: bp->b_modes[i] = defb_modes[i];
182: }
183: }
1.59 kjell 184:
185: /* Force FFOTHARG=1 so that this mode is enabled, not simply toggled */
186: if (init_fcn)
187: init_fcn(FFOTHARG, 1);
188:
1.35 henning 189: if (nobackups)
190: makebkfile(FFARG, 0);
1.27 vincent 191:
192: for (nfiles = 0, i = 0; i < argc; i++) {
193: if (argv[i][0] == '+' && strlen(argv[i]) >= 2) {
1.43 deraadt 194: long long lval;
1.30 pvalchev 195: const char *errstr;
1.23 deraadt 196:
1.32 vincent 197: lval = strtonum(&argv[i][1], INT_MIN, INT_MAX, &errstr);
1.33 vincent 198: if (argv[i][1] == '\0' || errstr != NULL)
1.23 deraadt 199: goto notnum;
1.30 pvalchev 200: startrow = lval;
1.24 vincent 201: } else {
1.23 deraadt 202: notnum:
1.52 jason 203: cp = adjustname(argv[i], FALSE);
1.24 vincent 204: if (cp != NULL) {
1.38 db 205: if (nfiles == 1)
1.27 vincent 206: splitwind(0, 1);
1.38 db 207:
1.76 lum 208: if (fisdir(cp) == TRUE) {
209: (void)do_dired(cp);
1.77 jasper 210: continue;
1.76 lum 211: }
1.39 beck 212: if ((curbp = findbuffer(cp)) == NULL) {
213: vttidy();
214: errx(1, "Can't find current buffer!");
215: }
1.24 vincent 216: (void)showbuffer(curbp, curwp, 0);
1.44 deraadt 217: if (readin(cp) != TRUE)
1.34 jfb 218: killbuffer(curbp);
1.38 db 219: else {
1.59 kjell 220: /* Ensure enabled, not just toggled */
1.34 jfb 221: if (init_fcn_name)
1.59 kjell 222: init_fcn(FFOTHARG, 1);
1.34 jfb 223: nfiles++;
224: }
1.85 lum 225: if (allbro)
1.81 lum 226: curbp->b_flag |= BFREADONLY;
1.24 vincent 227: }
1.22 vincent 228: }
1.1 deraadt 229: }
1.29 vincent 230:
231: if (nfiles > 2)
232: listbuffers(0, 1);
1.5 millert 233:
234: /* fake last flags */
235: thisflag = 0;
1.4 millert 236: for (;;) {
1.50 kjell 237: if (epresf == KCLEAR)
1.4 millert 238: eerase();
1.50 kjell 239: if (epresf == TRUE)
240: epresf = KCLEAR;
1.17 deraadt 241: if (winch_flag) {
1.49 otto 242: do_redraw(0, 0, TRUE);
1.17 deraadt 243: winch_flag = 0;
244: }
1.71 lum 245: update(CMODE);
1.4 millert 246: lastflag = thisflag;
247: thisflag = 0;
1.5 millert 248:
1.4 millert 249: switch (doin()) {
250: case TRUE:
251: break;
1.1 deraadt 252: case ABORT:
1.5 millert 253: ewprintf("Quit");
1.48 kjell 254: /* FALLTHRU */
1.1 deraadt 255: case FALSE:
256: default:
1.4 millert 257: macrodef = FALSE;
258: }
1.1 deraadt 259: }
260: }
261:
262: /*
1.66 lum 263: * Initialize default buffer and window. Default buffer is called *scratch*.
1.1 deraadt 264: */
1.7 art 265: static void
1.66 lum 266: edinit(struct buffer *bp)
1.4 millert 267: {
1.45 deraadt 268: struct mgwin *wp;
1.1 deraadt 269:
270: bheadp = NULL;
1.66 lum 271: bp = bfind("*scratch*", TRUE); /* Text buffer. */
1.63 lum 272: if (bp == NULL)
273: panic("edinit");
274:
1.26 vincent 275: wp = new_window(bp);
1.21 vincent 276: if (wp == NULL)
1.66 lum 277: panic("edinit: Out of memory");
1.63 lum 278:
1.66 lum 279: curbp = bp; /* Current buffer. */
1.1 deraadt 280: wheadp = wp;
1.4 millert 281: curwp = wp;
1.5 millert 282: wp->w_wndp = NULL; /* Initialize window. */
1.54 kjell 283: wp->w_linep = wp->w_dotp = bp->b_headp;
1.38 db 284: wp->w_ntrows = nrow - 2; /* 2 = mode, echo. */
1.61 kjell 285: wp->w_rflag = WFMODE | WFFULL; /* Full. */
1.89 lum 286: }
287:
288: /*
289: * Create pty for batch mode.
290: */
291: static void
292: pty_init(void)
293: {
294: struct winsize ws;
295: int master;
296: int slave;
297:
298: memset(&ws, 0, sizeof(ws));
299: ws.ws_col = 80,
300: ws.ws_row = 24;
1.92 op 301:
1.89 lum 302: openpty(&master, &slave, NULL, NULL, &ws);
303: login_tty(slave);
304:
305: return;
1.1 deraadt 306: }
307:
308: /*
1.5 millert 309: * Quit command. If an argument, always quit. Otherwise confirm if a buffer
1.87 lum 310: * has been changed and not written out. Normally bound to "C-x C-c".
1.1 deraadt 311: */
1.5 millert 312: int
1.20 vincent 313: quit(int f, int n)
1.1 deraadt 314: {
1.5 millert 315: int s;
1.1 deraadt 316:
1.4 millert 317: if ((s = anycb(FALSE)) == ABORT)
1.38 db 318: return (ABORT);
1.69 lum 319: if (s == FIOERR || s == UERROR)
1.68 lum 320: return (FALSE);
1.1 deraadt 321: if (s == FALSE
1.41 kjell 322: || eyesno("Modified buffers exist; really exit") == TRUE) {
1.1 deraadt 323: vttidy();
1.62 lum 324: closetags();
1.73 florian 325: exit(0);
1.1 deraadt 326: }
1.38 db 327: return (TRUE);
1.1 deraadt 328: }
329:
330: /*
1.10 mickey 331: * User abort. Should be called by any input routine that sees a C-g to abort
1.5 millert 332: * whatever C-g is aborting these days. Currently does nothing.
1.1 deraadt 333: */
1.4 millert 334: int
1.20 vincent 335: ctrlg(int f, int n)
1.1 deraadt 336: {
1.24 vincent 337: return (ABORT);
1.1 deraadt 338: }