Пример #1
0
static void
scriptexec(struct op *tp, const char **ap)
{
	const char *sh;
#ifndef MKSH_SMALL
	int fd;
	unsigned char buf[68];
#endif
	union mksh_ccphack args, cap;

	sh = str_val(global("EXECSHELL"));
	if (sh && *sh)
		sh = search_path(sh, path, X_OK, NULL);
	if (!sh || !*sh)
		sh = MKSH_DEFAULT_EXECSHELL;

	*tp->args-- = tp->str;

#ifndef MKSH_SMALL
	if ((fd = binopen2(tp->str, O_RDONLY)) >= 0) {
		unsigned char *cp;
		unsigned short m;
		ssize_t n;

		/* read first couple of octets from file */
		n = read(fd, buf, sizeof(buf) - 1);
		close(fd);
		/* read error or short read? */
		if (n < 5)
			goto nomagic;
		/* terminate buffer */
		buf[n] = '\0';

		/* skip UTF-8 Byte Order Mark, if present */
		cp = buf + (n = ((buf[0] == 0xEF) && (buf[1] == 0xBB) &&
		    (buf[2] == 0xBF)) ? 3 : 0);

		/* scan for newline or NUL (end of buffer) */
		while (*cp && *cp != '\n')
			++cp;
		/* if the shebang line is longer than MAXINTERP, bail out */
		if (!*cp)
			goto noshebang;
		/* replace newline by NUL */
		*cp = '\0';

		/* restore begin of shebang position (buf+0 or buf+3) */
		cp = buf + n;
		/* bail out if no shebang magic found */
		if (cp[0] == '#' && cp[1] == '!')
			cp += 2;
#ifdef __OS2__
		else if (!strncmp(cp, Textproc, 7) &&
		    (cp[7] == ' ' || cp[7] == '\t'))
			cp += 8;
#endif
		else
			goto noshebang;
		/* skip whitespace before shell name */
		while (*cp == ' ' || *cp == '\t')
			++cp;
		/* just whitespace on the line? */
		if (*cp == '\0')
			goto noshebang;
		/* no, we actually found an interpreter name */
		sh = (char *)cp;
		/* look for end of shell/interpreter name */
		while (*cp != ' ' && *cp != '\t' && *cp != '\0')
			++cp;
		/* any arguments? */
		if (*cp) {
			*cp++ = '\0';
			/* skip spaces before arguments */
			while (*cp == ' ' || *cp == '\t')
				++cp;
			/* pass it all in ONE argument (historic reasons) */
			if (*cp)
				*tp->args-- = (char *)cp;
		}
		goto nomagic;
 noshebang:
		m = buf[0] << 8 | buf[1];
		if (m == 0x7F45 && buf[2] == 'L' && buf[3] == 'F')
			errorf("%s: not executable: %d-bit ELF file", tp->str,
			    32 * buf[4]);
		if ((m == /* OMAGIC */ 0407) ||
		    (m == /* NMAGIC */ 0410) ||
		    (m == /* ZMAGIC */ 0413) ||
		    (m == /* QMAGIC */ 0314) ||
		    (m == /* ECOFF_I386 */ 0x4C01) ||
		    (m == /* ECOFF_M68K */ 0x0150 || m == 0x5001) ||
		    (m == /* ECOFF_SH */   0x0500 || m == 0x0005) ||
		    (m == /* bzip */ 0x425A) || (m == /* "MZ" */ 0x4D5A) ||
		    (m == /* "NE" */ 0x4E45) || (m == /* "LX" */ 0x4C58) ||
		    (m == /* xz */ 0xFD37 && buf[2] == 'z' && buf[3] == 'X' &&
		    buf[4] == 'Z') || (m == /* 7zip */ 0x377A) ||
		    (m == /* gzip */ 0x1F8B) || (m == /* .Z */ 0x1F9D))
			errorf("%s: not executable: magic %04X", tp->str, m);
 nomagic:
		;
	}
#endif
	args.ro = tp->args;
	*args.ro = sh;

	cap.ro = ap;
	execve(args.rw[0], args.rw, cap.rw);

	/* report both the programme that was run and the bogus interpreter */
	errorf("%s: %s: %s", tp->str, sh, cstrerror(errno));
}
Пример #2
0
static void
chvt(const Getopt *go)
{
	const char *dv = go->optarg;
	char *cp = NULL;
	int fd;

	switch (*dv) {
	case '-':
		dv = "/dev/null";
		break;
	case '!':
		++dv;
		/* FALLTHROUGH */
	default: {
		struct stat sb;

		if (stat(dv, &sb)) {
			cp = shf_smprintf("/dev/ttyC%s", dv);
			dv = cp;
			if (stat(dv, &sb)) {
				memmove(cp + 1, cp, /* /dev/tty */ 8);
				dv = cp + 1;
				if (stat(dv, &sb)) {
					errorf("%s: %s: %s", "chvt",
					    "can't find tty", go->optarg);
				}
			}
		}
		if (!(sb.st_mode & S_IFCHR))
			errorf("%s: %s: %s", "chvt", "not a char device", dv);
#ifndef MKSH_DISABLE_REVOKE_WARNING
#if HAVE_REVOKE
		if (revoke(dv))
#endif
			warningf(false, "%s: %s %s", "chvt",
			    "new shell is potentially insecure, can't revoke",
			    dv);
#endif
	    }
	}
	if ((fd = binopen2(dv, O_RDWR)) < 0) {
		sleep(1);
		if ((fd = binopen2(dv, O_RDWR)) < 0) {
			errorf("%s: %s %s", "chvt", "can't open", dv);
		}
	}
	if (go->optarg[0] != '!') {
		switch (fork()) {
		case -1:
			errorf("%s: %s %s", "chvt", "fork", "failed");
		case 0:
			break;
		default:
			exit(0);
		}
	}
	if (setsid() == -1)
		errorf("%s: %s %s", "chvt", "setsid", "failed");
	if (go->optarg[0] != '-') {
		if (ioctl(fd, TIOCSCTTY, NULL) == -1)
			errorf("%s: %s %s", "chvt", "TIOCSCTTY", "failed");
		if (tcflush(fd, TCIOFLUSH))
			errorf("%s: %s %s", "chvt", "TCIOFLUSH", "failed");
	}
	ksh_dup2(fd, 0, false);
	ksh_dup2(fd, 1, false);
	ksh_dup2(fd, 2, false);
	if (fd > 2)
		close(fd);
	rndset((unsigned long)chvt_rndsetup(go, sizeof(Getopt)));
	chvt_reinit();
}
Пример #3
0
int
main(int argc, char **argv)
{
	const char *tmpdir;
	size_t tdlen;

	/* may not be a constant, thus initialising early */
	listf = stderr;

	now = time(NULL);

	/*
	 * Keep a reference to cwd, so we can always come back home.
	 */
	cwdfd = binopen2(BO_CLEXEC, ".", O_RDONLY);
	if (cwdfd < 0) {
		syswarn(1, errno, "Cannot open current working directory.");
		return(exit_val);
	}

	/*
	 * Where should we put temporary files?
	 */
	if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
		tmpdir = _PATH_TMP;
	tdlen = strlen(tmpdir);
	while (tdlen > 0 && tmpdir[tdlen - 1] == '/')
		tdlen--;
	tempfile = malloc(tdlen + 1 + sizeof(_TFILE_BASE));
	if (tempfile == NULL) {
		paxwarn(1, "%s for %s", "Out of memory",
		    "temp file name");
		return (exit_val);
	}
	if (tdlen)
		memcpy(tempfile, tmpdir, tdlen);
	tempbase = tempfile + tdlen;
	*tempbase++ = '/';

#if HAVE_SETPGENT
	/*
	 * keep passwd and group files open for faster lookups.
	 */
	setpassent(1);
	setgroupent(1);
#endif

	/*
	 * parse options, determine operational mode, general init
	 */
	options(argc, argv);
	if ((gen_init() < 0) || (tty_init() < 0))
		return(exit_val);

#if HAVE_PLEDGE
	/*
	 * pmode needs to restore setugid bits when extracting or copying,
	 * so can't pledge at all then.
	 */
	if (pmode == 0 || (act != EXTRACT && act != COPY)) {
		if (pledge("stdio rpath wpath cpath fattr dpath getpw proc exec tape",
		    NULL) == -1)
			err(1, "pledge");

		/* Copy mode, or no gzip -- don't need to fork/exec. */
		if (compress_program == NULL || act == COPY) {
			if (pledge("stdio rpath wpath cpath fattr dpath getpw tape",
			    NULL) == -1)
				err(1, "pledge");
		}
	}
#endif

	/* make list fd independent and line-buffered */
	if ((listfd = dup(fileno(listf))) < 0 ||
	    !(listf = fdopen(listfd, "wb"))) {
		syswarn(1, errno, "Cannot open list file descriptor");
		return (exit_val);
	}
	if (fcntl(listfd, F_SETFD, FD_CLOEXEC) == -1)
		syswarn(0, errno, "%s on list file descriptor",
		    "Failed to set the close-on-exec flag");
	setlinebuf(listf);

	/*
	 * select a primary operation mode
	 */
	switch (act) {
	case EXTRACT:
		extract();
		break;
	case ARCHIVE:
		archive();
		break;
	case APPND:
		if (compress_program != NULL)
			errx(1, "cannot compress while appending");
		append();
		break;
	case COPY:
		copy();
		break;
	default:
		/* for ar_io.c etc. */
		act = LIST;
		/* FALLTHROUGH */
	case LIST:
		list();
		break;
	}
	return(exit_val);
}