Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / nvi / ex / ex_read.c
blob477fc83887d388018b742a1b80bd290b9bc86526
1 /* $NetBSD: ex_read.c,v 1.3 2009/11/14 23:31:37 christos Exp $ */
3 /*-
4 * Copyright (c) 1992, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 * Copyright (c) 1992, 1993, 1994, 1995, 1996
7 * Keith Bostic. All rights reserved.
9 * See the LICENSE file for redistribution information.
12 #include "config.h"
14 #ifndef lint
15 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";
16 #endif /* not lint */
18 #include <sys/types.h>
19 #include <sys/queue.h>
20 #include <sys/stat.h>
21 #include <sys/time.h>
23 #include <bitstring.h>
24 #include <ctype.h>
25 #include <errno.h>
26 #include <limits.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
31 #include "../common/common.h"
32 #include "../vi/vi.h"
35 * ex_read -- :read [file]
36 * :read [!cmd]
37 * Read from a file or utility.
39 * !!!
40 * Historical vi wouldn't undo a filter read, for no apparent reason.
42 * PUBLIC: int ex_read __P((SCR *, EXCMD *));
44 int
45 ex_read(SCR *sp, EXCMD *cmdp)
47 enum { R_ARG, R_EXPANDARG, R_FILTER } which;
48 struct stat sb;
49 CHAR_T *arg = NULL;
50 const char *name;
51 size_t nlen;
52 EX_PRIVATE *exp;
53 FILE *fp;
54 FREF *frp;
55 GS *gp;
56 MARK rm;
57 db_recno_t nlines;
58 size_t arglen = 0;
59 int argc, rval;
60 char *p;
62 gp = sp->gp;
65 * 0 args: read the current pathname.
66 * 1 args: check for "read !arg".
68 switch (cmdp->argc) {
69 case 0:
70 which = R_ARG;
71 break;
72 case 1:
73 arg = cmdp->argv[0]->bp;
74 arglen = cmdp->argv[0]->len;
75 if (*arg == '!') {
76 ++arg;
77 --arglen;
78 which = R_FILTER;
80 /* Secure means no shell access. */
81 if (O_ISSET(sp, O_SECURE)) {
82 ex_wemsg(sp, cmdp->cmd->name, EXM_SECURE_F);
83 return (1);
85 } else
86 which = R_EXPANDARG;
87 break;
88 default:
89 abort();
90 /* NOTREACHED */
93 /* Load a temporary file if no file being edited. */
94 if (sp->ep == NULL) {
95 if ((frp = file_add(sp, NULL)) == NULL)
96 return (1);
97 if (file_init(sp, frp, NULL, 0))
98 return (1);
101 switch (which) {
102 case R_FILTER:
104 * File name and bang expand the user's argument. If
105 * we don't get an additional argument, it's illegal.
107 argc = cmdp->argc;
108 if (argv_exp1(sp, cmdp, arg, arglen, 1))
109 return (1);
110 if (argc == cmdp->argc) {
111 ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
112 return (1);
114 argc = cmdp->argc - 1;
116 /* Set the last bang command. */
117 exp = EXP(sp);
118 if (exp->lastbcomm != NULL)
119 free(exp->lastbcomm);
120 if ((exp->lastbcomm =
121 v_wstrdup(sp, cmdp->argv[argc]->bp,
122 cmdp->argv[argc]->len)) == NULL) {
123 msgq(sp, M_SYSERR, NULL);
124 return (1);
128 * Vi redisplayed the user's argument if it changed, ex
129 * always displayed a !, plus the user's argument if it
130 * changed.
132 if (F_ISSET(sp, SC_VI)) {
133 if (F_ISSET(cmdp, E_MODIFY))
134 (void)vs_update(sp, "!", cmdp->argv[argc]->bp);
135 } else {
136 if (F_ISSET(cmdp, E_MODIFY)) {
137 INT2CHAR(sp, cmdp->argv[argc]->bp,
138 cmdp->argv[argc]->len + 1, name, nlen);
139 (void)ex_printf(sp,
140 "!%s\n", name);
141 } else
142 (void)ex_puts(sp, "!\n");
143 (void)ex_fflush(sp);
147 * Historically, filter reads as the first ex command didn't
148 * wait for the user. If SC_SCR_EXWROTE not already set, set
149 * the don't-wait flag.
151 if (!F_ISSET(sp, SC_SCR_EXWROTE))
152 F_SET(sp, SC_EX_WAIT_NO);
155 * Switch into ex canonical mode. The reason to restore the
156 * original terminal modes for read filters is so that users
157 * can do things like ":r! cat /dev/tty".
159 * !!!
160 * We do not output an extra <newline>, so that we don't touch
161 * the screen on a normal read.
163 if (F_ISSET(sp, SC_VI)) {
164 if (gp->scr_screen(sp, SC_EX)) {
165 ex_wemsg(sp, cmdp->cmd->name, EXM_NOCANON_F);
166 return (1);
169 * !!!
170 * Historically, the read command doesn't switch to
171 * the alternate X11 xterm screen, if doing a filter
172 * read -- don't set SA_ALTERNATE.
174 F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
177 if (ex_filter(sp, cmdp, &cmdp->addr1,
178 NULL, &rm, cmdp->argv[argc]->bp, FILTER_READ))
179 return (1);
181 /* The filter version of read set the autoprint flag. */
182 F_SET(cmdp, E_AUTOPRINT);
185 * If in vi mode, move to the first nonblank. Might have
186 * switched into ex mode, so saved the original SC_VI value.
188 sp->lno = rm.lno;
189 if (F_ISSET(sp, SC_VI)) {
190 sp->cno = 0;
191 (void)nonblank(sp, sp->lno, &sp->cno);
193 return (0);
194 case R_ARG:
195 name = sp->frp->name;
196 break;
197 case R_EXPANDARG:
198 if (argv_exp2(sp, cmdp, arg, arglen))
199 return (1);
201 * 0 args: impossible.
202 * 1 args: impossible (I hope).
203 * 2 args: read it.
204 * >2 args: object, too many args.
206 * The 1 args case depends on the argv_sexp() function refusing
207 * to return success without at least one non-blank character.
209 switch (cmdp->argc) {
210 case 0:
211 case 1:
212 abort();
213 /* NOTREACHED */
214 case 2:
215 INT2CHAR(sp, cmdp->argv[1]->bp, cmdp->argv[1]->len + 1,
216 name, nlen);
218 * !!!
219 * Historically, the read and write commands renamed
220 * "unnamed" files, or, if the file had a name, set
221 * the alternate file name.
223 if (F_ISSET(sp->frp, FR_TMPFILE) &&
224 !F_ISSET(sp->frp, FR_EXNAMED)) {
225 if ((p = strdup(name)) != NULL) {
226 free(sp->frp->name);
227 sp->frp->name = p;
230 * The file has a real name, it's no longer a
231 * temporary, clear the temporary file flags.
233 F_CLR(sp->frp, FR_TMPEXIT | FR_TMPFILE);
234 F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED);
236 /* Notify the screen. */
237 (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
238 name = sp->frp->name;
239 } else {
240 set_alt_name(sp, name);
241 name = sp->alt_name;
243 break;
244 default:
245 ex_wemsg(sp, cmdp->argv[0]->bp, EXM_FILECOUNT);
246 return (1);
249 break;
253 * !!!
254 * Historically, vi did not permit reads from non-regular files, nor
255 * did it distinguish between "read !" and "read!", so there was no
256 * way to "force" it. We permit reading from named pipes too, since
257 * they didn't exist when the original implementation of vi was done
258 * and they seem a reasonable addition.
260 if ((fp = fopen(name, "r")) == NULL || fstat(fileno(fp), &sb)) {
261 msgq_str(sp, M_SYSERR, name, "%s");
262 return (1);
264 if (!S_ISFIFO(sb.st_mode) && !S_ISREG(sb.st_mode)) {
265 (void)fclose(fp);
266 msgq(sp, M_ERR,
267 "145|Only regular files and named pipes may be read");
268 return (1);
271 /* Try and get a lock. */
272 if (file_lock(sp, NULL, NULL, fileno(fp), 0) == LOCK_UNAVAIL)
273 msgq(sp, M_ERR, "146|%s: read lock was unavailable", name);
275 rval = ex_readfp(sp, name, fp, &cmdp->addr1, &nlines, 0);
278 * In vi, set the cursor to the first line read in, if anything read
279 * in, otherwise, the address. (Historic vi set it to the line after
280 * the address regardless, but since that line may not exist we don't
281 * bother.)
283 * In ex, set the cursor to the last line read in, if anything read in,
284 * otherwise, the address.
286 if (F_ISSET(sp, SC_VI)) {
287 sp->lno = cmdp->addr1.lno;
288 if (nlines)
289 ++sp->lno;
290 } else
291 sp->lno = cmdp->addr1.lno + nlines;
292 return (rval);
296 * ex_readfp --
297 * Read lines into the file.
299 * PUBLIC: int ex_readfp __P((SCR *, char *, FILE *, MARK *, db_recno_t *, int));
302 ex_readfp(SCR *sp, const char *name, FILE *fp, MARK *fm, db_recno_t *nlinesp, int silent)
304 EX_PRIVATE *exp;
305 GS *gp;
306 db_recno_t lcnt, lno;
307 size_t len;
308 u_long ccnt; /* XXX: can't print off_t portably. */
309 int nf, rval;
310 const char *p;
311 size_t wlen;
312 const CHAR_T *wp;
314 gp = sp->gp;
315 exp = EXP(sp);
318 * Add in the lines from the output. Insertion starts at the line
319 * following the address.
321 ccnt = 0;
322 lcnt = 0;
323 p = "147|Reading...";
324 for (lno = fm->lno; !ex_getline(sp, fp, &len); ++lno, ++lcnt) {
325 if ((lcnt + 1) % INTERRUPT_CHECK == 0) {
326 if (INTERRUPTED(sp))
327 break;
328 if (!silent) {
329 gp->scr_busy(sp, p,
330 p == NULL ? BUSY_UPDATE : BUSY_ON);
331 p = NULL;
334 FILE2INT5(sp, exp->ibcw, exp->ibp, len, wp, wlen);
335 if (db_append(sp, 1, lno, wp, wlen))
336 goto err;
337 ccnt += len;
340 if (ferror(fp) || fclose(fp))
341 goto err;
343 /* Return the number of lines read in. */
344 if (nlinesp != NULL)
345 *nlinesp = lcnt;
347 if (!silent) {
348 char *q = msg_print(sp, name, &nf);
349 msgq(sp, M_INFO,
350 "148|%s: %lu lines, %lu characters", q, (unsigned long)lcnt,
351 (unsigned long)ccnt);
352 if (nf)
353 FREE_SPACE(sp, q, 0);
356 rval = 0;
357 if (0) {
358 err: msgq_str(sp, M_SYSERR, name, "%s");
359 (void)fclose(fp);
360 rval = 1;
363 if (!silent)
364 gp->scr_busy(sp, NULL, BUSY_OFF);
365 return (rval);