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