1 /*-
2 * Copyright (c) 1992, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1992, 1993, 1994, 1995, 1996
5 * Keith Bostic. All rights reserved.
6 *
7 * See the LICENSE file for redistribution information.
8 */
9
10 #include "config.h"
11
12 #include <sys/types.h>
13 #include <sys/queue.h>
14 #include <sys/stat.h>
15
16 #include <bitstring.h>
17 #include <ctype.h>
18 #include <errno.h>
19 #include <limits.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include "../common/common.h"
25 #include "../vi/vi.h"
26
27 /*
28 * ex_read -- :read [file]
29 * :read [!cmd]
30 * Read from a file or utility.
31 *
32 * !!!
33 * Historical vi wouldn't undo a filter read, for no apparent reason.
34 *
35 * PUBLIC: int ex_read(SCR *, EXCMD *);
36 */
37 int
ex_read(SCR * sp,EXCMD * cmdp)38 ex_read(SCR *sp, EXCMD *cmdp)
39 {
40 enum { R_ARG, R_EXPANDARG, R_FILTER } which;
41 struct stat sb;
42 CHAR_T *arg = NULL;
43 char *name = NULL;
44 size_t nlen;
45 EX_PRIVATE *exp;
46 FILE *fp;
47 FREF *frp;
48 GS *gp;
49 MARK rm;
50 recno_t nlines;
51 size_t arglen = 0;
52 int argc, rval;
53 char *p;
54
55 gp = sp->gp;
56
57 /*
58 * 0 args: read the current pathname.
59 * 1 args: check for "read !arg".
60 */
61 switch (cmdp->argc) {
62 case 0:
63 which = R_ARG;
64 break;
65 case 1:
66 arg = cmdp->argv[0]->bp;
67 arglen = cmdp->argv[0]->len;
68 if (*arg == '!') {
69 ++arg;
70 --arglen;
71 which = R_FILTER;
72
73 /* Secure means no shell access. */
74 if (O_ISSET(sp, O_SECURE)) {
75 ex_wemsg(sp, cmdp->cmd->name, EXM_SECURE_F);
76 return (1);
77 }
78 } else
79 which = R_EXPANDARG;
80 break;
81 default:
82 abort();
83 /* NOTREACHED */
84 }
85
86 /* Load a temporary file if no file being edited. */
87 if (sp->ep == NULL) {
88 if ((frp = file_add(sp, NULL)) == NULL)
89 return (1);
90 if (file_init(sp, frp, NULL, 0))
91 return (1);
92 }
93
94 switch (which) {
95 case R_FILTER:
96 /*
97 * File name and bang expand the user's argument. If
98 * we don't get an additional argument, it's illegal.
99 */
100 argc = cmdp->argc;
101 if (argv_exp1(sp, cmdp, arg, arglen, 1))
102 return (1);
103 if (argc == cmdp->argc) {
104 ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
105 return (1);
106 }
107 argc = cmdp->argc - 1;
108
109 /* Set the last bang command. */
110 exp = EXP(sp);
111 free(exp->lastbcomm);
112 if ((exp->lastbcomm =
113 v_wstrdup(sp, cmdp->argv[argc]->bp,
114 cmdp->argv[argc]->len)) == NULL) {
115 msgq(sp, M_SYSERR, NULL);
116 return (1);
117 }
118
119 /*
120 * Vi redisplayed the user's argument if it changed, ex
121 * always displayed a !, plus the user's argument if it
122 * changed.
123 */
124 if (F_ISSET(sp, SC_VI)) {
125 if (F_ISSET(cmdp, E_MODIFY))
126 (void)vs_update(sp, "!", cmdp->argv[argc]->bp);
127 } else {
128 if (F_ISSET(cmdp, E_MODIFY))
129 (void)ex_printf(sp,
130 "!"WS"\n", cmdp->argv[argc]->bp);
131 else
132 (void)ex_puts(sp, "!\n");
133 (void)ex_fflush(sp);
134 }
135
136 /*
137 * Historically, filter reads as the first ex command didn't
138 * wait for the user. If SC_SCR_EXWROTE not already set, set
139 * the don't-wait flag.
140 */
141 if (!F_ISSET(sp, SC_SCR_EXWROTE))
142 F_SET(sp, SC_EX_WAIT_NO);
143
144 /*
145 * Switch into ex canonical mode. The reason to restore the
146 * original terminal modes for read filters is so that users
147 * can do things like ":r! cat /dev/tty".
148 *
149 * !!!
150 * We do not output an extra <newline>, so that we don't touch
151 * the screen on a normal read.
152 */
153 if (F_ISSET(sp, SC_VI)) {
154 if (gp->scr_screen(sp, SC_EX)) {
155 ex_wemsg(sp, cmdp->cmd->name, EXM_NOCANON_F);
156 return (1);
157 }
158 /*
159 * !!!
160 * Historically, the read command doesn't switch to
161 * the alternate X11 xterm screen, if doing a filter
162 * read -- don't set SA_ALTERNATE.
163 */
164 F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
165 }
166
167 if (ex_filter(sp, cmdp, &cmdp->addr1,
168 NULL, &rm, cmdp->argv[argc]->bp, FILTER_READ))
169 return (1);
170
171 /* The filter version of read set the autoprint flag. */
172 F_SET(cmdp, E_AUTOPRINT);
173
174 /*
175 * If in vi mode, move to the first nonblank. Might have
176 * switched into ex mode, so saved the original SC_VI value.
177 */
178 sp->lno = rm.lno;
179 if (F_ISSET(sp, SC_VI)) {
180 sp->cno = 0;
181 (void)nonblank(sp, sp->lno, &sp->cno);
182 }
183 return (0);
184 case R_ARG:
185 name = sp->frp->name;
186 break;
187 case R_EXPANDARG:
188 if (argv_exp2(sp, cmdp, arg, arglen))
189 return (1);
190 /*
191 * 0 args: impossible.
192 * 1 args: impossible (I hope).
193 * 2 args: read it.
194 * >2 args: object, too many args.
195 *
196 * The 1 args case depends on the argv_sexp() function refusing
197 * to return success without at least one non-blank character.
198 */
199 switch (cmdp->argc) {
200 case 0:
201 case 1:
202 abort();
203 /* NOTREACHED */
204 case 2:
205 INT2CHAR(sp, cmdp->argv[1]->bp, cmdp->argv[1]->len + 1,
206 name, nlen);
207 /*
208 * !!!
209 * Historically, the read and write commands renamed
210 * "unnamed" files, or, if the file had a name, set
211 * the alternate file name.
212 */
213 if (F_ISSET(sp->frp, FR_TMPFILE) &&
214 !F_ISSET(sp->frp, FR_EXNAMED)) {
215 if ((p = strdup(name)) != NULL) {
216 free(sp->frp->name);
217 sp->frp->name = p;
218 }
219 /*
220 * The file has a real name, it's no longer a
221 * temporary, clear the temporary file flags.
222 */
223 F_CLR(sp->frp, FR_TMPEXIT | FR_TMPFILE);
224 F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED);
225
226 /* Notify the screen. */
227 (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
228 name = sp->frp->name;
229 } else {
230 set_alt_name(sp, name);
231 name = sp->alt_name;
232 }
233 break;
234 default:
235 ex_wemsg(sp, cmdp->argv[0]->bp, EXM_FILECOUNT);
236 return (1);
237
238 }
239 break;
240 }
241
242 /*
243 * !!!
244 * Historically, vi did not permit reads from non-regular files, nor
245 * did it distinguish between "read !" and "read!", so there was no
246 * way to "force" it. We permit reading from named pipes too, since
247 * they didn't exist when the original implementation of vi was done
248 * and they seem a reasonable addition.
249 */
250 if ((fp = fopen(name, "r")) == NULL || fstat(fileno(fp), &sb)) {
251 msgq_str(sp, M_SYSERR, name, "%s");
252 return (1);
253 }
254 if (!S_ISFIFO(sb.st_mode) && !S_ISREG(sb.st_mode)) {
255 (void)fclose(fp);
256 msgq(sp, M_ERR,
257 "145|Only regular files and named pipes may be read");
258 return (1);
259 }
260
261 /* Try and get a lock. */
262 if (file_lock(sp, NULL, fileno(fp), 0) == LOCK_UNAVAIL)
263 msgq(sp, M_ERR, "146|%s: read lock was unavailable", name);
264
265 rval = ex_readfp(sp, name, fp, &cmdp->addr1, &nlines, 0);
266
267 /*
268 * In vi, set the cursor to the first line read in, if anything read
269 * in, otherwise, the address. (Historic vi set it to the line after
270 * the address regardless, but since that line may not exist we don't
271 * bother.)
272 *
273 * In ex, set the cursor to the last line read in, if anything read in,
274 * otherwise, the address.
275 */
276 if (F_ISSET(sp, SC_VI)) {
277 sp->lno = cmdp->addr1.lno;
278 if (nlines)
279 ++sp->lno;
280 } else
281 sp->lno = cmdp->addr1.lno + nlines;
282 return (rval);
283 }
284
285 /*
286 * ex_readfp --
287 * Read lines into the file.
288 *
289 * PUBLIC: int ex_readfp(SCR *, char *, FILE *, MARK *, recno_t *, int);
290 */
291 int
ex_readfp(SCR * sp,char * name,FILE * fp,MARK * fm,recno_t * nlinesp,int silent)292 ex_readfp(SCR *sp, char *name, FILE *fp, MARK *fm, recno_t *nlinesp, int silent)
293 {
294 EX_PRIVATE *exp;
295 GS *gp;
296 recno_t lcnt, lno;
297 size_t len;
298 u_long ccnt; /* XXX: can't print off_t portably. */
299 int nf, rval;
300 char *p;
301 size_t wlen;
302 CHAR_T *wp;
303
304 gp = sp->gp;
305 exp = EXP(sp);
306
307 /*
308 * Add in the lines from the output. Insertion starts at the line
309 * following the address.
310 */
311 ccnt = 0;
312 lcnt = 0;
313 p = "147|Reading...";
314 for (lno = fm->lno; !ex_getline(sp, fp, &len); ++lno, ++lcnt) {
315 if ((lcnt + 1) % INTERRUPT_CHECK == 0) {
316 if (INTERRUPTED(sp))
317 break;
318 if (!silent) {
319 gp->scr_busy(sp, p,
320 p == NULL ? BUSY_UPDATE : BUSY_ON);
321 p = NULL;
322 }
323 }
324 FILE2INT5(sp, exp->ibcw, exp->ibp, len, wp, wlen);
325 if (db_append(sp, 1, lno, wp, wlen))
326 goto err;
327 ccnt += len;
328 }
329
330 if (ferror(fp) || fclose(fp))
331 goto err;
332
333 /* Return the number of lines read in. */
334 if (nlinesp != NULL)
335 *nlinesp = lcnt;
336
337 if (!silent) {
338 p = msg_print(sp, name, &nf);
339 msgq(sp, M_INFO,
340 "148|%s: %lu lines, %lu characters", p,
341 (u_long)lcnt, ccnt);
342 if (nf)
343 FREE_SPACE(sp, p, 0);
344 }
345
346 rval = 0;
347 if (0) {
348 err: msgq_str(sp, M_SYSERR, name, "%s");
349 (void)fclose(fp);
350 rval = 1;
351 }
352
353 if (!silent)
354 gp->scr_busy(sp, NULL, BUSY_OFF);
355 return (rval);
356 }
357