xref: /minix3/external/bsd/nvi/dist/ex/ex_read.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: ex_read.c,v 1.3 2014/01/26 21:43:45 christos Exp $ */
284d9c625SLionel Sambuc /*-
384d9c625SLionel Sambuc  * Copyright (c) 1992, 1993, 1994
484d9c625SLionel Sambuc  *	The Regents of the University of California.  All rights reserved.
584d9c625SLionel Sambuc  * Copyright (c) 1992, 1993, 1994, 1995, 1996
684d9c625SLionel Sambuc  *	Keith Bostic.  All rights reserved.
784d9c625SLionel Sambuc  *
884d9c625SLionel Sambuc  * See the LICENSE file for redistribution information.
984d9c625SLionel Sambuc  */
1084d9c625SLionel Sambuc 
1184d9c625SLionel Sambuc #include "config.h"
1284d9c625SLionel Sambuc 
13*0a6a1f1dSLionel Sambuc #include <sys/cdefs.h>
14*0a6a1f1dSLionel Sambuc #if 0
1584d9c625SLionel Sambuc #ifndef lint
1684d9c625SLionel Sambuc 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 ";
1784d9c625SLionel Sambuc #endif /* not lint */
18*0a6a1f1dSLionel Sambuc #else
19*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: ex_read.c,v 1.3 2014/01/26 21:43:45 christos Exp $");
20*0a6a1f1dSLionel Sambuc #endif
2184d9c625SLionel Sambuc 
2284d9c625SLionel Sambuc #include <sys/types.h>
2384d9c625SLionel Sambuc #include <sys/queue.h>
2484d9c625SLionel Sambuc #include <sys/stat.h>
2584d9c625SLionel Sambuc #include <sys/time.h>
2684d9c625SLionel Sambuc 
2784d9c625SLionel Sambuc #include <bitstring.h>
2884d9c625SLionel Sambuc #include <ctype.h>
2984d9c625SLionel Sambuc #include <errno.h>
3084d9c625SLionel Sambuc #include <limits.h>
3184d9c625SLionel Sambuc #include <stdio.h>
3284d9c625SLionel Sambuc #include <stdlib.h>
3384d9c625SLionel Sambuc #include <string.h>
3484d9c625SLionel Sambuc 
3584d9c625SLionel Sambuc #include "../common/common.h"
3684d9c625SLionel Sambuc #include "../vi/vi.h"
3784d9c625SLionel Sambuc 
3884d9c625SLionel Sambuc /*
3984d9c625SLionel Sambuc  * ex_read --	:read [file]
4084d9c625SLionel Sambuc  *		:read [!cmd]
4184d9c625SLionel Sambuc  *	Read from a file or utility.
4284d9c625SLionel Sambuc  *
4384d9c625SLionel Sambuc  * !!!
4484d9c625SLionel Sambuc  * Historical vi wouldn't undo a filter read, for no apparent reason.
4584d9c625SLionel Sambuc  *
4684d9c625SLionel Sambuc  * PUBLIC: int ex_read __P((SCR *, EXCMD *));
4784d9c625SLionel Sambuc  */
4884d9c625SLionel Sambuc int
ex_read(SCR * sp,EXCMD * cmdp)4984d9c625SLionel Sambuc ex_read(SCR *sp, EXCMD *cmdp)
5084d9c625SLionel Sambuc {
5184d9c625SLionel Sambuc 	enum { R_ARG, R_EXPANDARG, R_FILTER } which;
5284d9c625SLionel Sambuc 	struct stat sb;
5384d9c625SLionel Sambuc 	CHAR_T *arg = NULL;
5484d9c625SLionel Sambuc 	const char *name;
5584d9c625SLionel Sambuc 	size_t nlen;
5684d9c625SLionel Sambuc 	EX_PRIVATE *exp;
5784d9c625SLionel Sambuc 	FILE *fp;
5884d9c625SLionel Sambuc 	FREF *frp;
5984d9c625SLionel Sambuc 	GS *gp;
6084d9c625SLionel Sambuc 	MARK rm;
6184d9c625SLionel Sambuc 	db_recno_t nlines;
6284d9c625SLionel Sambuc 	size_t arglen = 0;
6384d9c625SLionel Sambuc 	int argc, rval;
6484d9c625SLionel Sambuc 	char *p;
6584d9c625SLionel Sambuc 
6661df9b64SLionel Sambuc #if defined(__minix)
6761df9b64SLionel Sambuc 	/* Prevent complains from GCC at -O3 optimisation level. */
6861df9b64SLionel Sambuc 	nlines = 0;
6961df9b64SLionel Sambuc #endif /* defined(__minix) */
7084d9c625SLionel Sambuc 	gp = sp->gp;
7184d9c625SLionel Sambuc 
7284d9c625SLionel Sambuc 	/*
7384d9c625SLionel Sambuc 	 * 0 args: read the current pathname.
7484d9c625SLionel Sambuc 	 * 1 args: check for "read !arg".
7584d9c625SLionel Sambuc 	 */
7684d9c625SLionel Sambuc 	switch (cmdp->argc) {
7784d9c625SLionel Sambuc 	case 0:
7884d9c625SLionel Sambuc 		which = R_ARG;
7984d9c625SLionel Sambuc 		break;
8084d9c625SLionel Sambuc 	case 1:
8184d9c625SLionel Sambuc 		arg = cmdp->argv[0]->bp;
8284d9c625SLionel Sambuc 		arglen = cmdp->argv[0]->len;
8384d9c625SLionel Sambuc 		if (*arg == '!') {
8484d9c625SLionel Sambuc 			++arg;
8584d9c625SLionel Sambuc 			--arglen;
8684d9c625SLionel Sambuc 			which = R_FILTER;
8784d9c625SLionel Sambuc 
8884d9c625SLionel Sambuc 			/* Secure means no shell access. */
8984d9c625SLionel Sambuc 			if (O_ISSET(sp, O_SECURE)) {
9084d9c625SLionel Sambuc 				ex_wemsg(sp, cmdp->cmd->name, EXM_SECURE_F);
9184d9c625SLionel Sambuc 				return (1);
9284d9c625SLionel Sambuc 			}
9384d9c625SLionel Sambuc 		} else
9484d9c625SLionel Sambuc 			which = R_EXPANDARG;
9584d9c625SLionel Sambuc 		break;
9684d9c625SLionel Sambuc 	default:
9784d9c625SLionel Sambuc 		abort();
9884d9c625SLionel Sambuc 		/* NOTREACHED */
9984d9c625SLionel Sambuc 	}
10084d9c625SLionel Sambuc 
10184d9c625SLionel Sambuc 	/* Load a temporary file if no file being edited. */
10284d9c625SLionel Sambuc 	if (sp->ep == NULL) {
10384d9c625SLionel Sambuc 		if ((frp = file_add(sp, NULL)) == NULL)
10484d9c625SLionel Sambuc 			return (1);
10584d9c625SLionel Sambuc 		if (file_init(sp, frp, NULL, 0))
10684d9c625SLionel Sambuc 			return (1);
10784d9c625SLionel Sambuc 	}
10884d9c625SLionel Sambuc 
10984d9c625SLionel Sambuc 	switch (which) {
11084d9c625SLionel Sambuc 	case R_FILTER:
11184d9c625SLionel Sambuc 		/*
11284d9c625SLionel Sambuc 		 * File name and bang expand the user's argument.  If
11384d9c625SLionel Sambuc 		 * we don't get an additional argument, it's illegal.
11484d9c625SLionel Sambuc 		 */
11584d9c625SLionel Sambuc 		argc = cmdp->argc;
11684d9c625SLionel Sambuc 		if (argv_exp1(sp, cmdp, arg, arglen, 1))
11784d9c625SLionel Sambuc 			return (1);
11884d9c625SLionel Sambuc 		if (argc == cmdp->argc) {
11984d9c625SLionel Sambuc 			ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
12084d9c625SLionel Sambuc 			return (1);
12184d9c625SLionel Sambuc 		}
12284d9c625SLionel Sambuc 		argc = cmdp->argc - 1;
12384d9c625SLionel Sambuc 
12484d9c625SLionel Sambuc 		/* Set the last bang command. */
12584d9c625SLionel Sambuc 		exp = EXP(sp);
12684d9c625SLionel Sambuc 		if (exp->lastbcomm != NULL)
12784d9c625SLionel Sambuc 			free(exp->lastbcomm);
12884d9c625SLionel Sambuc 		if ((exp->lastbcomm =
12984d9c625SLionel Sambuc 		    v_wstrdup(sp, cmdp->argv[argc]->bp,
13084d9c625SLionel Sambuc 				cmdp->argv[argc]->len)) == NULL) {
13184d9c625SLionel Sambuc 			msgq(sp, M_SYSERR, NULL);
13284d9c625SLionel Sambuc 			return (1);
13384d9c625SLionel Sambuc 		}
13484d9c625SLionel Sambuc 
13584d9c625SLionel Sambuc 		/*
13684d9c625SLionel Sambuc 		 * Vi redisplayed the user's argument if it changed, ex
13784d9c625SLionel Sambuc 		 * always displayed a !, plus the user's argument if it
13884d9c625SLionel Sambuc 		 * changed.
13984d9c625SLionel Sambuc 		 */
14084d9c625SLionel Sambuc 		if (F_ISSET(sp, SC_VI)) {
14184d9c625SLionel Sambuc 			if (F_ISSET(cmdp, E_MODIFY))
14284d9c625SLionel Sambuc 				(void)vs_update(sp, "!", cmdp->argv[argc]->bp);
14384d9c625SLionel Sambuc 		} else {
14484d9c625SLionel Sambuc 			if (F_ISSET(cmdp, E_MODIFY)) {
14584d9c625SLionel Sambuc 				INT2CHAR(sp, cmdp->argv[argc]->bp,
14684d9c625SLionel Sambuc 				    cmdp->argv[argc]->len + 1, name, nlen);
14784d9c625SLionel Sambuc 				(void)ex_printf(sp,
14884d9c625SLionel Sambuc 				    "!%s\n", name);
14984d9c625SLionel Sambuc 			} else
15084d9c625SLionel Sambuc 				(void)ex_puts(sp, "!\n");
15184d9c625SLionel Sambuc 			(void)ex_fflush(sp);
15284d9c625SLionel Sambuc 		}
15384d9c625SLionel Sambuc 
15484d9c625SLionel Sambuc 		/*
15584d9c625SLionel Sambuc 		 * Historically, filter reads as the first ex command didn't
15684d9c625SLionel Sambuc 		 * wait for the user. If SC_SCR_EXWROTE not already set, set
15784d9c625SLionel Sambuc 		 * the don't-wait flag.
15884d9c625SLionel Sambuc 		 */
15984d9c625SLionel Sambuc 		if (!F_ISSET(sp, SC_SCR_EXWROTE))
16084d9c625SLionel Sambuc 			F_SET(sp, SC_EX_WAIT_NO);
16184d9c625SLionel Sambuc 
16284d9c625SLionel Sambuc 		/*
16384d9c625SLionel Sambuc 		 * Switch into ex canonical mode.  The reason to restore the
16484d9c625SLionel Sambuc 		 * original terminal modes for read filters is so that users
16584d9c625SLionel Sambuc 		 * can do things like ":r! cat /dev/tty".
16684d9c625SLionel Sambuc 		 *
16784d9c625SLionel Sambuc 		 * !!!
16884d9c625SLionel Sambuc 		 * We do not output an extra <newline>, so that we don't touch
16984d9c625SLionel Sambuc 		 * the screen on a normal read.
17084d9c625SLionel Sambuc 		 */
17184d9c625SLionel Sambuc 		if (F_ISSET(sp, SC_VI)) {
17284d9c625SLionel Sambuc 			if (gp->scr_screen(sp, SC_EX)) {
17384d9c625SLionel Sambuc 				ex_wemsg(sp, cmdp->cmd->name, EXM_NOCANON_F);
17484d9c625SLionel Sambuc 				return (1);
17584d9c625SLionel Sambuc 			}
17684d9c625SLionel Sambuc 			/*
17784d9c625SLionel Sambuc 			 * !!!
17884d9c625SLionel Sambuc 			 * Historically, the read command doesn't switch to
17984d9c625SLionel Sambuc 			 * the alternate X11 xterm screen, if doing a filter
18084d9c625SLionel Sambuc 			 * read -- don't set SA_ALTERNATE.
18184d9c625SLionel Sambuc 			 */
18284d9c625SLionel Sambuc 			F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
18384d9c625SLionel Sambuc 		}
18484d9c625SLionel Sambuc 
18584d9c625SLionel Sambuc 		if (ex_filter(sp, cmdp, &cmdp->addr1,
18684d9c625SLionel Sambuc 		    NULL, &rm, cmdp->argv[argc]->bp, FILTER_READ))
18784d9c625SLionel Sambuc 			return (1);
18884d9c625SLionel Sambuc 
18984d9c625SLionel Sambuc 		/* The filter version of read set the autoprint flag. */
19084d9c625SLionel Sambuc 		F_SET(cmdp, E_AUTOPRINT);
19184d9c625SLionel Sambuc 
19284d9c625SLionel Sambuc 		/*
19384d9c625SLionel Sambuc 		 * If in vi mode, move to the first nonblank.  Might have
19484d9c625SLionel Sambuc 		 * switched into ex mode, so saved the original SC_VI value.
19584d9c625SLionel Sambuc 		 */
19684d9c625SLionel Sambuc 		sp->lno = rm.lno;
19784d9c625SLionel Sambuc 		if (F_ISSET(sp, SC_VI)) {
19884d9c625SLionel Sambuc 			sp->cno = 0;
19984d9c625SLionel Sambuc 			(void)nonblank(sp, sp->lno, &sp->cno);
20084d9c625SLionel Sambuc 		}
20184d9c625SLionel Sambuc 		return (0);
20284d9c625SLionel Sambuc 	case R_ARG:
20384d9c625SLionel Sambuc 		name = sp->frp->name;
20484d9c625SLionel Sambuc 		break;
20584d9c625SLionel Sambuc 	case R_EXPANDARG:
20684d9c625SLionel Sambuc 		if (argv_exp2(sp, cmdp, arg, arglen))
20784d9c625SLionel Sambuc 			return (1);
20884d9c625SLionel Sambuc 		/*
20984d9c625SLionel Sambuc 		 *  0 args: impossible.
21084d9c625SLionel Sambuc 		 *  1 args: impossible (I hope).
21184d9c625SLionel Sambuc 		 *  2 args: read it.
21284d9c625SLionel Sambuc 		 * >2 args: object, too many args.
21384d9c625SLionel Sambuc 		 *
21484d9c625SLionel Sambuc 		 * The 1 args case depends on the argv_sexp() function refusing
21584d9c625SLionel Sambuc 		 * to return success without at least one non-blank character.
21684d9c625SLionel Sambuc 		 */
21784d9c625SLionel Sambuc 		switch (cmdp->argc) {
21884d9c625SLionel Sambuc 		case 0:
21984d9c625SLionel Sambuc 		case 1:
22084d9c625SLionel Sambuc 			abort();
22184d9c625SLionel Sambuc 			/* NOTREACHED */
22284d9c625SLionel Sambuc 		case 2:
22384d9c625SLionel Sambuc 			INT2CHAR(sp, cmdp->argv[1]->bp, cmdp->argv[1]->len + 1,
22484d9c625SLionel Sambuc 				 name, nlen);
22584d9c625SLionel Sambuc 			/*
22684d9c625SLionel Sambuc 			 * !!!
22784d9c625SLionel Sambuc 			 * Historically, the read and write commands renamed
22884d9c625SLionel Sambuc 			 * "unnamed" files, or, if the file had a name, set
22984d9c625SLionel Sambuc 			 * the alternate file name.
23084d9c625SLionel Sambuc 			 */
23184d9c625SLionel Sambuc 			if (F_ISSET(sp->frp, FR_TMPFILE) &&
23284d9c625SLionel Sambuc 			    !F_ISSET(sp->frp, FR_EXNAMED)) {
23384d9c625SLionel Sambuc 				if ((p = strdup(name)) != NULL) {
23484d9c625SLionel Sambuc 					free(sp->frp->name);
23584d9c625SLionel Sambuc 					sp->frp->name = p;
23684d9c625SLionel Sambuc 				}
23784d9c625SLionel Sambuc 				/*
23884d9c625SLionel Sambuc 				 * The file has a real name, it's no longer a
23984d9c625SLionel Sambuc 				 * temporary, clear the temporary file flags.
24084d9c625SLionel Sambuc 				 */
24184d9c625SLionel Sambuc 				F_CLR(sp->frp, FR_TMPEXIT | FR_TMPFILE);
24284d9c625SLionel Sambuc 				F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED);
24384d9c625SLionel Sambuc 
24484d9c625SLionel Sambuc 				/* Notify the screen. */
24584d9c625SLionel Sambuc 				(void)sp->gp->scr_rename(sp, sp->frp->name, 1);
24684d9c625SLionel Sambuc 				name = sp->frp->name;
24784d9c625SLionel Sambuc 			} else {
24884d9c625SLionel Sambuc 				set_alt_name(sp, name);
24984d9c625SLionel Sambuc 				name = sp->alt_name;
25084d9c625SLionel Sambuc 			}
25184d9c625SLionel Sambuc 			break;
25284d9c625SLionel Sambuc 		default:
25384d9c625SLionel Sambuc 			ex_wemsg(sp, cmdp->argv[0]->bp, EXM_FILECOUNT);
25484d9c625SLionel Sambuc 			return (1);
25584d9c625SLionel Sambuc 
25684d9c625SLionel Sambuc 		}
25784d9c625SLionel Sambuc 		break;
25884d9c625SLionel Sambuc 	}
25984d9c625SLionel Sambuc 
26084d9c625SLionel Sambuc 	/*
26184d9c625SLionel Sambuc 	 * !!!
26284d9c625SLionel Sambuc 	 * Historically, vi did not permit reads from non-regular files, nor
26384d9c625SLionel Sambuc 	 * did it distinguish between "read !" and "read!", so there was no
26484d9c625SLionel Sambuc 	 * way to "force" it.  We permit reading from named pipes too, since
26584d9c625SLionel Sambuc 	 * they didn't exist when the original implementation of vi was done
26684d9c625SLionel Sambuc 	 * and they seem a reasonable addition.
26784d9c625SLionel Sambuc 	 */
26884d9c625SLionel Sambuc 	if ((fp = fopen(name, "r")) == NULL || fstat(fileno(fp), &sb)) {
26984d9c625SLionel Sambuc 		msgq_str(sp, M_SYSERR, name, "%s");
27084d9c625SLionel Sambuc 		return (1);
27184d9c625SLionel Sambuc 	}
27284d9c625SLionel Sambuc 	if (!S_ISFIFO(sb.st_mode) && !S_ISREG(sb.st_mode)) {
27384d9c625SLionel Sambuc 		(void)fclose(fp);
27484d9c625SLionel Sambuc 		msgq(sp, M_ERR,
27584d9c625SLionel Sambuc 		    "145|Only regular files and named pipes may be read");
27684d9c625SLionel Sambuc 		return (1);
27784d9c625SLionel Sambuc 	}
27884d9c625SLionel Sambuc 
27984d9c625SLionel Sambuc 	/* Try and get a lock. */
28084d9c625SLionel Sambuc 	if (file_lock(sp, NULL, NULL, fileno(fp), 0) == LOCK_UNAVAIL)
28184d9c625SLionel Sambuc 		msgq(sp, M_ERR, "146|%s: read lock was unavailable", name);
28284d9c625SLionel Sambuc 
28384d9c625SLionel Sambuc 	rval = ex_readfp(sp, name, fp, &cmdp->addr1, &nlines, 0);
28484d9c625SLionel Sambuc 
28584d9c625SLionel Sambuc 	/*
28684d9c625SLionel Sambuc 	 * In vi, set the cursor to the first line read in, if anything read
28784d9c625SLionel Sambuc 	 * in, otherwise, the address.  (Historic vi set it to the line after
28884d9c625SLionel Sambuc 	 * the address regardless, but since that line may not exist we don't
28984d9c625SLionel Sambuc 	 * bother.)
29084d9c625SLionel Sambuc 	 *
29184d9c625SLionel Sambuc 	 * In ex, set the cursor to the last line read in, if anything read in,
29284d9c625SLionel Sambuc 	 * otherwise, the address.
29384d9c625SLionel Sambuc 	 */
29484d9c625SLionel Sambuc 	if (F_ISSET(sp, SC_VI)) {
29584d9c625SLionel Sambuc 		sp->lno = cmdp->addr1.lno;
29684d9c625SLionel Sambuc 		if (nlines)
29784d9c625SLionel Sambuc 			++sp->lno;
29884d9c625SLionel Sambuc 	} else
29984d9c625SLionel Sambuc 		sp->lno = cmdp->addr1.lno + nlines;
30084d9c625SLionel Sambuc 	return (rval);
30184d9c625SLionel Sambuc }
30284d9c625SLionel Sambuc 
30384d9c625SLionel Sambuc /*
30484d9c625SLionel Sambuc  * ex_readfp --
30584d9c625SLionel Sambuc  *	Read lines into the file.
30684d9c625SLionel Sambuc  *
30784d9c625SLionel Sambuc  * PUBLIC: int ex_readfp __P((SCR *, const char *, FILE *, MARK *, db_recno_t *, int));
30884d9c625SLionel Sambuc  */
30984d9c625SLionel Sambuc int
ex_readfp(SCR * sp,const char * name,FILE * fp,MARK * fm,db_recno_t * nlinesp,int silent)31084d9c625SLionel Sambuc ex_readfp(SCR *sp, const char *name, FILE *fp, MARK *fm, db_recno_t *nlinesp, int silent)
31184d9c625SLionel Sambuc {
31284d9c625SLionel Sambuc 	EX_PRIVATE *exp;
31384d9c625SLionel Sambuc 	GS *gp;
31484d9c625SLionel Sambuc 	db_recno_t lcnt, lno;
31584d9c625SLionel Sambuc 	size_t len;
31684d9c625SLionel Sambuc 	u_long ccnt;			/* XXX: can't print off_t portably. */
31784d9c625SLionel Sambuc 	int nf, rval;
31884d9c625SLionel Sambuc 	const char *p;
31984d9c625SLionel Sambuc 	size_t wlen;
32084d9c625SLionel Sambuc 	const CHAR_T *wp;
32184d9c625SLionel Sambuc 
32284d9c625SLionel Sambuc 	gp = sp->gp;
32384d9c625SLionel Sambuc 	exp = EXP(sp);
32484d9c625SLionel Sambuc 
32584d9c625SLionel Sambuc 	/*
32684d9c625SLionel Sambuc 	 * Add in the lines from the output.  Insertion starts at the line
32784d9c625SLionel Sambuc 	 * following the address.
32884d9c625SLionel Sambuc 	 */
32984d9c625SLionel Sambuc 	ccnt = 0;
33084d9c625SLionel Sambuc 	lcnt = 0;
33184d9c625SLionel Sambuc 	p = "147|Reading...";
33284d9c625SLionel Sambuc 	for (lno = fm->lno; !ex_getline(sp, fp, &len); ++lno, ++lcnt) {
33384d9c625SLionel Sambuc 		if ((lcnt + 1) % INTERRUPT_CHECK == 0) {
33484d9c625SLionel Sambuc 			if (INTERRUPTED(sp))
33584d9c625SLionel Sambuc 				break;
33684d9c625SLionel Sambuc 			if (!silent) {
33784d9c625SLionel Sambuc 				gp->scr_busy(sp, p,
33884d9c625SLionel Sambuc 				    p == NULL ? BUSY_UPDATE : BUSY_ON);
33984d9c625SLionel Sambuc 				p = NULL;
34084d9c625SLionel Sambuc 			}
34184d9c625SLionel Sambuc 		}
34284d9c625SLionel Sambuc 		FILE2INT5(sp, exp->ibcw, exp->ibp, len, wp, wlen);
34384d9c625SLionel Sambuc 		if (db_append(sp, 1, lno, wp, wlen))
34484d9c625SLionel Sambuc 			goto err;
34584d9c625SLionel Sambuc 		ccnt += len;
34684d9c625SLionel Sambuc 	}
34784d9c625SLionel Sambuc 
34884d9c625SLionel Sambuc 	if (ferror(fp) || fclose(fp))
34984d9c625SLionel Sambuc 		goto err;
35084d9c625SLionel Sambuc 
35184d9c625SLionel Sambuc 	/* Return the number of lines read in. */
35284d9c625SLionel Sambuc 	if (nlinesp != NULL)
35384d9c625SLionel Sambuc 		*nlinesp = lcnt;
35484d9c625SLionel Sambuc 
35584d9c625SLionel Sambuc 	if (!silent) {
35684d9c625SLionel Sambuc 		char *q = msg_print(sp, name, &nf);
35784d9c625SLionel Sambuc 		msgq(sp, M_INFO,
35884d9c625SLionel Sambuc 		    "148|%s: %lu lines, %lu characters", q, (unsigned long)lcnt,
35984d9c625SLionel Sambuc 		    (unsigned long)ccnt);
36084d9c625SLionel Sambuc 		if (nf)
36184d9c625SLionel Sambuc 			FREE_SPACE(sp, q, 0);
36284d9c625SLionel Sambuc 	}
36384d9c625SLionel Sambuc 
36484d9c625SLionel Sambuc 	rval = 0;
36584d9c625SLionel Sambuc 	if (0) {
36684d9c625SLionel Sambuc err:		msgq_str(sp, M_SYSERR, name, "%s");
36784d9c625SLionel Sambuc 		(void)fclose(fp);
36884d9c625SLionel Sambuc 		rval = 1;
36984d9c625SLionel Sambuc 	}
37084d9c625SLionel Sambuc 
37184d9c625SLionel Sambuc 	if (!silent)
37284d9c625SLionel Sambuc 		gp->scr_busy(sp, NULL, BUSY_OFF);
37384d9c625SLionel Sambuc 	return (rval);
37484d9c625SLionel Sambuc }
375