1e0b8e63eSJohn Marino /*-
2e0b8e63eSJohn Marino * Copyright (c) 1992, 1993, 1994
3e0b8e63eSJohn Marino * The Regents of the University of California. All rights reserved.
4e0b8e63eSJohn Marino * Copyright (c) 1992, 1993, 1994, 1995, 1996
5e0b8e63eSJohn Marino * Keith Bostic. All rights reserved.
6e0b8e63eSJohn Marino *
7e0b8e63eSJohn Marino * See the LICENSE file for redistribution information.
8e0b8e63eSJohn Marino */
9e0b8e63eSJohn Marino
10e0b8e63eSJohn Marino #include "config.h"
11e0b8e63eSJohn Marino
12e0b8e63eSJohn Marino #include <sys/types.h>
13e0b8e63eSJohn Marino #include <sys/queue.h>
14e0b8e63eSJohn Marino #include <sys/stat.h>
15e0b8e63eSJohn Marino
16e0b8e63eSJohn Marino #include <bitstring.h>
17e0b8e63eSJohn Marino #include <errno.h>
18e0b8e63eSJohn Marino #include <fcntl.h>
19e0b8e63eSJohn Marino #include <limits.h>
20e0b8e63eSJohn Marino #include <stdio.h>
21e0b8e63eSJohn Marino #include <stdlib.h>
22e0b8e63eSJohn Marino #include <string.h>
23e0b8e63eSJohn Marino #include <unistd.h>
24e0b8e63eSJohn Marino
25e0b8e63eSJohn Marino #include "../common/common.h"
26e0b8e63eSJohn Marino
27e0b8e63eSJohn Marino /*
28e0b8e63eSJohn Marino * ex_source -- :source file
29e0b8e63eSJohn Marino * Execute ex commands from a file.
30e0b8e63eSJohn Marino *
31e0b8e63eSJohn Marino * PUBLIC: int ex_source(SCR *, EXCMD *);
32e0b8e63eSJohn Marino */
33e0b8e63eSJohn Marino int
ex_source(SCR * sp,EXCMD * cmdp)34e0b8e63eSJohn Marino ex_source(SCR *sp, EXCMD *cmdp)
35e0b8e63eSJohn Marino {
36e0b8e63eSJohn Marino struct stat sb;
37e0b8e63eSJohn Marino int fd, len;
38e0b8e63eSJohn Marino char *bp;
39e0b8e63eSJohn Marino char *name, *np;
40e0b8e63eSJohn Marino size_t nlen;
41e0b8e63eSJohn Marino CHAR_T *wp;
42e0b8e63eSJohn Marino size_t wlen;
43e0b8e63eSJohn Marino int rc;
44e0b8e63eSJohn Marino
45e0b8e63eSJohn Marino INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len + 1, name, nlen);
46e0b8e63eSJohn Marino if ((fd = open(name, O_RDONLY, 0)) < 0 || fstat(fd, &sb))
47e0b8e63eSJohn Marino goto err;
48e0b8e63eSJohn Marino
49e0b8e63eSJohn Marino /*
50e0b8e63eSJohn Marino * XXX
51e0b8e63eSJohn Marino * I'd like to test to see if the file is too large to malloc. Since
52e0b8e63eSJohn Marino * we don't know what size or type off_t's or size_t's are, what the
53e0b8e63eSJohn Marino * largest unsigned integral type is, or what random insanity the local
54e0b8e63eSJohn Marino * C compiler will perpetrate, doing the comparison in a portable way
55e0b8e63eSJohn Marino * is flatly impossible. So, put an fairly unreasonable limit on it,
56e0b8e63eSJohn Marino * I don't want to be dropping core here.
57e0b8e63eSJohn Marino */
58e0b8e63eSJohn Marino #define MEGABYTE 1048576
59e0b8e63eSJohn Marino if (sb.st_size > MEGABYTE) {
60e0b8e63eSJohn Marino errno = ENOMEM;
61e0b8e63eSJohn Marino goto err;
62e0b8e63eSJohn Marino }
63e0b8e63eSJohn Marino
64*b1ac2ebbSDaniel Fojt MALLOC(sp, bp, (size_t)sb.st_size + 1);
65e0b8e63eSJohn Marino if (bp == NULL) {
66e0b8e63eSJohn Marino (void)close(fd);
67e0b8e63eSJohn Marino return (1);
68e0b8e63eSJohn Marino }
69e0b8e63eSJohn Marino bp[sb.st_size] = '\0';
70e0b8e63eSJohn Marino
71e0b8e63eSJohn Marino /* Read the file into memory. */
72e0b8e63eSJohn Marino len = read(fd, bp, (int)sb.st_size);
73e0b8e63eSJohn Marino (void)close(fd);
74e0b8e63eSJohn Marino if (len == -1 || len != sb.st_size) {
75e0b8e63eSJohn Marino if (len != sb.st_size)
76e0b8e63eSJohn Marino errno = EIO;
77e0b8e63eSJohn Marino free(bp);
78e0b8e63eSJohn Marino err: msgq_str(sp, M_SYSERR, name, "%s");
79e0b8e63eSJohn Marino return (1);
80e0b8e63eSJohn Marino }
81e0b8e63eSJohn Marino
82e0b8e63eSJohn Marino np = strdup(name);
83e0b8e63eSJohn Marino if (CHAR2INT(sp, bp, (size_t)sb.st_size + 1, wp, wlen))
84e0b8e63eSJohn Marino msgq(sp, M_ERR, "323|Invalid input. Truncated.");
85e0b8e63eSJohn Marino /* Put it on the ex queue. */
86e0b8e63eSJohn Marino rc = ex_run_str(sp, np, wp, wlen - 1, 1, 0);
87e0b8e63eSJohn Marino free(np);
88e0b8e63eSJohn Marino free(bp);
89e0b8e63eSJohn Marino return (rc);
90e0b8e63eSJohn Marino }
91