ex_io.c revision f6db9f272f0061301cfaa1c0001b7d636eae31f4
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* Copyright (c) 1981 Regents of the University of California */
#pragma ident "%Z%%M% %I% %E% SMI"
#include "ex.h"
#include "ex_argv.h"
#include "ex_temp.h"
#include "ex_tty.h"
#include "ex_vis.h"
#include <stdlib.h>
#include <unistd.h>
/*
*/
/*
* Following remember where . was in the previous file for return
* on file switching.
*/
int altdot;
int oldadot;
bool wasalt;
short isalt;
long cntch; /* Count of characters on unit io */
#ifndef VMUNIX
short cntln; /* Count of lines " */
#else
int cntln;
#endif
long cntnull; /* Count of nulls " */
long cntodd; /* Count of non-ascii characters " */
static void chkmdln();
extern int getchar();
/*
* Parse file name for command encoded by comm.
* If comm is E then command is doomed and we are
* parsing just so user won't have to retype the name.
*/
void
{
int c = comm, d;
int i;
d = getchar();
if (endcmd(d)) {
gettext("No current filename"));
isalt = 0;
if (c == 'e' || c == 'E')
if (d == EOF)
ungetchar(d);
} else {
ungetchar(d);
getone();
eol();
c = 'e';
edited = 0;
}
switch (c) {
case 'f':
edited = 0;
/* fall into ... */
case 'e':
if (savedfile[0]) {
}
break;
default:
if (file[0]) {
if (c != 'E')
}
break;
}
}
return;
if (file[0] != 0) {
if (comm == 'f') {
if (value(vi_READONLY))
if (!edited)
if (tchng)
}
flush();
} else
if (comm == 'f') {
if (!(i = lineDOL()))
i++;
/*
* TRANSLATION_NOTE
* Reference order of arguments must not
* be changed using '%digit$', since vi's
* viprintf() does not support it.
*/
}
}
/*
* Get the argument words for a command into genbuf
* expanding # and %.
*/
int
getargs(void)
{
int c;
int len;
pastwh();
if (peekchar() == '+') {
continue;
}
}
c = getchar();
*cp++ = c;
c = getchar();
ungetchar(c);
*--cp = 0;
break;
}
}
}
if (skipend())
return (0);
for (;;) {
if (endcmd(c) && c != '"')
break;
continue;
}
}
if (endcmd(c) && c != '"')
break;
c = getchar();
switch (c) {
case '\\':
c = getchar();
/* fall into... */
default:
*cp++ = c;
break;
case '#':
if (*fp == 0)
gettext("No alternate filename") :
gettext("No alternate filename to substitute for #"));
goto filexp;
case '%':
if (*fp == 0)
gettext("No current filename") :
gettext("No current filename to substitute for %%"));
while (*fp) {
goto flong;
}
break;
}
}
*cp = 0;
return (1);
}
/*
* Glob the argument words in genbuf, or if no globbing
* is implied, just split them up directly.
*/
void
{
int pvec[2];
int c;
unsigned char ch;
if (gscan() == 0) {
for (;;) {
while (isspace(*v))
v++;
if (!*v)
break;
while (*v && !isspace(*v))
*cp++ = *v++;
*cp++ = 0;
}
*argv = 0;
return;
}
if (pid < 0) {
}
if (pid == 0) {
int oerrno;
close(1);
}
do {
for (;;) {
c = -1;
} else
c = ch;
if (c <= 0 || isspace(c))
break;
*cp++ = c;
if (--nleft <= 0)
}
--nleft;
*cp++ = 0;
argv++;
}
} while (c >= 0);
waitfor();
}
/*
* Scan genbuf for shell metacharacters.
* Set is union of v7 shell and csh metas.
*/
int
gscan(void)
{
unsigned char *cp;
int len;
return (1);
len = 1;
}
return (0);
}
/*
* Parse one filename into file.
*/
struct glob G;
void
getone(void)
{
unsigned char *str;
if (getargs() == 0)
glob(&G);
if (G.argc0 > 1)
gettext("Too many file names"));
if (G.argc0 < 1)
}
/*
* Read a file from the world.
* C is command, 'e' if this really an edit (or a recover).
*/
void
rop(int c)
{
int i;
short magic;
static int ovro; /* old value(vi_READONLY) */
static int denied; /* 1 if READONLY was set due to file permissions */
if (io < 0) {
edited++;
/*
* If the user just did "ex foo" he is probably
* creating a new file. Don't be an error, since
* this is ugly, and it messes up the + option.
*/
if (!seenprompt) {
noonl();
return;
}
}
denied = 0;
}
syserror(0);
}
syserror(0);
case S_IFBLK:
case S_IFCHR:
break;
case S_IFDIR:
}
if (c != 'r') {
denied = 0;
}
denied = 1;
}
}
flush();
}
if (c == 'r')
setdot();
else
setall();
/* If it is a read command, then we must set dot to addr1
* (value of N in :Nr ). In the default case, addr1 will
* already be set to dot.
*
* Next, it is necessary to mark the beginning (undap1) and
* ending (undap2) addresses affected (for undo). Note that
* rop2() and rop3() will adjust the value of undap2.
*/
}
rop2();
rop3(c);
}
void
rop2(void)
{
deletenone();
clrstats();
if (value(vi_MODELINES))
a = last - 4;
getline(*a);
}
}
void
rop3(int c)
{
if (iostats() == 0 && c == 'e')
edited++;
if (c == 'e') {
if (firstpat) {
firstpat = 0;
if (inopen)
} else
goto other;
} else
if (inopen)
}
if(FIXUNDO)
if (inopen) {
vcline = 0;
}
}
if (laste) {
#ifdef VMUNIX
tlaste();
#endif
laste = 0;
sync();
}
}
/*
* Are these two really the same inode?
*/
int
{
return (0);
}
/* Returns from edited() */
#define EDF 0 /* Edited file */
/*
* Write a file.
*/
void
bool dofname; /* if 1 call filename, else use savedfile */
{
char *messagep;
c = 0;
exclam = 0;
if (dofname) {
if (peekchar() == '!')
(void)skipwh();
while (peekchar() == '>')
if (c != 0 && c != 2)
filename('w');
} else {
if (savedfile[0] == 0)
gettext("No current filename"));
if (inopen) {
vclrech(0);
splitw++;
}
}
switch (c) {
case 0:
switch (edfile()) {
case NOTEDF:
if (nonexist)
break;
break;
break;
}
if (io < 0)
syserror(0);
(unsigned char *)gettext(" File exists") :
(unsigned char *)gettext(" File exists - use \"w! %s\" to overwrite"),
file);
break;
case EDF:
if (value(vi_READONLY))
break;
case PARTBUF:
if (value(vi_READONLY))
}
cre:
/*
synctmp();
*/
if (io < 0)
syserror(0);
writing = 1;
if (hush == 0)
if (nonexist)
break;
case 2:
if (io < 0) {
goto cre;
syserror(0);
}
break;
}
putfile(0);
/*
* For NFS files write in putfile doesn't return error, but
* fsync does. So, catch it here.
*/
"\r\nYour file has been preserved\r\n");
(void) preserve();
wrerror();
}
(void)iostats();
edited = 1;
sync();
}
if (!dofname) {
}
writing = 0;
}
/*
* Is file the edited file?
* Work here is that it is not considered edited
* if this is a partial buffer, and distinguish
* all cases.
*/
int
edfile(void)
{
return (NOTEDF);
}
/*
* Extract the next line from the io stream.
*/
unsigned char *nextip;
int
getfile(void)
{
short c;
unsigned char *lp;
unsigned char *fp;
do {
if (--ninbuf < 0) {
if (ninbuf < 0) {
lp++;
gettext(" [Incomplete last line]"));
break;
}
return (EOF);
}
if(crflag == -1) {
crflag = 2;
else
crflag = -2;
}
break;
}
}
}
c = *fp++;
if (c == 0) {
cntnull++;
continue;
}
*lp++ = c;
} while (c != '\n');
*--lp = 0;
cntln++;
return (0);
}
/*
* Write a range onto the io stream.
*/
void
{
unsigned char *lp;
unsigned char *fp;
int nib;
char *messagep;
/* the event of an interrupt during write */
clrstats();
do {
for (;;) {
if (--nib < 0) {
wrerror();
"\r\nYour file has been preserved\r\n");
(void) preserve();
if (!isfilter)
wrerror();
return;
}
}
break;
}
}
wrerror();
cntln = 0;
return;
}
"\r\nYour file has been preserved\r\n");
(void) preserve();
if(!isfilter)
wrerror();
return;
}
}
/*
* A write error has occurred; if the file being written was
* the edited file then we consider it to have changed since it is
* now likely scrambled.
*/
void
wrerror(void)
{
change();
syserror(1);
}
/*
* Source command, handles nested sources.
* Traps errors since it mungs unit 0 during the source.
*/
short slevel;
short ttyindes;
void
unsigned char *fil;
bool okfail;
{
unsigned char *saveglobp;
short savepeekc;
if (saveinp < 0)
if (slevel <= 0)
close(0);
setrupt();
if (!okfail)
return;
}
slevel++;
setrupt();
if (setexit() == 0)
else if (slevel > 1) {
close(0);
slevel--;
reset();
}
close(0);
slevel--;
}
/*
* Clear io statistics before a read or write.
*/
void
clrstats(void)
{
ninbuf = 0;
cntch = 0;
cntln = 0;
cntnull = 0;
cntodd = 0;
}
/*
* Io is finished, close the unit and print statistics.
*/
int
iostats(void)
{
io = -1;
if (hush == 0) {
/*
* TRANSLATION_NOTE
* Reference order of arguments must not
* be changed using '%digit$', since vi's
* viprintf() does not support it.
*/
cntch);
} else {
/* ridiculous */
}
viprintf(" (");
if (cntnull) {
if (cntodd)
viprintf(", ");
}
if (cntodd)
putchar(')');
}
noonl();
flush();
}
}
unsigned char *aline;
{
unsigned char cmdbuf[1024];
bool savetty;
int savepeekc;
int savechng;
unsigned char *savefirstpat;
unsigned char *p;
int len;
return;
return;
p = aline;
len = 1;
}
if (p != (beg - 2))
return;
}
return;
return;
*end = 0;
peekc = 0;
intty = 0;
firstpat = (unsigned char *)"";
globp = 0;
/* chng being increased indicates that text was changed */
laste = 0;
}