1 /* $NetBSD: ex_read.c,v 1.3 2014/01/26 21:43:45 christos Exp $ */
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.
13 #include <sys/cdefs.h>
16 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 ";
19 __RCSID("$NetBSD: ex_read.c,v 1.3 2014/01/26 21:43:45 christos Exp $");
22 #include <sys/types.h>
23 #include <sys/queue.h>
27 #include <bitstring.h>
35 #include "../common/common.h"
39 * ex_read -- :read [file]
41 * Read from a file or utility.
44 * Historical vi wouldn't undo a filter read, for no apparent reason.
46 * PUBLIC: int ex_read __P((SCR *, EXCMD *));
49 ex_read(SCR
*sp
, EXCMD
*cmdp
)
51 enum { R_ARG
, R_EXPANDARG
, R_FILTER
} which
;
67 /* Prevent complains from GCC at -O3 optimisation level. */
69 #endif /* defined(__minix) */
73 * 0 args: read the current pathname.
74 * 1 args: check for "read !arg".
81 arg
= cmdp
->argv
[0]->bp
;
82 arglen
= cmdp
->argv
[0]->len
;
88 /* Secure means no shell access. */
89 if (O_ISSET(sp
, O_SECURE
)) {
90 ex_wemsg(sp
, cmdp
->cmd
->name
, EXM_SECURE_F
);
101 /* Load a temporary file if no file being edited. */
102 if (sp
->ep
== NULL
) {
103 if ((frp
= file_add(sp
, NULL
)) == NULL
)
105 if (file_init(sp
, frp
, NULL
, 0))
112 * File name and bang expand the user's argument. If
113 * we don't get an additional argument, it's illegal.
116 if (argv_exp1(sp
, cmdp
, arg
, arglen
, 1))
118 if (argc
== cmdp
->argc
) {
119 ex_emsg(sp
, cmdp
->cmd
->usage
, EXM_USAGE
);
122 argc
= cmdp
->argc
- 1;
124 /* Set the last bang command. */
126 if (exp
->lastbcomm
!= NULL
)
127 free(exp
->lastbcomm
);
128 if ((exp
->lastbcomm
=
129 v_wstrdup(sp
, cmdp
->argv
[argc
]->bp
,
130 cmdp
->argv
[argc
]->len
)) == NULL
) {
131 msgq(sp
, M_SYSERR
, NULL
);
136 * Vi redisplayed the user's argument if it changed, ex
137 * always displayed a !, plus the user's argument if it
140 if (F_ISSET(sp
, SC_VI
)) {
141 if (F_ISSET(cmdp
, E_MODIFY
))
142 (void)vs_update(sp
, "!", cmdp
->argv
[argc
]->bp
);
144 if (F_ISSET(cmdp
, E_MODIFY
)) {
145 INT2CHAR(sp
, cmdp
->argv
[argc
]->bp
,
146 cmdp
->argv
[argc
]->len
+ 1, name
, nlen
);
150 (void)ex_puts(sp
, "!\n");
155 * Historically, filter reads as the first ex command didn't
156 * wait for the user. If SC_SCR_EXWROTE not already set, set
157 * the don't-wait flag.
159 if (!F_ISSET(sp
, SC_SCR_EXWROTE
))
160 F_SET(sp
, SC_EX_WAIT_NO
);
163 * Switch into ex canonical mode. The reason to restore the
164 * original terminal modes for read filters is so that users
165 * can do things like ":r! cat /dev/tty".
168 * We do not output an extra <newline>, so that we don't touch
169 * the screen on a normal read.
171 if (F_ISSET(sp
, SC_VI
)) {
172 if (gp
->scr_screen(sp
, SC_EX
)) {
173 ex_wemsg(sp
, cmdp
->cmd
->name
, EXM_NOCANON_F
);
178 * Historically, the read command doesn't switch to
179 * the alternate X11 xterm screen, if doing a filter
180 * read -- don't set SA_ALTERNATE.
182 F_SET(sp
, SC_SCR_EX
| SC_SCR_EXWROTE
);
185 if (ex_filter(sp
, cmdp
, &cmdp
->addr1
,
186 NULL
, &rm
, cmdp
->argv
[argc
]->bp
, FILTER_READ
))
189 /* The filter version of read set the autoprint flag. */
190 F_SET(cmdp
, E_AUTOPRINT
);
193 * If in vi mode, move to the first nonblank. Might have
194 * switched into ex mode, so saved the original SC_VI value.
197 if (F_ISSET(sp
, SC_VI
)) {
199 (void)nonblank(sp
, sp
->lno
, &sp
->cno
);
203 name
= sp
->frp
->name
;
206 if (argv_exp2(sp
, cmdp
, arg
, arglen
))
209 * 0 args: impossible.
210 * 1 args: impossible (I hope).
212 * >2 args: object, too many args.
214 * The 1 args case depends on the argv_sexp() function refusing
215 * to return success without at least one non-blank character.
217 switch (cmdp
->argc
) {
223 INT2CHAR(sp
, cmdp
->argv
[1]->bp
, cmdp
->argv
[1]->len
+ 1,
227 * Historically, the read and write commands renamed
228 * "unnamed" files, or, if the file had a name, set
229 * the alternate file name.
231 if (F_ISSET(sp
->frp
, FR_TMPFILE
) &&
232 !F_ISSET(sp
->frp
, FR_EXNAMED
)) {
233 if ((p
= strdup(name
)) != NULL
) {
238 * The file has a real name, it's no longer a
239 * temporary, clear the temporary file flags.
241 F_CLR(sp
->frp
, FR_TMPEXIT
| FR_TMPFILE
);
242 F_SET(sp
->frp
, FR_NAMECHANGE
| FR_EXNAMED
);
244 /* Notify the screen. */
245 (void)sp
->gp
->scr_rename(sp
, sp
->frp
->name
, 1);
246 name
= sp
->frp
->name
;
248 set_alt_name(sp
, name
);
253 ex_wemsg(sp
, cmdp
->argv
[0]->bp
, EXM_FILECOUNT
);
262 * Historically, vi did not permit reads from non-regular files, nor
263 * did it distinguish between "read !" and "read!", so there was no
264 * way to "force" it. We permit reading from named pipes too, since
265 * they didn't exist when the original implementation of vi was done
266 * and they seem a reasonable addition.
268 if ((fp
= fopen(name
, "r")) == NULL
|| fstat(fileno(fp
), &sb
)) {
269 msgq_str(sp
, M_SYSERR
, name
, "%s");
272 if (!S_ISFIFO(sb
.st_mode
) && !S_ISREG(sb
.st_mode
)) {
275 "145|Only regular files and named pipes may be read");
279 /* Try and get a lock. */
280 if (file_lock(sp
, NULL
, NULL
, fileno(fp
), 0) == LOCK_UNAVAIL
)
281 msgq(sp
, M_ERR
, "146|%s: read lock was unavailable", name
);
283 rval
= ex_readfp(sp
, name
, fp
, &cmdp
->addr1
, &nlines
, 0);
286 * In vi, set the cursor to the first line read in, if anything read
287 * in, otherwise, the address. (Historic vi set it to the line after
288 * the address regardless, but since that line may not exist we don't
291 * In ex, set the cursor to the last line read in, if anything read in,
292 * otherwise, the address.
294 if (F_ISSET(sp
, SC_VI
)) {
295 sp
->lno
= cmdp
->addr1
.lno
;
299 sp
->lno
= cmdp
->addr1
.lno
+ nlines
;
305 * Read lines into the file.
307 * PUBLIC: int ex_readfp __P((SCR *, const char *, FILE *, MARK *, db_recno_t *, int));
310 ex_readfp(SCR
*sp
, const char *name
, FILE *fp
, MARK
*fm
, db_recno_t
*nlinesp
, int silent
)
314 db_recno_t lcnt
, lno
;
316 u_long ccnt
; /* XXX: can't print off_t portably. */
326 * Add in the lines from the output. Insertion starts at the line
327 * following the address.
331 p
= "147|Reading...";
332 for (lno
= fm
->lno
; !ex_getline(sp
, fp
, &len
); ++lno
, ++lcnt
) {
333 if ((lcnt
+ 1) % INTERRUPT_CHECK
== 0) {
338 p
== NULL
? BUSY_UPDATE
: BUSY_ON
);
342 FILE2INT5(sp
, exp
->ibcw
, exp
->ibp
, len
, wp
, wlen
);
343 if (db_append(sp
, 1, lno
, wp
, wlen
))
348 if (ferror(fp
) || fclose(fp
))
351 /* Return the number of lines read in. */
356 char *q
= msg_print(sp
, name
, &nf
);
358 "148|%s: %lu lines, %lu characters", q
, (unsigned long)lcnt
,
359 (unsigned long)ccnt
);
361 FREE_SPACE(sp
, q
, 0);
366 err
: msgq_str(sp
, M_SYSERR
, name
, "%s");
372 gp
->scr_busy(sp
, NULL
, BUSY_OFF
);