imgact_shell.c revision 40435
1885Swollman/* 2885Swollman * Copyright (c) 1993, David Greenman 3885Swollman * All rights reserved. 4885Swollman * 5885Swollman * Redistribution and use in source and binary forms, with or without 6885Swollman * modification, are permitted provided that the following conditions 7885Swollman * are met: 8885Swollman * 1. Redistributions of source code must retain the above copyright 9885Swollman * notice, this list of conditions and the following disclaimer. 10885Swollman * 2. Redistributions in binary form must reproduce the above copyright 11885Swollman * notice, this list of conditions and the following disclaimer in the 12885Swollman * documentation and/or other materials provided with the distribution. 13885Swollman * 14885Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15885Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16885Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1710625Sdg * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18885Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19885Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20885Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21885Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22885Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23885Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24885Swollman * SUCH DAMAGE. 25885Swollman * 2640435Speter * $Id: imgact_shell.c,v 1.16 1997/08/02 14:31:23 bde Exp $ 27885Swollman */ 28885Swollman 292056Swollman#include <sys/param.h> 3040435Speter#include <sys/systm.h> 3111332Sswallace#include <sys/sysproto.h> 321549Srgrimes#include <sys/exec.h> 332056Swollman#include <sys/imgact.h> 342056Swollman#include <sys/kernel.h> 35885Swollman 36886Swollman#if BYTE_ORDER == LITTLE_ENDIAN 37885Swollman#define SHELLMAGIC 0x2123 /* #! */ 38886Swollman#else 39886Swollman#define SHELLMAGIC 0x2321 40886Swollman#endif 41886Swollman 42885Swollman#define MAXSHELLCMDLEN 64 43885Swollman 4412568Sbdestatic int exec_shell_imgact __P((struct image_params *imgp)); 4512568Sbde 46885Swollman/* 47885Swollman * Shell interpreter image activator. A interpreter name beginning 4812130Sdg * at imgp->stringbase is the minimal successful exit requirement. 49885Swollman */ 5012568Sbdestatic int 5112130Sdgexec_shell_imgact(imgp) 5212130Sdg struct image_params *imgp; 53885Swollman{ 5412130Sdg const char *image_header = imgp->image_header; 55885Swollman const char *ihp, *line_endp; 56885Swollman char *interp; 57885Swollman 58885Swollman /* a shell script? */ 5917974Sbde if (((const short *) image_header)[0] != SHELLMAGIC) 60885Swollman return(-1); 61885Swollman 62885Swollman /* 63885Swollman * Don't allow a shell script to be the shell for a shell 64885Swollman * script. :-) 65885Swollman */ 6612130Sdg if (imgp->interpreted) 67885Swollman return(ENOEXEC); 68885Swollman 6912130Sdg imgp->interpreted = 1; 70885Swollman 71885Swollman /* 72885Swollman * Copy shell name and arguments from image_header into string 73885Swollman * buffer. 74885Swollman */ 75885Swollman 76885Swollman /* 77885Swollman * Find end of line; return if the line > MAXSHELLCMDLEN long. 78885Swollman */ 79885Swollman for (ihp = &image_header[2]; *ihp != '\n'; ++ihp) { 80885Swollman if (ihp >= &image_header[MAXSHELLCMDLEN]) 81885Swollman return(ENOEXEC); 82885Swollman } 83885Swollman line_endp = ihp; 84885Swollman 85885Swollman /* reset for another pass */ 86885Swollman ihp = &image_header[2]; 87885Swollman 88885Swollman /* Skip over leading spaces - until the interpreter name */ 89885Swollman while ((*ihp == ' ') || (*ihp == '\t')) ihp++; 90885Swollman 91885Swollman /* copy the interpreter name */ 9212130Sdg interp = imgp->interpreter_name; 93885Swollman while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t')) 94885Swollman *interp++ = *ihp++; 95885Swollman *interp = '\0'; 96885Swollman 97885Swollman /* Disallow a null interpreter filename */ 9812130Sdg if (*imgp->interpreter_name == '\0') 99885Swollman return(ENOEXEC); 100885Swollman 101885Swollman /* reset for another pass */ 102885Swollman ihp = &image_header[2]; 103885Swollman 104885Swollman /* copy the interpreter name and arguments */ 105885Swollman while (ihp < line_endp) { 106885Swollman /* Skip over leading spaces */ 107885Swollman while ((*ihp == ' ') || (*ihp == '\t')) ihp++; 108885Swollman 109885Swollman if (ihp < line_endp) { 110885Swollman /* 111885Swollman * Copy to end of token. No need to watch stringspace 112885Swollman * because this is at the front of the string buffer 113885Swollman * and the maximum shell command length is tiny. 114885Swollman */ 115885Swollman while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t')) { 11612130Sdg *imgp->stringp++ = *ihp++; 11712130Sdg imgp->stringspace--; 118885Swollman } 119885Swollman 12012130Sdg *imgp->stringp++ = 0; 12112130Sdg imgp->stringspace--; 122885Swollman 12312130Sdg imgp->argc++; 124885Swollman } 125885Swollman } 126885Swollman 12725115Sache imgp->argv0 = imgp->uap->fname; 128885Swollman 129885Swollman return(0); 130885Swollman} 131886Swollman 132886Swollman/* 133886Swollman * Tell kern_execve.c about it, with a little help from the linker. 134886Swollman * Since `const' objects end up in the text segment, TEXT_SET is the 135886Swollman * correct directive to use. 136886Swollman */ 1372112Swollmanstatic const struct execsw shell_execsw = { exec_shell_imgact, "#!" }; 13840435SpeterEXEC_SET(shell, shell_execsw); 139