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