xref: /freebsd/sys/kern/imgact_shell.c (revision d323ddf3171ff6652c94cb9f79105f48f5ea8819)
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  *
26c3aac50fSPeter Wemm  * $FreeBSD$
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 /*
43cfefd687SGarrett Wollman  * Shell interpreter image activator. A interpreter name beginning
44c52007c2SDavid Greenman  *	at imgp->stringbase is the minimal successful exit requirement.
45cfefd687SGarrett Wollman  */
46d323ddf3SMatthew Dillon int
47c52007c2SDavid Greenman exec_shell_imgact(imgp)
48c52007c2SDavid Greenman 	struct image_params *imgp;
49cfefd687SGarrett Wollman {
50c52007c2SDavid Greenman 	const char *image_header = imgp->image_header;
51cfefd687SGarrett Wollman 	const char *ihp, *line_endp;
52cfefd687SGarrett Wollman 	char *interp;
53cfefd687SGarrett Wollman 
54cfefd687SGarrett Wollman 	/* a shell script? */
55e0c95ed9SBruce Evans 	if (((const short *) image_header)[0] != SHELLMAGIC)
56cfefd687SGarrett Wollman 		return(-1);
57cfefd687SGarrett Wollman 
58cfefd687SGarrett Wollman 	/*
59cfefd687SGarrett Wollman 	 * Don't allow a shell script to be the shell for a shell
60cfefd687SGarrett Wollman 	 *	script. :-)
61cfefd687SGarrett Wollman 	 */
62c52007c2SDavid Greenman 	if (imgp->interpreted)
63cfefd687SGarrett Wollman 		return(ENOEXEC);
64cfefd687SGarrett Wollman 
65c52007c2SDavid Greenman 	imgp->interpreted = 1;
66cfefd687SGarrett Wollman 
67cfefd687SGarrett Wollman 	/*
68cfefd687SGarrett Wollman 	 * Copy shell name and arguments from image_header into string
69cfefd687SGarrett Wollman 	 *	buffer.
70cfefd687SGarrett Wollman 	 */
71cfefd687SGarrett Wollman 
72cfefd687SGarrett Wollman 	/*
73cfefd687SGarrett Wollman 	 * Find end of line; return if the line > MAXSHELLCMDLEN long.
74cfefd687SGarrett Wollman 	 */
7530de91e8SMartin Cracauer 	for (ihp = &image_header[2]; *ihp != '\n' && *ihp != '#'; ++ihp) {
76cfefd687SGarrett Wollman 		if (ihp >= &image_header[MAXSHELLCMDLEN])
77cfefd687SGarrett Wollman 			return(ENOEXEC);
78cfefd687SGarrett Wollman 	}
79cfefd687SGarrett Wollman 	line_endp = ihp;
80cfefd687SGarrett Wollman 
81cfefd687SGarrett Wollman 	/* reset for another pass */
82cfefd687SGarrett Wollman 	ihp = &image_header[2];
83cfefd687SGarrett Wollman 
84cfefd687SGarrett Wollman 	/* Skip over leading spaces - until the interpreter name */
85cfefd687SGarrett Wollman 	while ((*ihp == ' ') || (*ihp == '\t')) ihp++;
86cfefd687SGarrett Wollman 
87cfefd687SGarrett Wollman 	/* copy the interpreter name */
88c52007c2SDavid Greenman 	interp = imgp->interpreter_name;
89cfefd687SGarrett Wollman 	while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t'))
90cfefd687SGarrett Wollman 		*interp++ = *ihp++;
91cfefd687SGarrett Wollman 	*interp = '\0';
92cfefd687SGarrett Wollman 
93cfefd687SGarrett Wollman 	/* Disallow a null interpreter filename */
94c52007c2SDavid Greenman 	if (*imgp->interpreter_name == '\0')
95cfefd687SGarrett Wollman 		return(ENOEXEC);
96cfefd687SGarrett Wollman 
97cfefd687SGarrett Wollman 	/* reset for another pass */
98cfefd687SGarrett Wollman 	ihp = &image_header[2];
99cfefd687SGarrett Wollman 
100cfefd687SGarrett Wollman 	/* copy the interpreter name and arguments */
101cfefd687SGarrett Wollman 	while (ihp < line_endp) {
102cfefd687SGarrett Wollman 		/* Skip over leading spaces */
103cfefd687SGarrett Wollman 		while ((*ihp == ' ') || (*ihp == '\t')) ihp++;
104cfefd687SGarrett Wollman 
105cfefd687SGarrett Wollman 		if (ihp < line_endp) {
106cfefd687SGarrett Wollman 			/*
107cfefd687SGarrett Wollman 			 * Copy to end of token. No need to watch stringspace
108cfefd687SGarrett Wollman 			 *	because this is at the front of the string buffer
109cfefd687SGarrett Wollman 			 *	and the maximum shell command length is tiny.
110cfefd687SGarrett Wollman 			 */
111cfefd687SGarrett Wollman 			while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t')) {
112c52007c2SDavid Greenman 				*imgp->stringp++ = *ihp++;
113c52007c2SDavid Greenman 				imgp->stringspace--;
114cfefd687SGarrett Wollman 			}
115cfefd687SGarrett Wollman 
116c52007c2SDavid Greenman 			*imgp->stringp++ = 0;
117c52007c2SDavid Greenman 			imgp->stringspace--;
118cfefd687SGarrett Wollman 
119c52007c2SDavid Greenman 			imgp->argc++;
120cfefd687SGarrett Wollman 		}
121cfefd687SGarrett Wollman 	}
122cfefd687SGarrett Wollman 
1235cf3d12cSAndrey A. Chernov 	imgp->argv0 = imgp->uap->fname;
124cfefd687SGarrett Wollman 
125cfefd687SGarrett Wollman 	return(0);
126cfefd687SGarrett Wollman }
12792d91f76SGarrett Wollman 
12892d91f76SGarrett Wollman /*
12992d91f76SGarrett Wollman  * Tell kern_execve.c about it, with a little help from the linker.
13092d91f76SGarrett Wollman  */
131820ca326SMatthew Dillon static struct execsw shell_execsw = { exec_shell_imgact, "#!" };
132aa855a59SPeter Wemm EXEC_SET(shell, shell_execsw);
133