* Copyright (c) 1992, 1993
* 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_write.c 8.19 (Berkeley) 12/18/93";
enum which
{WQ
, WRITE
, XIT
};
static int exwr
__P((SCR
*, EXF
*, EXCMDARG
*, enum which
));
* ex_wq -- :wq[!] [>>] [file]
if (exwr(sp
, ep
, cmdp
, WQ
))
force
= F_ISSET(cmdp
, E_FORCE
);
if (!force
&& ep
->refcnt
<= 1 && file_unedited(sp
) != NULL
) {
"More files to edit; use \":n\" to go to the next file");
F_SET(sp
, force
? S_EXIT_FORCE
: S_EXIT
);
* ex_write -- :write[!] [>>] [file]
return (exwr(sp
, ep
, cmdp
, WRITE
));
* ex_xit -- :x[it]! [file]
* Write out any modifications and quit.
if (F_ISSET((ep
), F_MODIFIED
) && exwr(sp
, ep
, cmdp
, XIT
))
force
= F_ISSET(cmdp
, E_FORCE
);
if (!force
&& ep
->refcnt
<= 1 && file_unedited(sp
) != NULL
) {
"More files to edit; use \":n\" to go to the next file");
F_SET(sp
, force
? S_EXIT_FORCE
: S_EXIT
);
* The guts of the ex write commands.
/* All write commands can have an associated '!'. */
if (F_ISSET(cmdp
, E_FORCE
))
/* Skip any leading whitespace. */
for (p
= cmdp
->argv
[0]->bp
; *p
&& isblank(*p
); ++p
);
/* If no arguments, just write the file back. */
if (cmdp
->argc
== 0 || *p
== '\0') {
if (F_ISSET(cmdp
, E_ADDR2_ALL
))
return (file_write(sp
, ep
,
&cmdp
->addr1
, &cmdp
->addr2
, NULL
, flags
));
/* If "write !" it's a pipe to a utility. */
if (cmd
== WRITE
&& *p
== '!') {
for (++p
; *p
&& isblank(*p
); ++p
);
msgq(sp
, M_ERR
, "Usage: %s.", cmdp
->cmd
->usage
);
/* Expand the argument. */
if (argv_exp1(sp
, ep
, cmdp
, p
, strlen(p
), 0))
if (filtercmd(sp
, ep
, &cmdp
->addr1
, &cmdp
->addr2
,
&rm
, cmdp
->argv
[1]->bp
, FILTER_WRITE
))
/* If "write >>" it's an append to a file. */
if (cmd
!= XIT
&& p
[0] == '>' && p
[1] == '>') {
/* Skip ">>" and whitespace. */
for (p
+= 2; *p
&& isblank(*p
); ++p
);
/* Build an argv so we get an argument count and file expansion. */
if (argv_exp2(sp
, ep
, cmdp
, p
, strlen(p
), 0))
* Nothing to expand, write the current file.
* Should never happen, already checked this case.
/* One new argument, write it. */
name
= cmdp
->argv
[exp
->argsoff
- 1]->bp
;
/* If expanded to more than one argument, object. */
msgq(sp
, M_ERR
, "%s expanded into too many file names",
msgq(sp
, M_ERR
, "Usage: %s.", cmdp
->cmd
->usage
);
if (F_ISSET(cmdp
, E_ADDR2_ALL
))
return (file_write(sp
, ep
, &cmdp
->addr1
, &cmdp
->addr2
, name
, flags
));
* Write a range of lines to a FILE *.
ex_writefp(sp
, ep
, name
, fp
, fm
, tm
, nlno
, nch
)
register u_long ccnt
, fline
, tline
;
* The vi filter code has multiple processes running simultaneously,
* and one of them calls ex_writefp(). The "unsafe" function calls
* in this code are to file_gline() and msgq(). File_gline() is safe,
* see the comment in filter.c:filtercmd() for details. We don't call
* msgq if the multiple process bit in the EXF is set.
* Historic vi permitted files of 0 length to be written. However,
* since the way vi got around dealing with "empty" files was to
* always have a line in the file no matter what, it wrote them as
* files of a single, empty line. We write empty files.
* "Alex, I'll take vi trivia for $1000."
for (; fline
<= tline
; ++fline
) {
if ((p
= file_gline(sp
, ep
, fline
, &len
)) == NULL
)
if (fwrite(p
, 1, len
, fp
) != len
) {
msgq(sp
, M_SYSERR
, name
);
if (putc('\n', fp
) != '\n')
if (!F_ISSET(ep
, F_MULTILOCK
))
msgq(sp
, M_SYSERR
, name
);
*nlno
= tm
->lno
== 0 ? 0 : tm
->lno
- fm
->lno
+ 1;