* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char sccsid
[] = "@(#)ex_read.c 9.5 (Berkeley) 12/1/94";
* ex_read -- :read [file]
* Read from a file or utility.
* Historical vi wouldn't undo a filter read, for no apparent reason.
enum { R_ARG
, R_EXPANDARG
, R_FILTER
} which
;
size_t arglen
, blen
, len
;
int argc
, btear
, nf
, rval
;
* 0 args: read the current pathname.
* 1 args: check for "read !arg".
arglen
= cmdp
->argv
[0]->len
;
/* Load a temporary file if no file being edited. */
if ((frp
= file_add(sp
, NULL
)) == NULL
)
if (file_init(sp
, frp
, NULL
, 0))
* File name and bang expand the user's argument. If
* we don't get an additional argument, it's illegal.
if (argv_exp1(sp
, cmdp
, arg
, arglen
, 1))
/* Set the last bang command. */
if (exp
->lastbcomm
!= NULL
)
strdup(cmdp
->argv
[argc
]->bp
)) == NULL
) {
msgq(sp
, M_SYSERR
, NULL
);
/* Redisplay the user's argument if it's changed. */
if (F_ISSET(cmdp
, E_MODIFY
) && IN_VI_MODE(sp
)) {
len
= cmdp
->argv
[argc
]->len
;
GET_SPACE_RET(sp
, p
, blen
, len
+ 2);
cmdp
->argv
[argc
]->bp
, cmdp
->argv
[argc
]->len
+ 1);
if (filtercmd(sp
, &cmdp
->addr1
,
NULL
, &rm
, cmdp
->argv
[argc
]->bp
, FILTER_READ
))
/* The filter version of read set the autoprint flag. */
F_SET(EXP(sp
), EX_AUTOPRINT
);
/* If in vi mode, move to the first nonblank. */
(void)nonblank(sp
, sp
->lno
, &sp
->cno
);
if (argv_exp2(sp
, cmdp
, arg
, arglen
))
* >2 args: object, too many args.
name
= cmdp
->argv
[1]->bp
;
* Historically, the read and write commands renamed
* "unnamed" files, or, if the file had a name, set
* the alternate file name.
if (F_ISSET(sp
->frp
, FR_TMPFILE
) &&
!F_ISSET(sp
->frp
, FR_EXNAMED
)) {
if ((p
= v_strdup(sp
, cmdp
->argv
[1]->bp
,
cmdp
->argv
[1]->len
)) != NULL
) {
* The file has a real name, it's no longer a
* temporary, clear the temporary file flags.
* The read-only flag follows the file name,
FR_RDONLY
| FR_TMPEXIT
| FR_TMPFILE
);
F_SET(sp
->frp
, FR_NAMECHANGE
| FR_EXNAMED
);
p
= msg_print(sp
, cmdp
->argv
[0]->bp
, &nf
);
"149|%s expanded into too many file names", p
);
usage
: ex_message(sp
, cmdp
->cmd
, EXM_USAGE
);
* Historically, vi did not permit reads from non-regular files,
* nor did it distinguish between "read !" and "read!", so there
* was no way to "force" it.
if ((fp
= fopen(name
, "r")) == NULL
|| fstat(fileno(fp
), &sb
)) {
p
= msg_print(sp
, name
, &nf
);
msgq(sp
, M_SYSERR
, "%s", p
);
if (!S_ISREG(sb
.st_mode
)) {
msgq(sp
, M_ERR
, "150|Only regular files may be read");
/* Try and get a lock. */
if (file_lock(sp
, NULL
, NULL
, fileno(fp
), 0) == LOCK_UNAVAIL
)
msgq(sp
, M_ERR
, "264|%s: read lock was unavailable", name
);
/* Turn on busy message. */
btear
= F_ISSET(sp
, S_EXSILENT
) ? 0 : !busy_on(sp
, "Reading...");
rval
= ex_readfp(sp
, name
, fp
, &cmdp
->addr1
, &nlines
, 1);
* Set the cursor to the first line read in, if anything read
* in, otherwise, the address. (Historic vi set it to the
* line after the address regardless, but since that line may
* not exist we don't bother.)
sp
->lno
= cmdp
->addr1
.lno
;
* Read lines into the file.
ex_readfp(sp
, name
, fp
, fm
, nlinesp
, success_msg
)
u_long ccnt
; /* XXX: can't print off_t portably. */
* Add in the lines from the output. Insertion starts at the line
for (lno
= fm
->lno
; !ex_getline(sp
, fp
, &len
); ++lno
, ++lcnt
) {
ex_message(sp
, NULL
, EXM_INTERRUPTED
);
if (file_aline(sp
, 1, lno
, exp
->ibp
, len
)) {
p
= msg_print(sp
, name
, &nf
);
msgq(sp
, M_SYSERR
, "%s", p
);
p
= msg_print(sp
, name
, &nf
);
msgq(sp
, M_SYSERR
, "%s", p
);
/* Return the number of lines read in. */
p
= msg_print(sp
, name
, &nf
);
"151|Interrupted read: %s: %lu lines, %lu characters",
"152|%s: %lu lines, %lu characters",