tools/llvm: Do not build with symbols
[minix3.git] / external / bsd / nvi / dist / ex / ex_read.c
blob41061086c7bfcf2fbac31fe66d1327fe37bfa57a
1 /* $NetBSD: ex_read.c,v 1.2 2013/11/22 15:52:05 christos Exp $ */
2 /*-
3 * Copyright (c) 1992, 1993, 1994
4 * The Regents of the University of California. All rights reserved.
5 * Copyright (c) 1992, 1993, 1994, 1995, 1996
6 * Keith Bostic. All rights reserved.
8 * See the LICENSE file for redistribution information.
9 */
11 #include "config.h"
13 #ifndef lint
14 static const char sccsid[] = "Id: ex_read.c,v 10.44 2001/06/25 15:19:19 skimo Exp (Berkeley) Date: 2001/06/25 15:19:19 ";
15 #endif /* not lint */
17 #include <sys/types.h>
18 #include <sys/queue.h>
19 #include <sys/stat.h>
20 #include <sys/time.h>
22 #include <bitstring.h>
23 #include <ctype.h>
24 #include <errno.h>
25 #include <limits.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
30 #include "../common/common.h"
31 #include "../vi/vi.h"
34 * ex_read -- :read [file]
35 * :read [!cmd]
36 * Read from a file or utility.
38 * !!!
39 * Historical vi wouldn't undo a filter read, for no apparent reason.
41 * PUBLIC: int ex_read __P((SCR *, EXCMD *));
43 int
44 ex_read(SCR *sp, EXCMD *cmdp)
46 enum { R_ARG, R_EXPANDARG, R_FILTER } which;
47 struct stat sb;
48 CHAR_T *arg = NULL;
49 const char *name;
50 size_t nlen;
51 EX_PRIVATE *exp;
52 FILE *fp;
53 FREF *frp;
54 GS *gp;
55 MARK rm;
56 db_recno_t nlines;
57 size_t arglen = 0;
58 int argc, rval;
59 char *p;
61 #if defined(__minix)
62 /* Prevent complains from GCC at -O3 optimisation level. */
63 nlines = 0;
64 #endif /* defined(__minix) */
65 gp = sp->gp;
68 * 0 args: read the current pathname.
69 * 1 args: check for "read !arg".
71 switch (cmdp->argc) {
72 case 0:
73 which = R_ARG;
74 break;
75 case 1:
76 arg = cmdp->argv[0]->bp;
77 arglen = cmdp->argv[0]->len;
78 if (*arg == '!') {
79 ++arg;
80 --arglen;
81 which = R_FILTER;
83 /* Secure means no shell access. */
84 if (O_ISSET(sp, O_SECURE)) {
85 ex_wemsg(sp, cmdp->cmd->name, EXM_SECURE_F);
86 return (1);
88 } else
89 which = R_EXPANDARG;
90 break;
91 default:
92 abort();
93 /* NOTREACHED */
96 /* Load a temporary file if no file being edited. */
97 if (sp->ep == NULL) {
98 if ((frp = file_add(sp, NULL)) == NULL)
99 return (1);
100 if (file_init(sp, frp, NULL, 0))
101 return (1);
104 switch (which) {
105 case R_FILTER:
107 * File name and bang expand the user's argument. If
108 * we don't get an additional argument, it's illegal.
110 argc = cmdp->argc;
111 if (argv_exp1(sp, cmdp, arg, arglen, 1))
112 return (1);
113 if (argc == cmdp->argc) {
114 ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
115 return (1);
117 argc = cmdp->argc - 1;
119 /* Set the last bang command. */
120 exp = EXP(sp);
121 if (exp->lastbcomm != NULL)
122 free(exp->lastbcomm);
123 if ((exp->lastbcomm =
124 v_wstrdup(sp, cmdp->argv[argc]->bp,
125 cmdp->argv[argc]->len)) == NULL) {
126 msgq(sp, M_SYSERR, NULL);
127 return (1);
131 * Vi redisplayed the user's argument if it changed, ex
132 * always displayed a !, plus the user's argument if it
133 * changed.
135 if (F_ISSET(sp, SC_VI)) {
136 if (F_ISSET(cmdp, E_MODIFY))
137 (void)vs_update(sp, "!", cmdp->argv[argc]->bp);
138 } else {
139 if (F_ISSET(cmdp, E_MODIFY)) {
140 INT2CHAR(sp, cmdp->argv[argc]->bp,
141 cmdp->argv[argc]->len + 1, name, nlen);
142 (void)ex_printf(sp,
143 "!%s\n", name);
144 } else
145 (void)ex_puts(sp, "!\n");
146 (void)ex_fflush(sp);
150 * Historically, filter reads as the first ex command didn't
151 * wait for the user. If SC_SCR_EXWROTE not already set, set
152 * the don't-wait flag.
154 if (!F_ISSET(sp, SC_SCR_EXWROTE))
155 F_SET(sp, SC_EX_WAIT_NO);
158 * Switch into ex canonical mode. The reason to restore the
159 * original terminal modes for read filters is so that users
160 * can do things like ":r! cat /dev/tty".
162 * !!!
163 * We do not output an extra <newline>, so that we don't touch
164 * the screen on a normal read.
166 if (F_ISSET(sp, SC_VI)) {
167 if (gp->scr_screen(sp, SC_EX)) {
168 ex_wemsg(sp, cmdp->cmd->name, EXM_NOCANON_F);
169 return (1);
172 * !!!
173 * Historically, the read command doesn't switch to
174 * the alternate X11 xterm screen, if doing a filter
175 * read -- don't set SA_ALTERNATE.
177 F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
180 if (ex_filter(sp, cmdp, &cmdp->addr1,
181 NULL, &rm, cmdp->argv[argc]->bp, FILTER_READ))
182 return (1);
184 /* The filter version of read set the autoprint flag. */
185 F_SET(cmdp, E_AUTOPRINT);
188 * If in vi mode, move to the first nonblank. Might have
189 * switched into ex mode, so saved the original SC_VI value.
191 sp->lno = rm.lno;
192 if (F_ISSET(sp, SC_VI)) {
193 sp->cno = 0;
194 (void)nonblank(sp, sp->lno, &sp->cno);
196 return (0);
197 case R_ARG:
198 name = sp->frp->name;
199 break;
200 case R_EXPANDARG:
201 if (argv_exp2(sp, cmdp, arg, arglen))
202 return (1);
204 * 0 args: impossible.
205 * 1 args: impossible (I hope).
206 * 2 args: read it.
207 * >2 args: object, too many args.
209 * The 1 args case depends on the argv_sexp() function refusing
210 * to return success without at least one non-blank character.
212 switch (cmdp->argc) {
213 case 0:
214 case 1:
215 abort();
216 /* NOTREACHED */
217 case 2:
218 INT2CHAR(sp, cmdp->argv[1]->bp, cmdp->argv[1]->len + 1,
219 name, nlen);
221 * !!!
222 * Historically, the read and write commands renamed
223 * "unnamed" files, or, if the file had a name, set
224 * the alternate file name.
226 if (F_ISSET(sp->frp, FR_TMPFILE) &&
227 !F_ISSET(sp->frp, FR_EXNAMED)) {
228 if ((p = strdup(name)) != NULL) {
229 free(sp->frp->name);
230 sp->frp->name = p;
233 * The file has a real name, it's no longer a
234 * temporary, clear the temporary file flags.
236 F_CLR(sp->frp, FR_TMPEXIT | FR_TMPFILE);
237 F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED);
239 /* Notify the screen. */
240 (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
241 name = sp->frp->name;
242 } else {
243 set_alt_name(sp, name);
244 name = sp->alt_name;
246 break;
247 default:
248 ex_wemsg(sp, cmdp->argv[0]->bp, EXM_FILECOUNT);
249 return (1);
252 break;
256 * !!!
257 * Historically, vi did not permit reads from non-regular files, nor
258 * did it distinguish between "read !" and "read!", so there was no
259 * way to "force" it. We permit reading from named pipes too, since
260 * they didn't exist when the original implementation of vi was done
261 * and they seem a reasonable addition.
263 if ((fp = fopen(name, "r")) == NULL || fstat(fileno(fp), &sb)) {
264 msgq_str(sp, M_SYSERR, name, "%s");
265 return (1);
267 if (!S_ISFIFO(sb.st_mode) && !S_ISREG(sb.st_mode)) {
268 (void)fclose(fp);
269 msgq(sp, M_ERR,
270 "145|Only regular files and named pipes may be read");
271 return (1);
274 /* Try and get a lock. */
275 if (file_lock(sp, NULL, NULL, fileno(fp), 0) == LOCK_UNAVAIL)
276 msgq(sp, M_ERR, "146|%s: read lock was unavailable", name);
278 rval = ex_readfp(sp, name, fp, &cmdp->addr1, &nlines, 0);
281 * In vi, set the cursor to the first line read in, if anything read
282 * in, otherwise, the address. (Historic vi set it to the line after
283 * the address regardless, but since that line may not exist we don't
284 * bother.)
286 * In ex, set the cursor to the last line read in, if anything read in,
287 * otherwise, the address.
289 if (F_ISSET(sp, SC_VI)) {
290 sp->lno = cmdp->addr1.lno;
291 if (nlines)
292 ++sp->lno;
293 } else
294 sp->lno = cmdp->addr1.lno + nlines;
295 return (rval);
299 * ex_readfp --
300 * Read lines into the file.
302 * PUBLIC: int ex_readfp __P((SCR *, const char *, FILE *, MARK *, db_recno_t *, int));
305 ex_readfp(SCR *sp, const char *name, FILE *fp, MARK *fm, db_recno_t *nlinesp, int silent)
307 EX_PRIVATE *exp;
308 GS *gp;
309 db_recno_t lcnt, lno;
310 size_t len;
311 u_long ccnt; /* XXX: can't print off_t portably. */
312 int nf, rval;
313 const char *p;
314 size_t wlen;
315 const CHAR_T *wp;
317 gp = sp->gp;
318 exp = EXP(sp);
321 * Add in the lines from the output. Insertion starts at the line
322 * following the address.
324 ccnt = 0;
325 lcnt = 0;
326 p = "147|Reading...";
327 for (lno = fm->lno; !ex_getline(sp, fp, &len); ++lno, ++lcnt) {
328 if ((lcnt + 1) % INTERRUPT_CHECK == 0) {
329 if (INTERRUPTED(sp))
330 break;
331 if (!silent) {
332 gp->scr_busy(sp, p,
333 p == NULL ? BUSY_UPDATE : BUSY_ON);
334 p = NULL;
337 FILE2INT5(sp, exp->ibcw, exp->ibp, len, wp, wlen);
338 if (db_append(sp, 1, lno, wp, wlen))
339 goto err;
340 ccnt += len;
343 if (ferror(fp) || fclose(fp))
344 goto err;
346 /* Return the number of lines read in. */
347 if (nlinesp != NULL)
348 *nlinesp = lcnt;
350 if (!silent) {
351 char *q = msg_print(sp, name, &nf);
352 msgq(sp, M_INFO,
353 "148|%s: %lu lines, %lu characters", q, (unsigned long)lcnt,
354 (unsigned long)ccnt);
355 if (nf)
356 FREE_SPACE(sp, q, 0);
359 rval = 0;
360 if (0) {
361 err: msgq_str(sp, M_SYSERR, name, "%s");
362 (void)fclose(fp);
363 rval = 1;
366 if (!silent)
367 gp->scr_busy(sp, NULL, BUSY_OFF);
368 return (rval);