1135446Strhodes/*- 2193149Sdougb * Copyright (c) 1992, 1993, 1994 3135446Strhodes * The Regents of the University of California. All rights reserved. 4135446Strhodes * Copyright (c) 1992, 1993, 1994, 1995, 1996 5193149Sdougb * Keith Bostic. All rights reserved. 6135446Strhodes * 7135446Strhodes * See the LICENSE file for redistribution information. 8135446Strhodes */ 9135446Strhodes 10135446Strhodes#include "config.h" 11135446Strhodes 12135446Strhodes#ifndef lint 13135446Strhodesstatic const char sccsid[] = "$Id: ex_source.c,v 10.17 2011/12/19 16:17:06 zy Exp $"; 14135446Strhodes#endif /* not lint */ 15135446Strhodes 16135446Strhodes#include <sys/types.h> 17135446Strhodes#include <sys/queue.h> 18234010Sdougb#include <sys/stat.h> 19135446Strhodes 20170222Sdougb#include <bitstring.h> 21170222Sdougb#include <errno.h> 22135446Strhodes#include <fcntl.h> 23135446Strhodes#include <limits.h> 24135446Strhodes#include <stdio.h> 25135446Strhodes#include <stdlib.h> 26135446Strhodes#include <string.h> 27135446Strhodes#include <unistd.h> 28135446Strhodes 29135446Strhodes#include "../common/common.h" 30170222Sdougb 31135446Strhodes/* 32135446Strhodes * ex_source -- :source file 33135446Strhodes * Execute ex commands from a file. 34135446Strhodes * 35170222Sdougb * PUBLIC: int ex_source __P((SCR *, EXCMD *)); 36135446Strhodes */ 37135446Strhodesint 38135446Strhodesex_source(SCR *sp, EXCMD *cmdp) 39135446Strhodes{ 40170222Sdougb struct stat sb; 41135446Strhodes int fd, len; 42135446Strhodes char *bp; 43135446Strhodes char *name, *np; 44135446Strhodes size_t nlen; 45135446Strhodes CHAR_T *wp; 46135446Strhodes size_t wlen; 47135446Strhodes int rc; 48135446Strhodes 49135446Strhodes INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len + 1, name, nlen); 50135446Strhodes if ((fd = open(name, O_RDONLY, 0)) < 0 || fstat(fd, &sb)) 51135446Strhodes goto err; 52135446Strhodes 53135446Strhodes /* 54135446Strhodes * XXX 55135446Strhodes * I'd like to test to see if the file is too large to malloc. Since 56135446Strhodes * we don't know what size or type off_t's or size_t's are, what the 57135446Strhodes * largest unsigned integral type is, or what random insanity the local 58135446Strhodes * C compiler will perpetrate, doing the comparison in a portable way 59135446Strhodes * is flatly impossible. So, put an fairly unreasonable limit on it, 60135446Strhodes * I don't want to be dropping core here. 61135446Strhodes */ 62135446Strhodes#define MEGABYTE 1048576 63135446Strhodes if (sb.st_size > MEGABYTE) { 64135446Strhodes errno = ENOMEM; 65135446Strhodes goto err; 66135446Strhodes } 67135446Strhodes 68135446Strhodes MALLOC(sp, bp, char *, (size_t)sb.st_size + 1); 69135446Strhodes if (bp == NULL) { 70135446Strhodes (void)close(fd); 71135446Strhodes return (1); 72135446Strhodes } 73135446Strhodes bp[sb.st_size] = '\0'; 74135446Strhodes 75135446Strhodes /* Read the file into memory. */ 76135446Strhodes len = read(fd, bp, (int)sb.st_size); 77135446Strhodes (void)close(fd); 78135446Strhodes if (len == -1 || len != sb.st_size) { 79135446Strhodes if (len != sb.st_size) 80135446Strhodes errno = EIO; 81135446Strhodes free(bp); 82135446Strhodeserr: msgq_str(sp, M_SYSERR, name, "%s"); 83135446Strhodes return (1); 84135446Strhodes } 85135446Strhodes 86135446Strhodes np = strdup(name); 87135446Strhodes if (CHAR2INT(sp, bp, (size_t)sb.st_size + 1, wp, wlen)) 88135446Strhodes msgq(sp, M_ERR, "323|Invalid input. Truncated."); 89135446Strhodes /* Put it on the ex queue. */ 90135446Strhodes rc = ex_run_str(sp, np, wp, wlen - 1, 1, 0); 91135446Strhodes if (np != NULL) 92135446Strhodes free(np); 93135446Strhodes free(bp); 94135446Strhodes return (rc); 95135446Strhodes} 96135446Strhodes