xref: /freebsd/sys/kern/imgact_shell.c (revision aa855a598d9a933daa5facd559803ef280326028)
1cfefd687SGarrett Wollman /*
2cfefd687SGarrett Wollman  * Copyright (c) 1993, David Greenman
3cfefd687SGarrett Wollman  * All rights reserved.
4cfefd687SGarrett Wollman  *
5cfefd687SGarrett Wollman  * Redistribution and use in source and binary forms, with or without
6cfefd687SGarrett Wollman  * modification, are permitted provided that the following conditions
7cfefd687SGarrett Wollman  * are met:
8cfefd687SGarrett Wollman  * 1. Redistributions of source code must retain the above copyright
9cfefd687SGarrett Wollman  *    notice, this list of conditions and the following disclaimer.
10cfefd687SGarrett Wollman  * 2. Redistributions in binary form must reproduce the above copyright
11cfefd687SGarrett Wollman  *    notice, this list of conditions and the following disclaimer in the
12cfefd687SGarrett Wollman  *    documentation and/or other materials provided with the distribution.
13cfefd687SGarrett Wollman  *
14cfefd687SGarrett Wollman  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15cfefd687SGarrett Wollman  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16cfefd687SGarrett Wollman  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171984b014SDavid Greenman  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18cfefd687SGarrett Wollman  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19cfefd687SGarrett Wollman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20cfefd687SGarrett Wollman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21cfefd687SGarrett Wollman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22cfefd687SGarrett Wollman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23cfefd687SGarrett Wollman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24cfefd687SGarrett Wollman  * SUCH DAMAGE.
25cfefd687SGarrett Wollman  *
26aa855a59SPeter Wemm  *	$Id: imgact_shell.c,v 1.16 1997/08/02 14:31:23 bde Exp $
27cfefd687SGarrett Wollman  */
28cfefd687SGarrett Wollman 
29f540b106SGarrett Wollman #include <sys/param.h>
30aa855a59SPeter Wemm #include <sys/systm.h>
31ad7507e2SSteven Wallace #include <sys/sysproto.h>
3226f9a767SRodney W. Grimes #include <sys/exec.h>
33f540b106SGarrett Wollman #include <sys/imgact.h>
34f540b106SGarrett Wollman #include <sys/kernel.h>
35cfefd687SGarrett Wollman 
3692d91f76SGarrett Wollman #if BYTE_ORDER == LITTLE_ENDIAN
37cfefd687SGarrett Wollman #define SHELLMAGIC	0x2123 /* #! */
3892d91f76SGarrett Wollman #else
3992d91f76SGarrett Wollman #define SHELLMAGIC	0x2321
4092d91f76SGarrett Wollman #endif
4192d91f76SGarrett Wollman 
42cfefd687SGarrett Wollman #define MAXSHELLCMDLEN	64
43cfefd687SGarrett Wollman 
447ee050b7SBruce Evans static int	exec_shell_imgact __P((struct image_params *imgp));
457ee050b7SBruce Evans 
46cfefd687SGarrett Wollman /*
47cfefd687SGarrett Wollman  * Shell interpreter image activator. A interpreter name beginning
48c52007c2SDavid Greenman  *	at imgp->stringbase is the minimal successful exit requirement.
49cfefd687SGarrett Wollman  */
507ee050b7SBruce Evans static int
51c52007c2SDavid Greenman exec_shell_imgact(imgp)
52c52007c2SDavid Greenman 	struct image_params *imgp;
53cfefd687SGarrett Wollman {
54c52007c2SDavid Greenman 	const char *image_header = imgp->image_header;
55cfefd687SGarrett Wollman 	const char *ihp, *line_endp;
56cfefd687SGarrett Wollman 	char *interp;
57cfefd687SGarrett Wollman 
58cfefd687SGarrett Wollman 	/* a shell script? */
59e0c95ed9SBruce Evans 	if (((const short *) image_header)[0] != SHELLMAGIC)
60cfefd687SGarrett Wollman 		return(-1);
61cfefd687SGarrett Wollman 
62cfefd687SGarrett Wollman 	/*
63cfefd687SGarrett Wollman 	 * Don't allow a shell script to be the shell for a shell
64cfefd687SGarrett Wollman 	 *	script. :-)
65cfefd687SGarrett Wollman 	 */
66c52007c2SDavid Greenman 	if (imgp->interpreted)
67cfefd687SGarrett Wollman 		return(ENOEXEC);
68cfefd687SGarrett Wollman 
69c52007c2SDavid Greenman 	imgp->interpreted = 1;
70cfefd687SGarrett Wollman 
71cfefd687SGarrett Wollman 	/*
72cfefd687SGarrett Wollman 	 * Copy shell name and arguments from image_header into string
73cfefd687SGarrett Wollman 	 *	buffer.
74cfefd687SGarrett Wollman 	 */
75cfefd687SGarrett Wollman 
76cfefd687SGarrett Wollman 	/*
77cfefd687SGarrett Wollman 	 * Find end of line; return if the line > MAXSHELLCMDLEN long.
78cfefd687SGarrett Wollman 	 */
79cfefd687SGarrett Wollman 	for (ihp = &image_header[2]; *ihp != '\n'; ++ihp) {
80cfefd687SGarrett Wollman 		if (ihp >= &image_header[MAXSHELLCMDLEN])
81cfefd687SGarrett Wollman 			return(ENOEXEC);
82cfefd687SGarrett Wollman 	}
83cfefd687SGarrett Wollman 	line_endp = ihp;
84cfefd687SGarrett Wollman 
85cfefd687SGarrett Wollman 	/* reset for another pass */
86cfefd687SGarrett Wollman 	ihp = &image_header[2];
87cfefd687SGarrett Wollman 
88cfefd687SGarrett Wollman 	/* Skip over leading spaces - until the interpreter name */
89cfefd687SGarrett Wollman 	while ((*ihp == ' ') || (*ihp == '\t')) ihp++;
90cfefd687SGarrett Wollman 
91cfefd687SGarrett Wollman 	/* copy the interpreter name */
92c52007c2SDavid Greenman 	interp = imgp->interpreter_name;
93cfefd687SGarrett Wollman 	while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t'))
94cfefd687SGarrett Wollman 		*interp++ = *ihp++;
95cfefd687SGarrett Wollman 	*interp = '\0';
96cfefd687SGarrett Wollman 
97cfefd687SGarrett Wollman 	/* Disallow a null interpreter filename */
98c52007c2SDavid Greenman 	if (*imgp->interpreter_name == '\0')
99cfefd687SGarrett Wollman 		return(ENOEXEC);
100cfefd687SGarrett Wollman 
101cfefd687SGarrett Wollman 	/* reset for another pass */
102cfefd687SGarrett Wollman 	ihp = &image_header[2];
103cfefd687SGarrett Wollman 
104cfefd687SGarrett Wollman 	/* copy the interpreter name and arguments */
105cfefd687SGarrett Wollman 	while (ihp < line_endp) {
106cfefd687SGarrett Wollman 		/* Skip over leading spaces */
107cfefd687SGarrett Wollman 		while ((*ihp == ' ') || (*ihp == '\t')) ihp++;
108cfefd687SGarrett Wollman 
109cfefd687SGarrett Wollman 		if (ihp < line_endp) {
110cfefd687SGarrett Wollman 			/*
111cfefd687SGarrett Wollman 			 * Copy to end of token. No need to watch stringspace
112cfefd687SGarrett Wollman 			 *	because this is at the front of the string buffer
113cfefd687SGarrett Wollman 			 *	and the maximum shell command length is tiny.
114cfefd687SGarrett Wollman 			 */
115cfefd687SGarrett Wollman 			while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t')) {
116c52007c2SDavid Greenman 				*imgp->stringp++ = *ihp++;
117c52007c2SDavid Greenman 				imgp->stringspace--;
118cfefd687SGarrett Wollman 			}
119cfefd687SGarrett Wollman 
120c52007c2SDavid Greenman 			*imgp->stringp++ = 0;
121c52007c2SDavid Greenman 			imgp->stringspace--;
122cfefd687SGarrett Wollman 
123c52007c2SDavid Greenman 			imgp->argc++;
124cfefd687SGarrett Wollman 		}
125cfefd687SGarrett Wollman 	}
126cfefd687SGarrett Wollman 
1275cf3d12cSAndrey A. Chernov 	imgp->argv0 = imgp->uap->fname;
128cfefd687SGarrett Wollman 
129cfefd687SGarrett Wollman 	return(0);
130cfefd687SGarrett Wollman }
13192d91f76SGarrett Wollman 
13292d91f76SGarrett Wollman /*
13392d91f76SGarrett Wollman  * Tell kern_execve.c about it, with a little help from the linker.
13492d91f76SGarrett Wollman  * Since `const' objects end up in the text segment, TEXT_SET is the
13592d91f76SGarrett Wollman  * correct directive to use.
13692d91f76SGarrett Wollman  */
137f23b4c91SGarrett Wollman static const struct execsw shell_execsw = { exec_shell_imgact, "#!" };
138aa855a59SPeter Wemm EXEC_SET(shell, shell_execsw);
139