2015-10-09 18:11:19 +02:00
/* $OpenBSD: main.c,v 1.57 2015/09/10 22:48:58 nicm Exp $ */
2014-09-12 22:23:33 +02:00
/* $OpenBSD: tty.c,v 1.10 2014/08/10 02:44:26 guenther Exp $ */
2015-10-09 18:11:19 +02:00
/* $OpenBSD: io.c,v 1.26 2015/09/11 08:00:27 guenther Exp $ */
2015-09-05 21:19:12 +02:00
/* $OpenBSD: table.c,v 1.16 2015/09/01 13:12:31 tedu Exp $ */
2005-05-23 05:06:10 +02:00
2009-05-16 18:59:42 +02:00
/*-
2012-01-29 02:41:15 +01:00
* Copyright ( c ) 2003 , 2004 , 2005 , 2006 , 2007 , 2008 , 2009 , 2010 ,
2017-03-11 23:58:51 +01:00
* 2011 , 2012 , 2013 , 2014 , 2015 , 2016 , 2017
2015-10-05 19:59:00 +02:00
* mirabilos < m @ mirbsd . org >
2009-05-16 18:59:42 +02:00
*
* Provided that these terms and disclaimer and all copyright notices
* are retained or reproduced in an accompanying document , permission
* is granted to deal in this work without restriction , including un -
* limited rights to use , publicly perform , distribute , sell , modify ,
* merge , give away , or sublicence .
*
* This work is provided " AS IS " and WITHOUT WARRANTY of any kind , to
* the utmost extent permitted by applicable law , neither express nor
* implied ; without malicious intent or gross negligence . In no event
* may a licensor , author or contributor be held liable for indirect ,
* direct , other damage , loss , or other issues arising in any way out
* of dealing in the work , even if advised of the possibility of such
* damage or existence of a defect , except proven that it results out
* of said person ' s immediate fault when using the work as intended .
*/
2011-08-27 19:30:07 +02:00
# define EXTERN
2005-05-23 05:06:10 +02:00
# include "sh.h"
2006-11-09 00:45:47 +01:00
# if HAVE_LANGINFO_CODESET
2006-11-05 13:11:14 +01:00
# include <langinfo.h>
2006-11-09 00:45:47 +01:00
# endif
# if HAVE_SETLOCALE_CTYPE
2006-11-05 13:11:14 +01:00
# include <locale.h>
# endif
2017-04-22 02:07:10 +02:00
__RCSID ( " $MirOS: src/bin/mksh/main.c,v 1.334 2017/04/22 00:07:08 tg Exp $ " ) ;
2005-05-23 05:06:10 +02:00
extern char * * environ ;
2010-03-27 21:36:26 +01:00
# ifndef MKSHRC_PATH
# define MKSHRC_PATH "~ / .mkshrc"
# endif
2010-04-20 19:28:20 +02:00
# ifndef MKSH_DEFAULT_TMPDIR
2015-07-10 21:36:38 +02:00
# define MKSH_DEFAULT_TMPDIR MKSH_UNIXROOT " / tmp"
2010-04-20 19:28:20 +02:00
# endif
2012-04-06 14:59:28 +02:00
static uint8_t isuc ( const char * ) ;
2012-01-29 02:41:15 +01:00
static int main_init ( int , const char * [ ] , Source * * , struct block * * ) ;
2011-01-21 22:04:48 +01:00
void chvt_reinit ( void ) ;
2008-12-13 18:02:18 +01:00
static void reclaim ( void ) ;
2006-08-23 00:49:38 +02:00
static void remove_temps ( struct temp * ) ;
2011-01-21 22:04:48 +01:00
static mksh_uari_t rndsetup ( void ) ;
2010-07-04 19:45:17 +02:00
# ifdef SIGWINCH
static void x_sigwinch ( int ) ;
# endif
2005-05-23 05:06:10 +02:00
2009-09-26 05:40:03 +02:00
static const char initsubs [ ] =
2016-10-27 00:55:51 +02:00
" ${PS2=> } "
" ${PS3=#? } "
" ${PS4=+ } "
" ${SECONDS=0} "
" ${TMOUT=0} "
" ${EPOCHREALTIME=} " ;
2005-05-23 05:06:10 +02:00
2005-06-09 00:22:24 +02:00
static const char * initcoms [ ] = {
2011-09-07 17:24:22 +02:00
Ttypeset , " -r " , initvsn , NULL ,
2016-07-25 02:04:48 +02:00
Ttypeset , " -x " , " HOME " , TPATH , TSHELL , NULL ,
2012-11-30 20:25:08 +01:00
Ttypeset , " -i10 " , " COLUMNS " , " LINES " , " SECONDS " , " TMOUT " , NULL ,
2011-09-07 17:24:22 +02:00
Talias ,
2017-03-19 21:36:08 +01:00
" integer= \\ \\ builtin typeset -i " ,
" local= \\ \\ builtin typeset " ,
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* not "alias -t --": hash -r needs to work */
2017-03-19 21:36:08 +01:00
" hash= \\ \\ builtin alias -t " ,
" type= \\ \\ builtin whence -v " ,
" autoload= \\ \\ builtin typeset -fu " ,
" functions= \\ \\ builtin typeset -f " ,
" history= \\ \\ builtin fc -l " ,
" nameref= \\ \\ builtin typeset -n " ,
2005-06-09 00:22:24 +02:00
" nohup=nohup " ,
2017-03-19 21:36:08 +01:00
" r= \\ \\ builtin fc -e - " ,
" login= \\ \\ builtin exec login " ,
2005-06-09 00:22:24 +02:00
NULL ,
2009-06-11 14:42:21 +02:00
/* this is what AT&T ksh seems to track, with the addition of emacs */
2011-09-07 17:24:22 +02:00
Talias , " -tU " ,
2015-07-06 19:48:37 +02:00
Tcat , " cc " , " chmod " , " cp " , " date " , " ed " , " emacs " , " grep " , " ls " ,
2016-07-25 02:04:48 +02:00
" make " , " mv " , " pr " , " rm " , " sed " , Tsh , " vi " , " who " , NULL ,
2005-05-23 05:06:10 +02:00
NULL
} ;
2011-07-02 19:57:41 +02:00
static const char * restr_com [ ] = {
2016-07-25 02:04:48 +02:00
Ttypeset , " -r " , TPATH , " ENV " , TSHELL , NULL
2011-07-02 19:57:41 +02:00
} ;
2012-03-23 19:58:15 +01:00
static bool initio_done ;
2005-05-23 05:06:10 +02:00
2011-01-21 22:04:48 +01:00
/* top-level parsing and execution environment */
static struct env env ;
struct env * e = & env ;
2017-04-12 18:01:45 +02:00
/* compile-time assertions */
# define cta(name, expr) struct cta_ ## name { char t[(expr) ? 1 : -1]; }
/* this one should be defined by the standard */
cta ( char_is_1_char , ( sizeof ( char ) = = 1 ) & & ( sizeof ( signed char ) = = 1 ) & &
( sizeof ( unsigned char ) = = 1 ) ) ;
cta ( char_is_8_bits , ( ( CHAR_BIT ) = = 8 ) & & ( ( int ) ( unsigned char ) 0xFF = = 0xFF ) & &
( ( int ) ( unsigned char ) 0x100 = = 0 ) & & ( ( int ) ( unsigned char ) ( int ) - 1 = = 0xFF ) ) ;
/* the next assertion is probably not really needed */
cta ( short_is_2_char , sizeof ( short ) = = 2 ) ;
cta ( short_size_no_matter_of_signedness , sizeof ( short ) = = sizeof ( unsigned short ) ) ;
/* the next assertion is probably not really needed */
cta ( int_is_4_char , sizeof ( int ) = = 4 ) ;
cta ( int_size_no_matter_of_signedness , sizeof ( int ) = = sizeof ( unsigned int ) ) ;
cta ( long_ge_int , sizeof ( long ) > = sizeof ( int ) ) ;
cta ( long_size_no_matter_of_signedness , sizeof ( long ) = = sizeof ( unsigned long ) ) ;
# ifndef MKSH_LEGACY_MODE
/* the next assertion is probably not really needed */
cta ( ari_is_4_char , sizeof ( mksh_ari_t ) = = 4 ) ;
/* but this is */
cta ( ari_has_31_bit , 0 < ( mksh_ari_t ) ( ( ( ( ( mksh_ari_t ) 1 < < 15 ) < < 15 ) - 1 ) * 2 + 1 ) ) ;
/* the next assertion is probably not really needed */
cta ( uari_is_4_char , sizeof ( mksh_uari_t ) = = 4 ) ;
/* but the next three are; we REQUIRE unsigned integer wraparound */
cta ( uari_has_31_bit , 0 < ( mksh_uari_t ) ( ( ( ( ( mksh_uari_t ) 1 < < 15 ) < < 15 ) - 1 ) * 2 + 1 ) ) ;
cta ( uari_has_32_bit , 0 < ( mksh_uari_t ) ( ( ( ( ( mksh_uari_t ) 1 < < 15 ) < < 15 ) - 1 ) * 4 + 3 ) ) ;
cta ( uari_wrap_32_bit ,
( mksh_uari_t ) ( ( ( ( ( mksh_uari_t ) 1 < < 15 ) < < 15 ) - 1 ) * 4 + 3 ) >
( mksh_uari_t ) ( ( ( ( ( mksh_uari_t ) 1 < < 15 ) < < 15 ) - 1 ) * 4 + 4 ) ) ;
# endif
/* these are always required */
cta ( ari_is_signed , ( mksh_ari_t ) - 1 < ( mksh_ari_t ) 0 ) ;
cta ( uari_is_unsigned , ( mksh_uari_t ) - 1 > ( mksh_uari_t ) 0 ) ;
/* we require these to have the precisely same size and assume 2s complement */
cta ( ari_size_no_matter_of_signedness , sizeof ( mksh_ari_t ) = = sizeof ( mksh_uari_t ) ) ;
cta ( sizet_size_no_matter_of_signedness , sizeof ( ssize_t ) = = sizeof ( size_t ) ) ;
cta ( sizet_voidptr_same_size , sizeof ( size_t ) = = sizeof ( void * ) ) ;
cta ( sizet_funcptr_same_size , sizeof ( size_t ) = = sizeof ( void ( * ) ( void ) ) ) ;
/* our formatting routines assume this */
cta ( ptr_fits_in_long , sizeof ( size_t ) < = sizeof ( long ) ) ;
cta ( ari_fits_in_long , sizeof ( mksh_ari_t ) < = sizeof ( long ) ) ;
2011-01-21 22:04:48 +01:00
static mksh_uari_t
rndsetup ( void )
{
register uint32_t h ;
struct {
2011-09-07 17:24:22 +02:00
ALLOC_ITEM alloc_INT ;
2011-01-21 22:04:48 +01:00
void * dataptr , * stkptr , * mallocptr ;
2012-03-31 19:08:52 +02:00
# if defined(__GLIBC__) && (__GLIBC__ >= 2)
2011-01-21 22:04:48 +01:00
sigjmp_buf jbuf ;
2012-03-31 19:08:52 +02:00
# endif
2011-01-21 22:04:48 +01:00
struct timeval tv ;
} * bufptr ;
char * cp ;
2016-02-26 22:53:37 +01:00
cp = alloc ( sizeof ( * bufptr ) - sizeof ( ALLOC_ITEM ) , APERM ) ;
2016-10-23 01:56:50 +02:00
/* clear the allocated space, for valgrind and to avoid UB */
2016-02-26 22:53:37 +01:00
memset ( cp , 0 , sizeof ( * bufptr ) - sizeof ( ALLOC_ITEM ) ) ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* undo what alloc() did to the malloc result address */
2016-02-26 22:53:37 +01:00
bufptr = ( void * ) ( cp - sizeof ( ALLOC_ITEM ) ) ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* PIE or something similar provides us with deltas here */
bufptr - > dataptr = & rndsetupstate ;
/* ASLR in at least Windows, Linux, some BSDs */
bufptr - > stkptr = & bufptr ;
/* randomised malloc in BSD (and possibly others) */
bufptr - > mallocptr = bufptr ;
2012-03-31 19:08:52 +02:00
# if defined(__GLIBC__) && (__GLIBC__ >= 2)
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* glibc pointer guard */
sigsetjmp ( bufptr - > jbuf , 1 ) ;
2012-03-31 19:08:52 +02:00
# endif
2012-03-24 23:11:41 +01:00
/* introduce variation (and yes, second arg MBZ for portability) */
2012-05-04 23:47:04 +02:00
mksh_TIME ( bufptr - > tv ) ;
2011-01-21 22:04:48 +01:00
2016-02-24 02:44:46 +01:00
# ifdef MKSH_ALLOC_CATCH_UNDERRUNS
mprotect ( ( ( char * ) bufptr ) + 4096 , 4096 , PROT_READ | PROT_WRITE ) ;
# endif
2013-06-04 00:28:06 +02:00
h = chvt_rndsetup ( bufptr , sizeof ( * bufptr ) ) ;
afree ( cp , APERM ) ;
return ( ( mksh_uari_t ) h ) ;
}
2009-10-30 15:37:43 +01:00
void
chvt_reinit ( void )
{
kshpid = procpid = getpid ( ) ;
ksheuid = geteuid ( ) ;
kshpgrp = getpgrp ( ) ;
kshppid = getppid ( ) ;
}
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
static const char * empty_argv [ ] = {
2016-07-25 02:04:48 +02:00
Tmksh , NULL
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
} ;
2012-04-06 14:59:28 +02:00
static uint8_t
isuc ( const char * cx ) {
char * cp , * x ;
uint8_t rv = 0 ;
if ( ! cx | | ! * cx )
return ( 0 ) ;
/* uppercase a string duplicate */
strdupx ( x , cx , ATEMP ) ;
cp = x ;
while ( ( * cp = ksh_toupper ( * cp ) ) )
+ + cp ;
/* check for UTF-8 */
if ( strstr ( x , " UTF-8 " ) | | strstr ( x , " UTF8 " ) )
rv = 1 ;
/* free copy and out */
afree ( x , ATEMP ) ;
return ( rv ) ;
}
2012-01-29 02:41:15 +01:00
static int
main_init ( int argc , const char * argv [ ] , Source * * sp , struct block * * lp )
2005-05-23 05:06:10 +02:00
{
2007-07-17 15:56:51 +02:00
int argi , i ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
Source * s = NULL ;
2005-05-23 05:06:10 +02:00
struct block * l ;
2014-10-02 15:55:16 +02:00
unsigned char restricted_shell , errexit , utf_flag ;
2011-03-26 20:43:49 +01:00
char * cp ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
const char * ccp , * * wp ;
2005-07-04 14:47:13 +02:00
struct tbl * vp ;
struct stat s_stdin ;
2006-11-09 23:08:08 +01:00
# if !defined(_PATH_DEFPATH) && defined(_CS_PATH)
2010-09-14 23:26:19 +02:00
ssize_t k ;
2006-11-09 23:08:08 +01:00
# endif
2005-05-23 05:06:10 +02:00
2015-07-09 22:52:43 +02:00
# ifdef __OS2__
for ( i = 0 ; i < 3 ; + + i )
if ( ! isatty ( i ) )
setmode ( i , O_BINARY ) ;
2016-12-14 03:05:50 +01:00
os2_init ( & argc , & argv ) ;
2015-07-09 22:52:43 +02:00
# endif
2009-10-30 15:37:43 +01:00
/* do things like getpgrp() et al. */
chvt_reinit ( ) ;
2008-11-12 05:55:19 +01:00
2015-09-05 21:19:12 +02:00
/* make sure argv[] is sane, for weird OSes */
2005-05-23 05:06:10 +02:00
if ( ! * argv ) {
2006-11-12 15:58:16 +01:00
argv = empty_argv ;
2005-05-23 05:06:10 +02:00
argc = 1 ;
}
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
kshname = argv [ 0 ] ;
2005-05-23 05:06:10 +02:00
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* initialise permanent Area */
ainit ( & aperm ) ;
2016-02-26 19:48:14 +01:00
/* max. name length: -2147483648 = 11 (+ NUL) */
vtemp = alloc ( offsetof ( struct tbl , name [ 0 ] ) + 12 , APERM ) ;
2005-05-23 05:06:10 +02:00
/* set up base environment */
2011-01-21 22:04:48 +01:00
env . type = E_NONE ;
ainit ( & env . area ) ;
/* set up global l->vars and l->funs */
newblock ( ) ;
2005-05-23 05:06:10 +02:00
/* Do this first so output routines (eg, errorf, shellf) can work */
initio ( ) ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* determine the basename (without '-' or path) of the executable */
ccp = kshname ;
2016-09-01 14:59:12 +02:00
goto begin_parsing_kshname ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
while ( ( i = ccp [ argi + + ] ) ) {
2016-11-12 00:31:39 +01:00
if ( mksh_cdirsep ( i ) ) {
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
ccp + = argi ;
2016-09-01 14:59:12 +02:00
begin_parsing_kshname :
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
argi = 0 ;
if ( * ccp = = ' - ' )
+ + ccp ;
}
}
if ( ! * ccp )
ccp = empty_argv [ 0 ] ;
2014-01-16 14:54:45 +01:00
/*
* Turn on nohup by default . ( AT & T ksh does not have a nohup
* option - it always sends the hup ) .
*/
Flag ( FNOHUP ) = 1 ;
/*
* Turn on brace expansion by default . AT & T kshs that have
* alternation always have it on .
*/
Flag ( FBRACEEXPAND ) = 1 ;
/*
* Turn on " set -x " inheritance by default .
*/
Flag ( FXTRACEREC ) = 1 ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* define built-in commands and see if we were called as one */
2011-06-05 21:58:21 +02:00
ktinit ( APERM , & builtins ,
2017-03-19 21:59:29 +01:00
/* currently up to 54 builtins: 75% of 128 = 2^7 */
2012-07-01 17:38:09 +02:00
7 ) ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
for ( i = 0 ; mkshbuiltins [ i ] . name ! = NULL ; i + + )
if ( ! strcmp ( ccp , builtin ( mkshbuiltins [ i ] . name ,
mkshbuiltins [ i ] . func ) ) )
Flag ( FAS_BUILTIN ) = 1 ;
if ( ! Flag ( FAS_BUILTIN ) ) {
/* check for -T option early */
argi = parse_args ( argv , OF_FIRSTTIME , NULL ) ;
if ( argi < 0 )
return ( 1 ) ;
2013-05-02 22:21:45 +02:00
# if defined(MKSH_BINSHPOSIX) || defined(MKSH_BINSHREDUCED)
/* are we called as -sh or /bin/sh or so? */
2015-07-09 21:28:21 +02:00
if ( ! strcmp ( ccp , " sh " MKSH_EXE_EXT ) ) {
2013-05-02 22:21:45 +02:00
/* either also turns off braceexpand */
# ifdef MKSH_BINSHPOSIX
/* enable better POSIX conformance */
change_flag ( FPOSIX , OF_FIRSTTIME , true ) ;
# endif
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
# ifdef MKSH_BINSHREDUCED
2013-05-02 22:21:45 +02:00
/* enable kludge/compat mode */
2012-12-05 20:38:25 +01:00
change_flag ( FSH , OF_FIRSTTIME , true ) ;
2013-05-02 22:21:45 +02:00
# endif
}
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
# endif
}
2005-05-23 05:06:10 +02:00
initvar ( ) ;
2017-04-22 02:07:10 +02:00
/*XXX do this earlier, just call set_ifs(TC_IFSWS); with the new scheme, then ifs0 need not be E_INIT’ d, drop initctypes and setctypes from misc.c/sh.h then */
2005-05-23 05:06:10 +02:00
initctypes ( ) ;
inittraps ( ) ;
coproc_init ( ) ;
/* set up variable and command dictionaries */
2012-07-01 17:38:09 +02:00
ktinit ( APERM , & taliases , 0 ) ;
ktinit ( APERM , & aliases , 0 ) ;
2009-07-25 22:26:33 +02:00
# ifndef MKSH_NOPWNAM
2012-07-01 17:38:09 +02:00
ktinit ( APERM , & homedirs , 0 ) ;
2007-01-11 01:32:31 +01:00
# endif
2005-05-23 05:06:10 +02:00
/* define shell keywords */
initkeywords ( ) ;
init_histvec ( ) ;
2012-11-30 20:25:08 +01:00
/* initialise tty size before importing environment */
2012-03-23 22:58:24 +01:00
change_winsz ( ) ;
2006-11-09 23:08:08 +01:00
# ifdef _PATH_DEFPATH
2005-05-23 05:06:10 +02:00
def_path = _PATH_DEFPATH ;
2006-11-09 23:08:08 +01:00
# else
2006-08-24 22:32:53 +02:00
# ifdef _CS_PATH
2010-09-14 23:26:19 +02:00
if ( ( k = confstr ( _CS_PATH , NULL , 0 ) ) > 0 & &
2008-12-13 18:02:18 +01:00
confstr ( _CS_PATH , cp = alloc ( k + 1 , APERM ) , k + 1 ) = = k + 1 )
2007-01-12 03:06:34 +01:00
def_path = cp ;
2006-11-09 23:08:08 +01:00
else
# endif
2007-02-13 14:36:18 +01:00
/*
* this is uniform across all OSes unless it
2016-07-25 22:36:28 +02:00
* breaks somewhere hard ; don ' t try to optimise ,
2007-02-13 14:36:18 +01:00
* e . g . add stuff for Interix or remove / usr
* for HURD , because e . g . Debian GNU / HURD is
* " keeping a regular /usr " ; this is supposed
* to be a sane ' basic ' default PATH
*/
2015-07-10 21:36:38 +02:00
def_path = MKSH_UNIXROOT " /bin " MKSH_PATHSEPS
MKSH_UNIXROOT " /usr/bin " MKSH_PATHSEPS
MKSH_UNIXROOT " /sbin " MKSH_PATHSEPS
MKSH_UNIXROOT " /usr/sbin " ;
2005-06-24 17:36:57 +02:00
# endif
2005-05-23 05:06:10 +02:00
2011-01-21 22:04:48 +01:00
/*
* Set PATH to def_path ( will set the path global variable ) .
2005-05-23 05:06:10 +02:00
* ( import of environment below will probably change this setting ) .
*/
2016-07-25 02:04:48 +02:00
vp = global ( TPATH ) ;
2005-07-04 14:47:13 +02:00
/* setstr can't fail here */
setstr ( vp , def_path , KSH_RETURN_ERROR ) ;
2005-05-23 05:06:10 +02:00
2012-05-04 22:49:08 +02:00
# ifndef MKSH_NO_CMDLINE_EDITING
2011-01-21 22:04:48 +01:00
/*
* Set edit mode to emacs by default , may be overridden
2009-06-10 20:12:51 +02:00
* by the environment or the user . Also , we want tab completion
2011-01-21 22:04:48 +01:00
* on in vi by default .
*/
2012-12-05 20:38:25 +01:00
change_flag ( FEMACS , OF_SPECIAL , true ) ;
2009-09-24 19:15:33 +02:00
# if !MKSH_S_NOVI
2005-05-23 05:06:10 +02:00
Flag ( FVITABCOMPLETE ) = 1 ;
2012-05-04 22:49:08 +02:00
# endif
2007-06-15 23:55:20 +02:00
# endif
2005-05-23 05:06:10 +02:00
/* import environment */
2014-01-11 19:09:43 +01:00
if ( environ ! = NULL ) {
wp = ( const char * * ) environ ;
while ( * wp ! = NULL ) {
rndpush ( * wp ) ;
2005-06-09 00:22:24 +02:00
typeset ( * wp , IMPORT | EXPORT , 0 , 0 , 0 ) ;
2014-01-11 19:09:43 +01:00
+ + wp ;
}
}
2005-05-23 05:06:10 +02:00
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* for security */
2017-04-22 02:07:10 +02:00
typeset ( TinitIFS , 0 , 0 , 0 , 0 ) ;
2005-05-23 05:06:10 +02:00
/* assign default shell variable values */
2017-03-19 23:31:29 +01:00
typeset ( " PATHSEP= " MKSH_PATHSEPS , 0 , 0 , 0 , 0 ) ;
2005-05-23 05:06:10 +02:00
substitute ( initsubs , 0 ) ;
/* Figure out the current working directory and set $PWD */
2016-07-25 02:04:48 +02:00
vp = global ( TPWD ) ;
2011-03-26 20:43:49 +01:00
cp = str_val ( vp ) ;
/* Try to use existing $PWD if it is valid */
2016-07-25 02:04:48 +02:00
set_current_wd ( ( mksh_abspath ( cp ) & & test_eval ( NULL , TO_FILEQ , cp ,
Tdot , true ) ) ? cp : NULL ) ;
2011-03-26 20:43:49 +01:00
if ( current_wd [ 0 ] )
simplify_path ( current_wd ) ;
/* Only set pwd if we know where we are or if it had a bogus value */
if ( current_wd [ 0 ] | | * cp )
/* setstr can't fail here */
setstr ( vp , current_wd , KSH_RETURN_ERROR ) ;
2005-05-23 05:06:10 +02:00
2007-03-04 01:13:17 +01:00
for ( wp = initcoms ; * wp ! = NULL ; wp + + ) {
2017-03-12 00:22:36 +01:00
c_builtin ( wp ) ;
2007-06-15 22:52:19 +02:00
while ( * wp ! = NULL )
wp + + ;
2005-05-23 05:06:10 +02:00
}
2011-11-08 23:07:15 +01:00
setint_n ( global ( " OPTIND " ) , 1 , 10 ) ;
2005-05-23 05:06:10 +02:00
2011-01-21 22:04:48 +01:00
kshuid = getuid ( ) ;
kshgid = getgid ( ) ;
kshegid = getegid ( ) ;
2009-09-26 05:40:03 +02:00
safe_prompt = ksheuid ? " $ " : " # " ;
2005-07-04 14:47:13 +02:00
vp = global ( " PS1 " ) ;
/* Set PS1 if unset or we are root and prompt doesn't contain a # */
if ( ! ( vp - > flag & ISSET ) | |
( ! ksheuid & & ! strchr ( str_val ( vp ) , ' # ' ) ) )
/* setstr can't fail here */
setstr ( vp , safe_prompt , KSH_RETURN_ERROR ) ;
2012-11-20 18:42:32 +01:00
setint_n ( ( vp = global ( " BASHPID " ) ) , 0 , 10 ) ;
vp - > flag | = INT_U ;
2011-11-08 23:07:15 +01:00
setint_n ( ( vp = global ( " PGRP " ) ) , ( mksh_uari_t ) kshpgrp , 10 ) ;
2009-09-26 05:40:03 +02:00
vp - > flag | = INT_U ;
2011-11-08 23:07:15 +01:00
setint_n ( ( vp = global ( " PPID " ) ) , ( mksh_uari_t ) kshppid , 10 ) ;
2009-10-17 23:16:05 +02:00
vp - > flag | = INT_U ;
2011-11-08 23:07:15 +01:00
setint_n ( ( vp = global ( " USER_ID " ) ) , ( mksh_uari_t ) ksheuid , 10 ) ;
2009-09-26 05:40:03 +02:00
vp - > flag | = INT_U ;
2011-11-08 23:07:15 +01:00
setint_n ( ( vp = global ( " KSHUID " ) ) , ( mksh_uari_t ) kshuid , 10 ) ;
2011-01-21 22:04:48 +01:00
vp - > flag | = INT_U ;
2011-11-08 23:07:15 +01:00
setint_n ( ( vp = global ( " KSHEGID " ) ) , ( mksh_uari_t ) kshegid , 10 ) ;
2011-01-21 22:04:48 +01:00
vp - > flag | = INT_U ;
2011-11-08 23:07:15 +01:00
setint_n ( ( vp = global ( " KSHGID " ) ) , ( mksh_uari_t ) kshgid , 10 ) ;
2011-01-21 22:04:48 +01:00
vp - > flag | = INT_U ;
2011-11-08 23:07:15 +01:00
setint_n ( ( vp = global ( " RANDOM " ) ) , rndsetup ( ) , 10 ) ;
2011-01-21 22:04:48 +01:00
vp - > flag | = INT_U ;
2011-11-08 23:07:15 +01:00
setint_n ( ( vp_pipest = global ( " PIPESTATUS " ) ) , 0 , 10 ) ;
2005-05-23 05:06:10 +02:00
/* Set this before parsing arguments */
2015-10-05 19:59:00 +02:00
Flag ( FPRIVILEGED ) = ( kshuid ! = ksheuid | | kshgid ! = kshegid ) ? 2 : 0 ;
2005-05-23 05:06:10 +02:00
/* this to note if monitor is set on command line (see below) */
2009-09-20 18:40:58 +02:00
# ifndef MKSH_UNEMPLOYED
2005-05-23 05:06:10 +02:00
Flag ( FMONITOR ) = 127 ;
2009-09-20 18:40:58 +02:00
# endif
2009-11-28 16:38:30 +01:00
/* this to note if utf-8 mode is set on command line (see below) */
UTFMODE = 2 ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
if ( ! Flag ( FAS_BUILTIN ) ) {
argi = parse_args ( argv , OF_CMDLINE , NULL ) ;
if ( argi < 0 )
return ( 1 ) ;
}
2009-11-28 16:38:30 +01:00
/* process this later only, default to off (hysterical raisins) */
utf_flag = UTFMODE ;
UTFMODE = 0 ;
2005-05-23 05:06:10 +02:00
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
if ( Flag ( FAS_BUILTIN ) ) {
/* auto-detect from environment variables, always */
utf_flag = 3 ;
} else if ( Flag ( FCOMMAND ) ) {
2012-06-28 22:05:11 +02:00
s = pushs ( SSTRINGCMDLINE , ATEMP ) ;
2005-05-23 05:06:10 +02:00
if ( ! ( s - > start = s - > str = argv [ argi + + ] ) )
2016-07-25 02:04:48 +02:00
errorf ( Tf_optfoo , " " , " " , ' c ' , Treq_arg ) ;
2012-10-21 23:26:41 +02:00
while ( * s - > str ) {
if ( * s - > str ! = ' ' & & ctype ( * s - > str , C_QUOTE ) )
break ;
s - > str + + ;
}
if ( ! * s - > str )
s - > flags | = SF_MAYEXEC ;
s - > str = s - > start ;
2009-05-16 20:40:09 +02:00
# ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT
2010-01-28 16:18:51 +01:00
/* compatibility to MidnightBSD 0.1 /bin/sh (kludge) */
2009-10-02 20:08:37 +02:00
if ( Flag ( FSH ) & & argv [ argi ] & & ! strcmp ( argv [ argi ] , " -- " ) )
2009-04-05 13:44:56 +02:00
+ + argi ;
# endif
2005-05-23 05:06:10 +02:00
if ( argv [ argi ] )
kshname = argv [ argi + + ] ;
} else if ( argi < argc & & ! Flag ( FSTDIN ) ) {
s = pushs ( SFILE , ATEMP ) ;
2015-07-09 21:46:43 +02:00
# ifdef __OS2__
/*
* A bug in OS / 2 extproc ( like shebang ) handling makes
* it not pass the full pathname of a script , so we need
* to search for it . This changes the behaviour of a
* simple " mksh foo " , but can ' t be helped .
*/
2017-01-11 04:46:36 +01:00
s - > file = argv [ argi + + ] ;
if ( search_access ( s - > file , X_OK ) ! = 0 )
s - > file = search_path ( s - > file , path , X_OK , NULL ) ;
2015-07-09 21:46:43 +02:00
if ( ! s - > file | | ! * s - > file )
s - > file = argv [ argi - 1 ] ;
# else
2009-09-29 14:28:13 +02:00
s - > file = argv [ argi + + ] ;
2015-07-09 21:46:43 +02:00
# endif
2005-06-09 00:22:24 +02:00
s - > u . shf = shf_open ( s - > file , O_RDONLY , 0 ,
SHF_MAPHI | SHF_CLEXEC ) ;
2005-05-23 05:06:10 +02:00
if ( s - > u . shf = = NULL ) {
2010-08-28 17:39:20 +02:00
shl_stdout_ok = false ;
2016-07-25 02:04:48 +02:00
warningf ( true , Tf_sD_s , s - > file , cstrerror ( errno ) ) ;
2009-09-29 14:28:13 +02:00
/* mandated by SUSv4 */
exstat = 127 ;
unwind ( LERROR ) ;
2005-05-23 05:06:10 +02:00
}
2009-09-29 14:28:13 +02:00
kshname = s - > file ;
2005-05-23 05:06:10 +02:00
} else {
Flag ( FSTDIN ) = 1 ;
s = pushs ( SSTDIN , ATEMP ) ;
s - > file = " <stdin> " ;
s - > u . shf = shf_fdopen ( 0 , SHF_RD | can_seek ( 0 ) ,
NULL ) ;
if ( isatty ( 0 ) & & isatty ( 2 ) ) {
Flag ( FTALKING ) = Flag ( FTALKING_I ) = 1 ;
/* The following only if isatty(0) */
s - > flags | = SF_TTY ;
s - > u . shf - > flags | = SHF_INTERRUPT ;
s - > file = NULL ;
}
}
2009-10-02 20:08:37 +02:00
/* this bizarreness is mandated by POSIX */
2005-07-04 14:47:13 +02:00
if ( fstat ( 0 , & s_stdin ) > = 0 & & S_ISCHR ( s_stdin . st_mode ) & &
Flag ( FTALKING ) )
reset_nonblock ( 0 ) ;
2005-05-23 05:06:10 +02:00
2007-01-12 11:18:22 +01:00
/* initialise job control */
2009-04-05 14:35:32 +02:00
j_init ( ) ;
2012-11-30 20:25:08 +01:00
/* do this after j_init() which calls tty_init_state() */
2006-11-12 11:44:42 +01:00
if ( Flag ( FTALKING ) ) {
2009-11-28 16:38:30 +01:00
if ( utf_flag = = 2 ) {
2007-02-10 22:59:15 +01:00
# ifndef MKSH_ASSUME_UTF8
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* auto-detect from locale or environment */
utf_flag = 4 ;
2014-01-05 22:57:29 +01:00
# else /* this may not be an #elif */
# if MKSH_ASSUME_UTF8
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
utf_flag = 1 ;
2009-06-08 00:28:05 +02:00
# else
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* always disable UTF-8 (for interactive) */
utf_flag = 0 ;
2014-01-05 22:57:29 +01:00
# endif
2006-11-12 11:44:42 +01:00
# endif
2009-11-28 16:38:30 +01:00
}
2012-05-04 22:49:08 +02:00
# ifndef MKSH_NO_CMDLINE_EDITING
2005-05-23 05:06:10 +02:00
x_init ( ) ;
2012-05-04 22:49:08 +02:00
# endif
2006-11-12 11:44:42 +01:00
}
2005-05-23 05:06:10 +02:00
2010-07-04 19:45:17 +02:00
# ifdef SIGWINCH
sigtraps [ SIGWINCH ] . flags | = TF_SHELL_USES ;
setsig ( & sigtraps [ SIGWINCH ] , x_sigwinch ,
SS_RESTORE_ORIG | SS_FORCE | SS_SHTRAP ) ;
# endif
2005-05-23 05:06:10 +02:00
l = e - > loc ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
if ( Flag ( FAS_BUILTIN ) ) {
l - > argc = argc ;
l - > argv = argv ;
l - > argv [ 0 ] = ccp ;
} else {
l - > argc = argc - argi ;
2012-09-07 23:02:43 +02:00
/*
* allocate a new array because otherwise , when we modify
* it in - place , ps ( 1 ) output changes ; the meaning of argc
* here is slightly different as it excludes kshname , and
* we add a trailing NULL sentinel as well
*/
l - > argv = alloc2 ( l - > argc + 2 , sizeof ( void * ) , APERM ) ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
l - > argv [ 0 ] = kshname ;
2012-09-07 23:02:43 +02:00
memcpy ( & l - > argv [ 1 ] , & argv [ argi ] , l - > argc * sizeof ( void * ) ) ;
l - > argv [ l - > argc + 1 ] = NULL ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
getopts_reset ( 1 ) ;
}
/* divine the initial state of the utf8-mode Flag */
ccp = null ;
switch ( utf_flag ) {
/* auto-detect from locale or environment */
case 4 :
# if HAVE_SETLOCALE_CTYPE
ccp = setlocale ( LC_CTYPE , " " ) ;
# if HAVE_LANGINFO_CODESET
if ( ! isuc ( ccp ) )
ccp = nl_langinfo ( CODESET ) ;
# endif
if ( ! isuc ( ccp ) )
ccp = null ;
# endif
2016-11-12 00:48:30 +01:00
/* FALLTHROUGH */
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* auto-detect from environment */
case 3 :
/* these were imported from environ earlier */
if ( ccp = = null )
ccp = str_val ( global ( " LC_ALL " ) ) ;
if ( ccp = = null )
ccp = str_val ( global ( " LC_CTYPE " ) ) ;
if ( ccp = = null )
ccp = str_val ( global ( " LANG " ) ) ;
UTFMODE = isuc ( ccp ) ;
break ;
/* not set on command line, not FTALKING */
case 2 :
/* unknown values */
default :
utf_flag = 0 ;
/* FALLTHROUGH */
/* known values */
case 1 :
case 0 :
UTFMODE = utf_flag ;
break ;
}
2005-05-23 05:06:10 +02:00
/* Disable during .profile/ENV reading */
2014-10-02 15:55:16 +02:00
restricted_shell = Flag ( FRESTRICTED ) ;
2005-05-23 05:06:10 +02:00
Flag ( FRESTRICTED ) = 0 ;
errexit = Flag ( FERREXIT ) ;
Flag ( FERREXIT ) = 0 ;
2011-01-21 22:04:48 +01:00
/*
* Do this before profile / $ ENV so that if it causes problems in them ,
2005-05-23 05:06:10 +02:00
* user will know why things broke .
*/
if ( ! current_wd [ 0 ] & & Flag ( FTALKING ) )
2010-08-28 22:22:24 +02:00
warningf ( false , " can't determine current directory " ) ;
2005-05-23 05:06:10 +02:00
2014-06-09 14:28:19 +02:00
if ( Flag ( FLOGIN ) )
2012-10-30 21:13:20 +01:00
include ( MKSH_SYSTEM_PROFILE , 0 , NULL , true ) ;
2014-06-09 14:28:19 +02:00
if ( ! Flag ( FPRIVILEGED ) ) {
if ( Flag ( FLOGIN ) )
include ( substitute ( " $HOME/.profile " , 0 ) , 0 , NULL , true ) ;
if ( Flag ( FTALKING ) ) {
cp = substitute ( substitute ( " ${ENV:- " MKSHRC_PATH " } " ,
0 ) , DOTILDE ) ;
if ( cp [ 0 ] ! = ' \0 ' )
include ( cp , 0 , NULL , true ) ;
}
} else {
2012-10-30 21:13:20 +01:00
include ( MKSH_SUID_PROFILE , 0 , NULL , true ) ;
2014-06-09 14:28:19 +02:00
/* turn off -p if not set explicitly */
if ( Flag ( FPRIVILEGED ) ! = 1 )
change_flag ( FPRIVILEGED , OF_INTERNAL , false ) ;
2005-05-23 05:06:10 +02:00
}
2014-10-02 15:55:16 +02:00
if ( restricted_shell ) {
2017-03-12 00:22:36 +01:00
c_builtin ( restr_com ) ;
2005-05-23 05:06:10 +02:00
/* After typeset command... */
Flag ( FRESTRICTED ) = 1 ;
}
2009-08-08 15:08:53 +02:00
Flag ( FERREXIT ) = errexit ;
2005-05-23 05:06:10 +02:00
2012-06-24 22:15:47 +02:00
if ( Flag ( FTALKING ) & & s )
2005-05-23 05:06:10 +02:00
hist_init ( s ) ;
2011-04-17 14:24:44 +02:00
else
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* set after ENV */
Flag ( FTRACKALL ) = 1 ;
2011-04-17 14:24:44 +02:00
alarm_init ( ) ;
2012-01-29 02:41:15 +01:00
* sp = s ;
* lp = l ;
2011-01-21 22:04:48 +01:00
return ( 0 ) ;
2005-05-23 05:06:10 +02:00
}
2012-01-29 02:41:15 +01:00
/* this indirection barrier reduces stack usage during normal operation */
int
main ( int argc , const char * argv [ ] )
{
int rv ;
Source * s ;
struct block * l ;
if ( ( rv = main_init ( argc , argv , & s , & l ) ) = = 0 ) {
if ( Flag ( FAS_BUILTIN ) ) {
2017-03-12 00:22:36 +01:00
rv = c_builtin ( l - > argv ) ;
2012-01-29 02:41:15 +01:00
} else {
2017-04-08 03:07:18 +02:00
shell ( s , 0 ) ;
2012-01-29 02:41:15 +01:00
/* NOTREACHED */
}
}
return ( rv ) ;
}
2005-05-23 05:06:10 +02:00
int
2012-10-30 21:13:20 +01:00
include ( const char * name , int argc , const char * * argv , bool intr_ok )
2005-05-23 05:06:10 +02:00
{
Source * volatile s = NULL ;
struct shf * shf ;
2007-03-04 01:13:17 +01:00
const char * * volatile old_argv ;
2005-05-23 05:06:10 +02:00
volatile int old_argc ;
int i ;
2005-06-09 00:22:24 +02:00
shf = shf_open ( name , O_RDONLY , 0 , SHF_MAPHI | SHF_CLEXEC ) ;
2005-05-23 05:06:10 +02:00
if ( shf = = NULL )
2009-06-08 22:06:50 +02:00
return ( - 1 ) ;
2005-05-23 05:06:10 +02:00
if ( argv ) {
old_argv = e - > loc - > argv ;
old_argc = e - > loc - > argc ;
} else {
old_argv = NULL ;
old_argc = 0 ;
}
newenv ( E_INCL ) ;
2012-03-31 19:30:00 +02:00
if ( ( i = kshsetjmp ( e - > jbuf ) ) ) {
2005-05-23 05:06:10 +02:00
quitenv ( s ? s - > u . shf : NULL ) ;
if ( old_argv ) {
e - > loc - > argv = old_argv ;
e - > loc - > argc = old_argc ;
}
switch ( i ) {
case LRETURN :
case LERROR :
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* see below */
return ( exstat & 0xFF ) ;
2005-05-23 05:06:10 +02:00
case LINTR :
2011-01-21 22:04:48 +01:00
/*
* intr_ok is set if we are including . profile or $ ENV .
2005-05-23 05:06:10 +02:00
* If user ^ Cs out , we don ' t want to kill the shell . . .
*/
2012-10-21 23:39:06 +02:00
if ( intr_ok & & ( ( exstat & 0xFF ) - 128 ) ! = SIGTERM )
2009-06-08 22:06:50 +02:00
return ( 1 ) ;
2010-01-29 10:34:31 +01:00
/* FALLTHROUGH */
2005-05-23 05:06:10 +02:00
case LEXIT :
case LLEAVE :
case LSHELL :
unwind ( i ) ;
2005-06-09 00:34:03 +02:00
/* NOTREACHED */
2005-05-23 05:06:10 +02:00
default :
2017-04-08 03:07:18 +02:00
internal_errorf ( Tunexpected_type , Tunwind , Tsource , i ) ;
2005-06-09 00:34:03 +02:00
/* NOTREACHED */
2005-05-23 05:06:10 +02:00
}
}
if ( argv ) {
e - > loc - > argv = argv ;
e - > loc - > argc = argc ;
}
s = pushs ( SFILE , ATEMP ) ;
s - > u . shf = shf ;
2008-10-28 15:32:43 +01:00
strdupx ( s - > file , name , ATEMP ) ;
2017-04-08 03:07:18 +02:00
i = shell ( s , 1 ) ;
2005-05-23 05:06:10 +02:00
quitenv ( s - > u . shf ) ;
if ( old_argv ) {
e - > loc - > argv = old_argv ;
e - > loc - > argc = old_argc ;
}
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* & 0xff to ensure value not -1 */
return ( i & 0xFF ) ;
2005-05-23 05:06:10 +02:00
}
2010-05-22 14:49:16 +02:00
/* spawn a command into a shell optionally keeping track of the line number */
2005-05-23 05:06:10 +02:00
int
2010-05-22 14:49:16 +02:00
command ( const char * comm , int line )
2005-05-23 05:06:10 +02:00
{
2016-08-04 22:31:01 +02:00
Source * s , * sold = source ;
int rv ;
2005-05-23 05:06:10 +02:00
s = pushs ( SSTRING , ATEMP ) ;
s - > start = s - > str = comm ;
2010-05-22 14:49:16 +02:00
s - > line = line ;
2017-04-08 03:07:18 +02:00
rv = shell ( s , 1 ) ;
2016-08-04 22:31:01 +02:00
source = sold ;
return ( rv ) ;
2005-05-23 05:06:10 +02:00
}
/*
* run the commands from the input source , returning status .
*/
int
2017-04-08 03:07:18 +02:00
shell ( Source * volatile s , volatile int level )
2005-05-23 05:06:10 +02:00
{
struct op * t ;
2012-05-04 23:15:34 +02:00
volatile bool wastty = tobool ( s - > flags & SF_TTY ) ;
volatile uint8_t attempts = 13 ;
2017-04-08 03:07:18 +02:00
volatile bool interactive = ( level = = 0 ) & & Flag ( FTALKING ) ;
2011-03-13 17:03:54 +01:00
volatile bool sfirst = true ;
2005-05-23 05:06:10 +02:00
Source * volatile old_source = source ;
int i ;
2017-04-08 03:07:18 +02:00
newenv ( level = = 2 ? E_EVAL : E_PARSE ) ;
2005-05-23 05:06:10 +02:00
if ( interactive )
2012-05-04 23:15:34 +02:00
really_exit = false ;
2012-03-31 19:30:00 +02:00
switch ( ( i = kshsetjmp ( e - > jbuf ) ) ) {
case 0 :
break ;
2017-04-08 03:07:18 +02:00
case LBREAK :
case LCONTIN :
if ( level ! = 2 ) {
source = old_source ;
quitenv ( NULL ) ;
internal_errorf ( Tf_cant_s , Tshell ,
i = = LBREAK ? Tbreak : Tcontinue ) ;
/* NOTREACHED */
}
/* assert: interactive == false */
/* FALLTHROUGH */
2012-03-31 19:30:00 +02:00
case LINTR :
/* we get here if SIGINT not caught or ignored */
case LERROR :
case LSHELL :
if ( interactive ) {
if ( i = = LINTR )
shellf ( " \n " ) ;
/*
* Reset any eof that was read as part of a
* multiline command .
*/
if ( Flag ( FIGNOREEOF ) & & s - > type = = SEOF & & wastty )
s - > type = SSTDIN ;
/*
* Used by exit command to get back to
* top level shell . Kind of strange since
* interactive is set if we are reading from
* a tty , but to have stopped jobs , one only
* needs FMONITOR set ( not FTALKING / SF_TTY ) . . .
*/
/* toss any input we have so far */
2012-10-30 21:49:44 +01:00
yyrecursive_pop ( true ) ;
2012-03-31 19:30:00 +02:00
s - > start = s - > str = null ;
2012-10-30 21:49:44 +01:00
retrace_info = NULL ;
2012-10-30 21:07:00 +01:00
herep = heres ;
2012-03-31 19:30:00 +02:00
break ;
2005-05-23 05:06:10 +02:00
}
2012-03-31 19:30:00 +02:00
/* FALLTHROUGH */
case LEXIT :
case LLEAVE :
case LRETURN :
source = old_source ;
quitenv ( NULL ) ;
/* keep on going */
unwind ( i ) ;
/* NOTREACHED */
default :
source = old_source ;
quitenv ( NULL ) ;
2017-04-08 03:07:18 +02:00
internal_errorf ( Tunexpected_type , Tunwind , Tshell , i ) ;
2012-03-31 19:30:00 +02:00
/* NOTREACHED */
2005-05-23 05:06:10 +02:00
}
2011-03-13 02:20:25 +01:00
while ( /* CONSTCOND */ 1 ) {
2005-05-23 05:06:10 +02:00
if ( trap )
runtraps ( 0 ) ;
if ( s - > next = = NULL ) {
if ( Flag ( FVERBOSE ) )
s - > flags | = SF_ECHO ;
else
s - > flags & = ~ SF_ECHO ;
}
if ( interactive ) {
j_notify ( ) ;
set_prompt ( PS1 , s ) ;
}
2017-04-06 03:59:58 +02:00
t = compile ( s , sfirst , true ) ;
2015-07-05 21:37:18 +02:00
if ( interactive )
histsave ( & s - > line , NULL , HIST_FLUSH , true ) ;
2011-03-13 17:03:54 +01:00
sfirst = false ;
2012-10-21 23:26:41 +02:00
if ( ! t )
goto source_no_tree ;
if ( t - > type = = TEOF ) {
2005-05-23 05:06:10 +02:00
if ( wastty & & Flag ( FIGNOREEOF ) & & - - attempts > 0 ) {
2010-08-28 20:50:58 +02:00
shellf ( " Use 'exit' to leave mksh \n " ) ;
2005-05-23 05:06:10 +02:00
s - > type = SSTDIN ;
} else if ( wastty & & ! really_exit & &
j_stopped_running ( ) ) {
2012-05-04 23:15:34 +02:00
really_exit = true ;
2005-05-23 05:06:10 +02:00
s - > type = SSTDIN ;
} else {
2011-01-21 22:04:48 +01:00
/*
* this for POSIX which says EXIT traps
2005-05-23 05:06:10 +02:00
* shall be taken in the environment
* immediately after the last command
* executed .
*/
2017-04-08 03:07:18 +02:00
if ( level = = 0 )
2005-05-23 05:06:10 +02:00
unwind ( LEXIT ) ;
break ;
}
2014-01-11 17:26:28 +01:00
} else if ( ( s - > flags & SF_MAYEXEC ) & & t - > type = = TCOM )
2012-10-21 23:26:41 +02:00
t - > u . evalflags | = DOTCOMEXEC ;
if ( ! Flag ( FNOEXEC ) | | ( s - > flags & SF_TTY ) )
2012-10-21 23:39:06 +02:00
exstat = execute ( t , 0 , NULL ) & 0xFF ;
2005-05-23 05:06:10 +02:00
2012-10-21 23:26:41 +02:00
if ( t - > type ! = TEOF & & interactive & & really_exit )
2012-05-04 23:15:34 +02:00
really_exit = false ;
2005-05-23 05:06:10 +02:00
2012-10-21 23:26:41 +02:00
source_no_tree :
2008-12-13 18:02:18 +01:00
reclaim ( ) ;
2005-05-23 05:06:10 +02:00
}
quitenv ( NULL ) ;
source = old_source ;
2012-10-21 23:39:06 +02:00
return ( exstat & 0xFF ) ;
2005-05-23 05:06:10 +02:00
}
/* return to closest error handler or shell(), exit if none found */
2012-07-22 17:56:51 +02:00
/* note: i MUST NOT be 0 */
2005-05-23 05:06:10 +02:00
void
unwind ( int i )
{
2013-01-01 21:45:04 +01:00
/*
* This is a kludge . We need to restore everything that was
* changed in the new environment , see cid 1005090337 C7A669439
* and 10050903386452 ACBF1 , but fail to even save things most of
* the time . funcs . c : c_eval ( ) changes FERREXIT temporarily to 0 ,
* which needs to be restored thus ( related to Debian # 696823 ) .
* We did not save the shell flags , so we use a special or ' d
* value here . . . this is mostly to clean up behind * other *
* callers of unwind ( LERROR ) here ; exec . c has the regular case .
*/
if ( Flag ( FERREXIT ) & 0x80 ) {
/* GNU bash does not run this trapsig */
trapsig ( ksh_SIGERR ) ;
Flag ( FERREXIT ) & = ~ 0x80 ;
}
2013-01-01 23:23:16 +01:00
/* ordering for EXIT vs ERR is a bit odd (this is what AT&T ksh does) */
2013-07-25 20:07:47 +02:00
if ( i = = LEXIT | | ( ( i = = LERROR | | i = = LINTR ) & &
sigtraps [ ksh_SIGEXIT ] . trap & &
( ! Flag ( FTALKING ) | | Flag ( FERREXIT ) ) ) ) {
2013-01-01 23:23:16 +01:00
+ + trap_nested ;
runtrap ( & sigtraps [ ksh_SIGEXIT ] , trap_nested = = 1 ) ;
- - trap_nested ;
i = LLEAVE ;
} else if ( Flag ( FERREXIT ) = = 1 & & ( i = = LERROR | | i = = LINTR ) ) {
+ + trap_nested ;
runtrap ( & sigtraps [ ksh_SIGERR ] , trap_nested = = 1 ) ;
- - trap_nested ;
i = LLEAVE ;
}
2011-03-13 02:20:25 +01:00
while ( /* CONSTCOND */ 1 ) {
2005-05-23 05:06:10 +02:00
switch ( e - > type ) {
case E_PARSE :
case E_FUNC :
case E_INCL :
case E_LOOP :
case E_ERRH :
2017-04-08 03:07:18 +02:00
case E_EVAL :
2012-03-31 19:30:00 +02:00
kshlongjmp ( e - > jbuf , i ) ;
2005-06-09 00:34:03 +02:00
/* NOTREACHED */
2005-05-23 05:06:10 +02:00
case E_NONE :
if ( i = = LINTR )
e - > flags | = EF_FAKE_SIGDIE ;
2010-01-29 10:34:31 +01:00
/* FALLTHROUGH */
2005-05-23 05:06:10 +02:00
default :
quitenv ( NULL ) ;
}
}
}
void
newenv ( int type )
{
struct env * ep ;
2009-04-07 21:43:28 +02:00
char * cp ;
2005-05-23 05:06:10 +02:00
2009-04-07 21:43:28 +02:00
/*
* struct env includes ALLOC_ITEM for alignment constraints
* so first get the actually used memory , then assign it
*/
2016-02-26 22:53:37 +01:00
cp = alloc ( sizeof ( struct env ) - sizeof ( ALLOC_ITEM ) , ATEMP ) ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* undo what alloc() did to the malloc result address */
2016-02-26 22:53:37 +01:00
ep = ( void * ) ( cp - sizeof ( ALLOC_ITEM ) ) ;
2009-04-07 21:43:28 +02:00
/* initialise public members of struct env (not the ALLOC_ITEM) */
2008-12-13 18:02:18 +01:00
ainit ( & ep - > area ) ;
2009-04-07 21:43:28 +02:00
ep - > oenv = e ;
2005-05-23 05:06:10 +02:00
ep - > loc = e - > loc ;
ep - > savefd = NULL ;
ep - > temps = NULL ;
2012-10-30 21:07:15 +01:00
ep - > yyrecursive_statep = NULL ;
2009-04-07 21:43:28 +02:00
ep - > type = type ;
ep - > flags = 0 ;
/* jump buffer is invalid because flags == 0 */
2005-05-23 05:06:10 +02:00
e = ep ;
}
void
quitenv ( struct shf * shf )
{
struct env * ep = e ;
2009-04-07 21:43:28 +02:00
char * cp ;
2005-05-23 05:06:10 +02:00
int fd ;
2012-10-30 21:49:44 +01:00
yyrecursive_pop ( true ) ;
2013-02-10 20:05:37 +01:00
while ( ep - > oenv & & ep - > oenv - > loc ! = ep - > loc )
2005-05-23 05:06:10 +02:00
popblock ( ) ;
if ( ep - > savefd ! = NULL ) {
for ( fd = 0 ; fd < NUFILE ; fd + + )
/* if ep->savefd[fd] < 0, means fd was closed */
if ( ep - > savefd [ fd ] )
restfd ( fd , ep - > savefd [ fd ] ) ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
if ( ep - > savefd [ 2 ] )
/* Clear any write errors */
2005-05-23 05:06:10 +02:00
shf_reopen ( 2 , SHF_WR , shl_out ) ;
}
2011-01-21 22:04:48 +01:00
/*
* Bottom of the stack .
2005-05-23 05:06:10 +02:00
* Either main shell is exiting or cleanup_parents_env ( ) was called .
*/
if ( ep - > oenv = = NULL ) {
2013-02-10 22:42:16 +01:00
# ifdef DEBUG_LEAKS
int i ;
# endif
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
if ( ep - > type = = E_NONE ) {
/* Main shell exiting? */
2007-03-03 22:36:08 +01:00
# if HAVE_PERSISTENT_HISTORY
2005-05-23 05:06:10 +02:00
if ( Flag ( FTALKING ) )
hist_finish ( ) ;
2006-11-10 06:23:14 +01:00
# endif
2005-05-23 05:06:10 +02:00
j_exit ( ) ;
if ( ep - > flags & EF_FAKE_SIGDIE ) {
2012-10-21 23:39:06 +02:00
int sig = ( exstat & 0xFF ) - 128 ;
2005-05-23 05:06:10 +02:00
2011-01-21 22:04:48 +01:00
/*
* ham up our death a bit ( AT & T ksh
2005-05-23 05:06:10 +02:00
* only seems to do this for SIGTERM )
* Don ' t do it for SIGQUIT , since we ' d
* dump a core . .
*/
if ( ( sig = = SIGINT | | sig = = SIGTERM ) & &
2008-05-15 17:24:11 +02:00
( kshpgrp = = kshpid ) ) {
2005-05-23 05:06:10 +02:00
setsig ( & sigtraps [ sig ] , SIG_DFL ,
2005-06-09 00:22:24 +02:00
SS_RESTORE_CURR | SS_FORCE ) ;
2005-05-23 05:06:10 +02:00
kill ( 0 , sig ) ;
}
}
}
if ( shf )
shf_close ( shf ) ;
2008-12-13 18:02:18 +01:00
reclaim ( ) ;
2013-02-10 18:41:06 +01:00
# ifdef DEBUG_LEAKS
2013-02-10 18:38:15 +01:00
# ifndef MKSH_NO_CMDLINE_EDITING
2013-02-10 20:05:37 +01:00
x_done ( ) ;
2013-06-02 05:09:17 +02:00
# endif
# ifndef MKSH_NOPROSPECTOFWORK
/* block at least SIGCHLD during/after afreeall */
sigprocmask ( SIG_BLOCK , & sm_sigchld , NULL ) ;
2013-02-10 18:38:15 +01:00
# endif
2013-02-10 18:43:07 +01:00
afreeall ( APERM ) ;
2013-02-10 22:42:16 +01:00
for ( fd = 3 ; fd < NUFILE ; fd + + )
if ( ( i = fcntl ( fd , F_GETFD , 0 ) ) ! = - 1 & &
( i & FD_CLOEXEC ) )
close ( fd ) ;
2013-02-10 18:55:57 +01:00
close ( 2 ) ;
close ( 1 ) ;
close ( 0 ) ;
2013-02-10 18:38:15 +01:00
# endif
2012-10-21 23:39:06 +02:00
exit ( exstat & 0xFF ) ;
2005-05-23 05:06:10 +02:00
}
if ( shf )
shf_close ( shf ) ;
2008-12-13 18:02:18 +01:00
reclaim ( ) ;
2005-05-23 05:06:10 +02:00
e = e - > oenv ;
2009-04-07 21:43:28 +02:00
/* free the struct env - tricky due to the ALLOC_ITEM inside */
cp = ( void * ) ep ;
2016-02-26 22:53:37 +01:00
afree ( cp + sizeof ( ALLOC_ITEM ) , ATEMP ) ;
2005-05-23 05:06:10 +02:00
}
/* Called after a fork to cleanup stuff left over from parents environment */
void
cleanup_parents_env ( void )
{
struct env * ep ;
int fd ;
2009-12-05 18:43:50 +01:00
/*
* Don ' t clean up temporary files - parent will probably need them .
2005-05-23 05:06:10 +02:00
* Also , can ' t easily reclaim memory since variables , etc . could be
* anywhere .
*/
/* close all file descriptors hiding in savefd */
for ( ep = e ; ep ; ep = ep - > oenv ) {
if ( ep - > savefd ) {
for ( fd = 0 ; fd < NUFILE ; fd + + )
if ( ep - > savefd [ fd ] > 0 )
close ( ep - > savefd [ fd ] ) ;
2008-12-13 18:02:18 +01:00
afree ( ep - > savefd , & ep - > area ) ;
2005-05-23 05:06:10 +02:00
ep - > savefd = NULL ;
}
2013-02-10 22:17:07 +01:00
# ifdef DEBUG_LEAKS
if ( ep - > type ! = E_NONE )
ep - > type = E_GONE ;
# endif
2005-05-23 05:06:10 +02:00
}
2013-02-10 22:17:07 +01:00
# ifndef DEBUG_LEAKS
2005-05-23 05:06:10 +02:00
e - > oenv = NULL ;
2013-02-10 22:17:07 +01:00
# endif
2005-05-23 05:06:10 +02:00
}
/* Called just before an execve cleanup stuff temporary files */
void
cleanup_proc_env ( void )
{
struct env * ep ;
for ( ep = e ; ep ; ep = ep - > oenv )
remove_temps ( ep - > temps ) ;
}
/* remove temp files and free ATEMP Area */
static void
2008-12-13 18:02:18 +01:00
reclaim ( void )
2005-05-23 05:06:10 +02:00
{
2013-02-10 20:05:37 +01:00
struct block * l ;
while ( ( l = e - > loc ) & & ( ! e - > oenv | | e - > oenv - > loc ! = l ) ) {
e - > loc = l - > next ;
afreeall ( & l - > area ) ;
}
2005-05-23 05:06:10 +02:00
remove_temps ( e - > temps ) ;
e - > temps = NULL ;
2016-08-04 22:51:35 +02:00
/*
* if the memory backing source is reclaimed , things
* will end up badly when a function expecting it to
* be valid is run ; a NULL pointer is easily debugged
*/
if ( source & & source - > areap = = & e - > area )
source = NULL ;
2008-12-13 18:02:18 +01:00
afreeall ( & e - > area ) ;
2005-05-23 05:06:10 +02:00
}
static void
remove_temps ( struct temp * tp )
{
2016-08-04 22:32:14 +02:00
while ( tp ) {
2007-10-25 17:19:16 +02:00
if ( tp - > pid = = procpid )
2012-04-14 18:07:48 +02:00
unlink ( tp - > tffn ) ;
2016-08-04 22:32:14 +02:00
tp = tp - > next ;
}
2005-05-23 05:06:10 +02:00
}
2011-01-21 22:04:48 +01:00
/*
2012-11-30 20:25:08 +01:00
* Initialise tty_fd . Used for tracking the size of the terminal ,
* saving / resetting tty modes upon forground job completion , and
* for setting up the tty process group . Return values :
* 0 = got controlling tty
* 1 = got terminal but no controlling tty
* 2 = cannot find a terminal
* 3 = cannot dup fd
* 4 = cannot make fd close - on - exec
* An existing tty_fd is cached if no " better " one could be found ,
* i . e . if tty_devtty was already set or the new would not set it .
2005-05-23 05:06:10 +02:00
*/
2012-11-30 20:25:08 +01:00
int
tty_init_fd ( void )
2005-05-23 05:06:10 +02:00
{
2012-11-30 20:25:08 +01:00
int fd , rv , eno = 0 ;
bool do_close = false , is_devtty = true ;
2005-05-23 05:06:10 +02:00
2012-11-30 20:25:08 +01:00
if ( tty_devtty ) {
/* already got a tty which is /dev/tty */
return ( 0 ) ;
2005-05-23 05:06:10 +02:00
}
2007-07-01 21:04:53 +02:00
# ifdef _UWIN
2011-02-27 20:29:32 +01:00
/*XXX imake style */
if ( isatty ( 3 ) ) {
/* fd 3 on UWIN _is_ /dev/tty (or our controlling tty) */
2012-11-30 20:25:08 +01:00
fd = 3 ;
goto got_fd ;
2005-05-23 05:06:10 +02:00
}
2012-05-05 00:34:51 +02:00
# endif
2016-07-25 02:04:48 +02:00
if ( ( fd = open ( T_devtty , O_RDWR , 0 ) ) > = 0 ) {
2012-11-30 20:25:08 +01:00
do_close = true ;
goto got_fd ;
2005-05-23 05:06:10 +02:00
}
2012-11-30 20:25:08 +01:00
eno = errno ;
2005-05-23 05:06:10 +02:00
if ( tty_fd > = 0 ) {
2012-11-30 20:25:08 +01:00
/* already got a non-devtty one */
rv = 1 ;
goto out ;
2005-05-23 05:06:10 +02:00
}
2012-11-30 20:25:08 +01:00
is_devtty = false ;
if ( isatty ( ( fd = 0 ) ) | | isatty ( ( fd = 2 ) ) )
goto got_fd ;
/* cannot find one */
rv = 2 ;
/* assert: do_close == false */
goto out ;
got_fd :
if ( ( rv = fcntl ( fd , F_DUPFD , FDBASE ) ) < 0 ) {
eno = errno ;
rv = 3 ;
goto out ;
}
if ( fcntl ( rv , F_SETFD , FD_CLOEXEC ) < 0 ) {
eno = errno ;
close ( rv ) ;
rv = 4 ;
goto out ;
}
tty_fd = rv ;
tty_devtty = is_devtty ;
rv = eno = 0 ;
out :
if ( do_close )
close ( fd ) ;
errno = eno ;
return ( rv ) ;
2005-05-23 05:06:10 +02:00
}
/* A shell error occurred (eg, syntax error, etc.) */
2011-03-27 20:50:06 +02:00
# define VWARNINGF_ERRORPREFIX 1
# define VWARNINGF_FILELINE 2
# define VWARNINGF_BUILTIN 4
# define VWARNINGF_INTERNAL 8
2011-05-29 18:31:42 +02:00
static void vwarningf ( unsigned int , const char * , va_list )
MKSH_A_FORMAT ( __printf__ , 2 , 0 ) ;
static void
2011-03-27 20:50:06 +02:00
vwarningf ( unsigned int flags , const char * fmt , va_list ap )
{
2012-11-30 20:58:48 +01:00
if ( fmt ) {
2011-03-27 20:50:06 +02:00
if ( flags & VWARNINGF_INTERNAL )
2016-07-25 02:04:48 +02:00
shf_fprintf ( shl_out , Tf_sD_ , " internal error " ) ;
2011-03-27 20:50:06 +02:00
if ( flags & VWARNINGF_ERRORPREFIX )
error_prefix ( tobool ( flags & VWARNINGF_FILELINE ) ) ;
if ( ( flags & VWARNINGF_BUILTIN ) & &
/* not set when main() calls parse_args() */
builtin_argv0 & & builtin_argv0 ! = kshname )
2016-07-25 02:04:48 +02:00
shf_fprintf ( shl_out , Tf_sD_ , builtin_argv0 ) ;
2011-03-27 20:50:06 +02:00
shf_vfprintf ( shl_out , fmt , ap ) ;
shf_putchar ( ' \n ' , shl_out ) ;
}
shf_flush ( shl_out ) ;
}
2005-05-23 05:06:10 +02:00
void
2011-03-27 20:50:06 +02:00
errorfx ( int rc , const char * fmt , . . . )
2005-05-23 05:06:10 +02:00
{
va_list va ;
2011-03-27 20:50:06 +02:00
exstat = rc ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* debugging: note that stdout not valid */
shl_stdout_ok = false ;
2011-03-27 20:50:06 +02:00
va_start ( va , fmt ) ;
vwarningf ( VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE , fmt , va ) ;
va_end ( va ) ;
unwind ( LERROR ) ;
}
void
errorf ( const char * fmt , . . . )
{
va_list va ;
2005-05-23 05:06:10 +02:00
exstat = 1 ;
2011-03-27 20:50:06 +02:00
/* debugging: note that stdout not valid */
shl_stdout_ok = false ;
va_start ( va , fmt ) ;
vwarningf ( VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE , fmt , va ) ;
va_end ( va ) ;
2005-05-23 05:06:10 +02:00
unwind ( LERROR ) ;
}
/* like errorf(), but no unwind is done */
void
2006-11-10 02:13:52 +01:00
warningf ( bool fileline , const char * fmt , . . . )
2005-05-23 05:06:10 +02:00
{
va_list va ;
va_start ( va , fmt ) ;
2011-03-27 20:50:06 +02:00
vwarningf ( VWARNINGF_ERRORPREFIX | ( fileline ? VWARNINGF_FILELINE : 0 ) ,
fmt , va ) ;
2005-05-23 05:06:10 +02:00
va_end ( va ) ;
}
2011-01-21 22:04:48 +01:00
/*
* Used by built - in utilities to prefix shell and utility name to message
2005-05-23 05:06:10 +02:00
* ( also unwinds environments for special builtins ) .
*/
void
bi_errorf ( const char * fmt , . . . )
{
va_list va ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* debugging: note that stdout not valid */
shl_stdout_ok = false ;
2005-05-23 05:06:10 +02:00
exstat = 1 ;
2011-03-27 20:50:06 +02:00
va_start ( va , fmt ) ;
vwarningf ( VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE |
VWARNINGF_BUILTIN , fmt , va ) ;
va_end ( va ) ;
2017-03-11 23:58:51 +01:00
/* POSIX special builtins cause non-interactive shells to exit */
2014-10-12 23:58:53 +02:00
if ( builtin_spec ) {
2005-05-23 05:06:10 +02:00
builtin_argv0 = NULL ;
2017-03-11 23:58:51 +01:00
/* may not want to use LERROR here */
2005-05-23 05:06:10 +02:00
unwind ( LERROR ) ;
}
}
/* Called when something that shouldn't happen does */
void
2007-05-13 19:51:24 +02:00
internal_errorf ( const char * fmt , . . . )
2005-05-23 05:06:10 +02:00
{
va_list va ;
va_start ( va , fmt ) ;
2011-03-27 20:50:06 +02:00
vwarningf ( VWARNINGF_INTERNAL , fmt , va ) ;
2007-05-13 19:51:24 +02:00
va_end ( va ) ;
unwind ( LERROR ) ;
}
void
internal_warningf ( const char * fmt , . . . )
{
va_list va ;
va_start ( va , fmt ) ;
2011-03-27 20:50:06 +02:00
vwarningf ( VWARNINGF_INTERNAL , fmt , va ) ;
2005-05-23 05:06:10 +02:00
va_end ( va ) ;
}
/* used by error reporting functions to print "ksh: .kshrc[25]: " */
void
2006-11-10 02:13:52 +01:00
error_prefix ( bool fileline )
2005-05-23 05:06:10 +02:00
{
/* Avoid foo: foo[2]: ... */
if ( ! fileline | | ! source | | ! source - > file | |
strcmp ( source - > file , kshname ) ! = 0 )
2016-07-25 02:04:48 +02:00
shf_fprintf ( shl_out , Tf_sD_ , kshname + ( * kshname = = ' - ' ) ) ;
2005-05-23 05:06:10 +02:00
if ( fileline & & source & & source - > file ! = NULL ) {
2015-04-19 20:50:38 +02:00
shf_fprintf ( shl_out , " %s[%lu]: " , source - > file ,
( unsigned long ) ( source - > errline ?
source - > errline : source - > line ) ) ;
2005-05-23 05:06:10 +02:00
source - > errline = 0 ;
}
}
/* printf to shl_out (stderr) with flush */
void
shellf ( const char * fmt , . . . )
{
va_list va ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
if ( ! initio_done )
/* shl_out may not be set up yet... */
2005-05-23 05:06:10 +02:00
return ;
va_start ( va , fmt ) ;
shf_vfprintf ( shl_out , fmt , va ) ;
va_end ( va ) ;
shf_flush ( shl_out ) ;
}
/* printf to shl_stdout (stdout) */
void
shprintf ( const char * fmt , . . . )
{
va_list va ;
if ( ! shl_stdout_ok )
2007-05-13 19:51:24 +02:00
internal_errorf ( " shl_stdout not valid " ) ;
2005-05-23 05:06:10 +02:00
va_start ( va , fmt ) ;
shf_vfprintf ( shl_stdout , fmt , va ) ;
va_end ( va ) ;
}
/* test if we can seek backwards fd (returns 0 or SHF_UNBUF) */
int
can_seek ( int fd )
{
struct stat statb ;
2009-06-08 22:06:50 +02:00
return ( fstat ( fd , & statb ) = = 0 & & ! S_ISREG ( statb . st_mode ) ?
SHF_UNBUF : 0 ) ;
2005-05-23 05:06:10 +02:00
}
2012-03-23 20:38:12 +01:00
# ifdef DF
int shl_dbg_fd ;
# define NSHF_IOB 4
# else
# define NSHF_IOB 3
# endif
struct shf shf_iob [ NSHF_IOB ] ;
2005-05-23 05:06:10 +02:00
void
initio ( void )
{
2012-10-21 19:16:45 +02:00
# ifdef DF
const char * lfp ;
# endif
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/* force buffer allocation */
shf_fdopen ( 1 , SHF_WR , shl_stdout ) ;
2005-05-23 05:06:10 +02:00
shf_fdopen ( 2 , SHF_WR , shl_out ) ;
2013-07-21 20:47:24 +02:00
shf_fdopen ( 2 , SHF_WR , shl_xtrace ) ;
2012-03-23 20:38:12 +01:00
# ifdef DF
2013-01-06 19:44:07 +01:00
if ( ( lfp = getenv ( " SDMKSH_PATH " ) ) = = NULL ) {
2015-07-10 21:36:38 +02:00
if ( ( lfp = getenv ( " HOME " ) ) = = NULL | | ! mksh_abspath ( lfp ) )
2017-04-08 03:07:18 +02:00
errorf ( " can't get home directory " ) ;
2016-07-25 02:04:48 +02:00
lfp = shf_smprintf ( Tf_sSs , lfp , " mksh-dbg.txt " ) ;
2013-01-06 19:44:07 +01:00
}
2012-10-21 19:16:45 +02:00
2012-11-30 20:02:10 +01:00
if ( ( shl_dbg_fd = open ( lfp , O_WRONLY | O_APPEND | O_CREAT , 0600 ) ) < 0 )
2017-04-08 03:07:18 +02:00
errorf ( " can't open debug output file %s " , lfp ) ;
2012-03-23 20:38:12 +01:00
if ( shl_dbg_fd < FDBASE ) {
int nfd ;
nfd = fcntl ( shl_dbg_fd , F_DUPFD , FDBASE ) ;
close ( shl_dbg_fd ) ;
if ( ( shl_dbg_fd = nfd ) = = - 1 )
2017-04-08 03:07:18 +02:00
errorf ( " can't dup debug output file " ) ;
2012-03-23 20:38:12 +01:00
}
2012-10-21 19:16:45 +02:00
fcntl ( shl_dbg_fd , F_SETFD , FD_CLOEXEC ) ;
2012-03-23 20:38:12 +01:00
shf_fdopen ( shl_dbg_fd , SHF_WR , shl_dbg ) ;
DF ( " === open === " ) ;
# endif
2012-03-23 19:58:15 +01:00
initio_done = true ;
2005-05-23 05:06:10 +02:00
}
/* A dup2() with error checking */
int
2008-04-01 22:40:22 +02:00
ksh_dup2 ( int ofd , int nfd , bool errok )
2005-05-23 05:06:10 +02:00
{
2008-04-01 22:40:22 +02:00
int rv ;
2005-05-23 05:06:10 +02:00
2008-04-01 22:40:22 +02:00
if ( ( ( rv = dup2 ( ofd , nfd ) ) < 0 ) & & ! errok & & ( errno ! = EBADF ) )
2017-04-08 03:07:18 +02:00
errorf ( Ttoo_many_files ) ;
2005-05-23 05:06:10 +02:00
2008-04-01 22:40:22 +02:00
# ifdef __ultrix
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/*XXX imake style */
2008-04-01 22:40:22 +02:00
if ( rv > = 0 )
fcntl ( nfd , F_SETFD , 0 ) ;
# endif
return ( rv ) ;
2005-05-23 05:06:10 +02:00
}
/*
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
* Move fd from user space ( 0 < = fd < 10 ) to shell space ( fd > = 10 ) ,
* set close - on - exec flag . See FDBASE in sh . h , maybe 24 not 10 here .
2005-05-23 05:06:10 +02:00
*/
2007-06-07 01:28:17 +02:00
short
2006-05-10 20:54:13 +02:00
savefd ( int fd )
2005-05-23 05:06:10 +02:00
{
2007-06-07 01:28:17 +02:00
int nfd = fd ;
2005-05-23 05:06:10 +02:00
2007-06-07 01:28:17 +02:00
if ( fd < FDBASE & & ( nfd = fcntl ( fd , F_DUPFD , FDBASE ) ) < 0 & &
2015-07-09 21:19:10 +02:00
( errno = = EBADF | | errno = = EPERM ) )
2009-06-08 22:06:50 +02:00
return ( - 1 ) ;
2007-06-07 01:28:17 +02:00
if ( nfd < 0 | | nfd > SHRT_MAX )
2017-04-08 03:07:18 +02:00
errorf ( Ttoo_many_files ) ;
2005-05-23 05:06:10 +02:00
fcntl ( nfd , F_SETFD , FD_CLOEXEC ) ;
2007-06-07 01:28:17 +02:00
return ( ( short ) nfd ) ;
2005-05-23 05:06:10 +02:00
}
void
restfd ( int fd , int ofd )
{
if ( fd = = 2 )
2012-10-22 22:19:18 +02:00
shf_flush ( & shf_iob [ /* fd */ 2 ] ) ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
if ( ofd < 0 )
/* original fd closed */
2005-05-23 05:06:10 +02:00
close ( fd ) ;
else if ( fd ! = ofd ) {
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
/*XXX: what to do if this dup fails? */
ksh_dup2 ( ofd , fd , true ) ;
2005-05-23 05:06:10 +02:00
close ( ofd ) ;
}
}
void
openpipe ( int * pv )
{
2006-05-10 20:54:13 +02:00
int lpv [ 2 ] ;
if ( pipe ( lpv ) < 0 )
2005-05-23 05:06:10 +02:00
errorf ( " can't create pipe - try again " ) ;
2006-05-10 20:54:13 +02:00
pv [ 0 ] = savefd ( lpv [ 0 ] ) ;
if ( pv [ 0 ] ! = lpv [ 0 ] )
close ( lpv [ 0 ] ) ;
pv [ 1 ] = savefd ( lpv [ 1 ] ) ;
if ( pv [ 1 ] ! = lpv [ 1 ] )
close ( lpv [ 1 ] ) ;
2015-05-16 06:20:53 +02:00
# ifdef __OS2__
2016-12-17 09:04:37 +01:00
setmode ( pv [ 0 ] , O_BINARY ) ;
2015-05-16 06:20:53 +02:00
setmode ( pv [ 1 ] , O_BINARY ) ;
# endif
2005-05-23 05:06:10 +02:00
}
void
closepipe ( int * pv )
{
close ( pv [ 0 ] ) ;
close ( pv [ 1 ] ) ;
}
2011-01-21 22:04:48 +01:00
/*
* Called by iosetup ( ) ( deals with 2 > & 4 , etc . ) , c_read , c_print to turn
2005-05-23 05:06:10 +02:00
* a string ( the X in 2 > & X , read - uX , print - uX ) into a file descriptor .
*/
int
2007-03-04 01:13:17 +01:00
check_fd ( const char * name , int mode , const char * * emsgp )
2005-05-23 05:06:10 +02:00
{
2016-07-25 23:05:25 +02:00
int fd , fl ;
2005-05-23 05:06:10 +02:00
2016-07-25 23:05:25 +02:00
if ( ! name [ 0 ] | | name [ 1 ] )
goto illegal_fd_name ;
if ( name [ 0 ] = = ' p ' )
2008-07-09 23:32:45 +02:00
return ( coproc_getfd ( mode , emsgp ) ) ;
2016-07-25 23:05:25 +02:00
if ( ! ksh_isdigit ( name [ 0 ] ) ) {
illegal_fd_name :
2008-07-09 23:32:45 +02:00
if ( emsgp )
* emsgp = " illegal file descriptor name " ;
return ( - 1 ) ;
}
2016-07-25 23:05:25 +02:00
if ( ( fl = fcntl ( ( fd = ksh_numdig ( name [ 0 ] ) ) , F_GETFL , 0 ) ) < 0 ) {
2008-07-09 23:32:45 +02:00
if ( emsgp )
* emsgp = " bad file descriptor " ;
return ( - 1 ) ;
}
fl & = O_ACCMODE ;
2011-01-21 22:04:48 +01:00
/*
* X_OK is a kludge to disable this check for dups ( x < & 1 ) :
2008-07-09 23:32:45 +02:00
* historical shells never did this check ( XXX don ' t know what
2009-10-02 20:08:37 +02:00
* POSIX has to say ) .
2008-07-09 23:32:45 +02:00
*/
if ( ! ( mode & X_OK ) & & fl ! = O_RDWR & & (
( ( mode & R_OK ) & & fl ! = O_RDONLY ) | |
( ( mode & W_OK ) & & fl ! = O_WRONLY ) ) ) {
if ( emsgp )
* emsgp = ( fl = = O_WRONLY ) ?
" fd not open for reading " :
" fd not open for writing " ;
return ( - 1 ) ;
}
return ( fd ) ;
2005-05-23 05:06:10 +02:00
}
/* Called once from main */
void
coproc_init ( void )
{
coproc . read = coproc . readw = coproc . write = - 1 ;
coproc . njobs = 0 ;
coproc . id = 0 ;
}
/* Called by c_read() when eof is read - close fd if it is the co-process fd */
void
coproc_read_close ( int fd )
{
if ( coproc . read > = 0 & & fd = = coproc . read ) {
coproc_readw_close ( fd ) ;
close ( coproc . read ) ;
coproc . read = - 1 ;
}
}
2011-01-21 22:04:48 +01:00
/*
* Called by c_read ( ) and by iosetup ( ) to close the other side of the
2005-05-23 05:06:10 +02:00
* read pipe , so reads will actually terminate .
*/
void
coproc_readw_close ( int fd )
{
if ( coproc . readw > = 0 & & coproc . read > = 0 & & fd = = coproc . read ) {
close ( coproc . readw ) ;
coproc . readw = - 1 ;
}
}
2011-01-21 22:04:48 +01:00
/*
* Called by c_print when a write to a fd fails with EPIPE and by iosetup
2005-05-23 05:06:10 +02:00
* when co - process input is dup ' d
*/
void
coproc_write_close ( int fd )
{
if ( coproc . write > = 0 & & fd = = coproc . write ) {
close ( coproc . write ) ;
coproc . write = - 1 ;
}
}
2011-01-21 22:04:48 +01:00
/*
* Called to check for existence of / value of the co - process file descriptor .
2005-05-23 05:06:10 +02:00
* ( Used by check_fd ( ) and by c_read / c_print to deal with - p option ) .
*/
int
coproc_getfd ( int mode , const char * * emsgp )
{
int fd = ( mode & R_OK ) ? coproc . read : coproc . write ;
if ( fd > = 0 )
2009-06-08 22:06:50 +02:00
return ( fd ) ;
2005-05-23 05:06:10 +02:00
if ( emsgp )
* emsgp = " no coprocess " ;
2009-06-08 22:06:50 +02:00
return ( - 1 ) ;
2005-05-23 05:06:10 +02:00
}
2011-01-21 22:04:48 +01:00
/*
* called to close file descriptors related to the coprocess ( if any )
2005-05-23 05:06:10 +02:00
* Should be called with SIGCHLD blocked .
*/
void
coproc_cleanup ( int reuse )
{
/* This to allow co-processes to share output pipe */
if ( ! reuse | | coproc . readw < 0 | | coproc . read < 0 ) {
if ( coproc . read > = 0 ) {
close ( coproc . read ) ;
coproc . read = - 1 ;
}
if ( coproc . readw > = 0 ) {
close ( coproc . readw ) ;
coproc . readw = - 1 ;
}
}
if ( coproc . write > = 0 ) {
close ( coproc . write ) ;
coproc . write = - 1 ;
}
}
struct temp *
2008-12-13 18:02:18 +01:00
maketemp ( Area * ap , Temp_type type , struct temp * * tlist )
2005-05-23 05:06:10 +02:00
{
2012-04-14 18:07:48 +02:00
char * cp ;
2011-08-27 20:06:52 +02:00
size_t len ;
2013-03-29 18:33:07 +01:00
int i , j ;
2012-04-14 18:07:48 +02:00
struct temp * tp ;
2005-05-23 05:06:10 +02:00
const char * dir ;
2012-04-14 18:07:48 +02:00
struct stat sb ;
2005-05-23 05:06:10 +02:00
2010-04-20 19:28:20 +02:00
dir = tmpdir ? tmpdir : MKSH_DEFAULT_TMPDIR ;
2012-04-14 18:07:48 +02:00
/* add "/shXXXXXX.tmp" plus NUL */
len = strlen ( dir ) ;
checkoktoadd ( len , offsetof ( struct temp , tffn [ 0 ] ) + 14 ) ;
tp = alloc ( offsetof ( struct temp , tffn [ 0 ] ) + 14 + len , ap ) ;
2005-05-23 05:06:10 +02:00
tp - > shf = NULL ;
tp - > pid = procpid ;
2012-04-14 18:07:48 +02:00
tp - > type = type ;
if ( stat ( dir , & sb ) | | ! S_ISDIR ( sb . st_mode ) ) {
tp - > tffn [ 0 ] = ' \0 ' ;
goto maketemp_out ;
}
cp = ( void * ) tp ;
cp + = offsetof ( struct temp , tffn [ 0 ] ) ;
memcpy ( cp , dir , len ) ;
cp + = len ;
memcpy ( cp , " /shXXXXXX.tmp " , 14 ) ;
/* point to the first of six Xes */
cp + = 3 ;
/* cyclically attempt to open a temporary file */
2015-04-29 22:07:35 +02:00
do {
/* generate random part of filename */
len = 0 ;
do {
cp [ len + + ] = digits_lc [ rndget ( ) % 36 ] ;
} while ( len < 6 ) ;
/* check if this one works */
2015-07-09 22:52:43 +02:00
if ( ( i = binopen3 ( tp - > tffn , O_CREAT | O_EXCL | O_RDWR ,
2015-04-29 22:07:35 +02:00
0600 ) ) < 0 & & errno ! = EEXIST )
2012-04-14 18:07:48 +02:00
goto maketemp_out ;
2015-04-29 22:07:35 +02:00
} while ( i < 0 ) ;
2012-04-14 18:07:48 +02:00
2012-10-22 22:19:18 +02:00
if ( type = = TT_FUNSUB ) {
/* map us high and mark as close-on-exec */
2013-03-29 18:33:07 +01:00
if ( ( j = savefd ( i ) ) ! = i ) {
2012-10-22 22:19:18 +02:00
close ( i ) ;
2013-03-29 18:33:07 +01:00
i = j ;
2012-10-22 22:19:18 +02:00
}
2013-03-29 18:33:07 +01:00
/* operation mode for the shf */
j = SHF_RD ;
} else
j = SHF_WR ;
2012-10-22 22:19:18 +02:00
2012-04-14 18:07:48 +02:00
/* shf_fdopen cannot fail, so no fd leak */
2013-03-29 18:33:07 +01:00
tp - > shf = shf_fdopen ( i , j , NULL ) ;
2005-05-23 05:06:10 +02:00
2012-04-14 18:07:48 +02:00
maketemp_out :
2005-05-23 05:06:10 +02:00
tp - > next = * tlist ;
* tlist = tp ;
2009-06-08 22:06:50 +02:00
return ( tp ) ;
2005-05-23 05:06:10 +02:00
}
2010-01-01 18:44:10 +01:00
/*
* We use a similar collision resolution algorithm as Python 2.5 .4
* but with a slightly tweaked implementation written from scratch .
*/
2011-06-05 21:58:21 +02:00
# define INIT_TBLSHIFT 3 /* initial table shift (2^3 = 8) */
2010-01-01 18:44:10 +01:00
# define PERTURB_SHIFT 5 /* see Python 2.5.4 Objects/dictobject.c */
2005-05-23 05:06:10 +02:00
2011-06-05 21:58:21 +02:00
static void tgrow ( struct table * ) ;
2006-11-10 04:23:50 +01:00
static int tnamecmp ( const void * , const void * ) ;
2005-05-23 05:06:10 +02:00
static void
2011-06-05 21:58:21 +02:00
tgrow ( struct table * tp )
2005-05-23 05:06:10 +02:00
{
2011-06-05 21:58:21 +02:00
size_t i , j , osize , mask , perturb ;
2010-01-01 18:44:10 +01:00
struct tbl * tblp , * * pp ;
2005-05-23 05:06:10 +02:00
struct tbl * * ntblp , * * otblp = tp - > tbls ;
2011-06-05 21:58:21 +02:00
if ( tp - > tshift > 29 )
2011-06-04 18:42:31 +02:00
internal_errorf ( " hash table size limit reached " ) ;
2011-06-05 21:58:21 +02:00
/* calculate old size, new shift and new size */
2011-08-27 20:06:52 +02:00
osize = ( size_t ) 1 < < ( tp - > tshift + + ) ;
2011-06-05 21:58:21 +02:00
i = osize < < 1 ;
ntblp = alloc2 ( i , sizeof ( struct tbl * ) , tp - > areap ) ;
/* multiplication cannot overflow: alloc2 checked that */
memset ( ntblp , 0 , i * sizeof ( struct tbl * ) ) ;
2012-03-03 22:30:59 +01:00
/* table can get very full when reaching its size limit */
tp - > nfree = ( tp - > tshift = = 30 ) ? 0x3FFF0000UL :
2012-07-01 17:38:09 +02:00
/* but otherwise, only 75% */
( ( i * 3 ) / 4 ) ;
2005-05-23 05:06:10 +02:00
tp - > tbls = ntblp ;
if ( otblp = = NULL )
return ;
• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
bin/echo bin/kill bin/pwd bin/sleep (exact matches)
bin/test bin/[ (were scripts before)
bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
2011-02-11 02:18:23 +01:00
2011-06-05 21:58:21 +02:00
mask = i - 1 ;
2005-05-23 05:06:10 +02:00
for ( i = 0 ; i < osize ; i + + )
if ( ( tblp = otblp [ i ] ) ! = NULL ) {
2005-06-09 00:22:24 +02:00
if ( ( tblp - > flag & DEFINED ) ) {
2010-01-01 18:44:10 +01:00
/* search for free hash table slot */
2012-12-08 00:46:38 +01:00
j = perturb = tblp - > ua . hval ;
2010-01-01 18:44:10 +01:00
goto find_first_empty_slot ;
find_next_empty_slot :
j = ( j < < 2 ) + j + perturb + 1 ;
perturb > > = PERTURB_SHIFT ;
find_first_empty_slot :
2011-06-05 21:58:21 +02:00
pp = & ntblp [ j & mask ] ;
2010-01-01 18:44:10 +01:00
if ( * pp ! = NULL )
goto find_next_empty_slot ;
/* found an empty hash table slot */
* pp = tblp ;
2005-05-23 05:06:10 +02:00
tp - > nfree - - ;
} else if ( ! ( tblp - > flag & FINUSE ) ) {
2008-11-12 01:54:52 +01:00
afree ( tblp , tp - > areap ) ;
2005-05-23 05:06:10 +02:00
}
}
2008-11-12 01:54:52 +01:00
afree ( otblp , tp - > areap ) ;
2005-05-23 05:06:10 +02:00
}
2009-08-28 20:54:01 +02:00
void
2012-07-01 17:38:09 +02:00
ktinit ( Area * ap , struct table * tp , uint8_t initshift )
2009-08-28 20:54:01 +02:00
{
tp - > areap = ap ;
tp - > tbls = NULL ;
2011-06-05 21:58:21 +02:00
tp - > tshift = ( ( initshift > INIT_TBLSHIFT ) ?
initshift : INIT_TBLSHIFT ) - 1 ;
tgrow ( tp ) ;
2009-08-28 20:54:01 +02:00
}
2010-01-01 18:44:10 +01:00
/* table, name (key) to search for, hash(name), rv pointer to tbl ptr */
2011-06-05 21:58:21 +02:00
struct tbl *
2010-01-01 18:44:10 +01:00
ktscan ( struct table * tp , const char * name , uint32_t h , struct tbl * * * ppp )
2005-05-23 05:06:10 +02:00
{
2010-01-01 18:44:10 +01:00
size_t j , perturb , mask ;
2005-05-23 05:06:10 +02:00
struct tbl * * pp , * p ;
2011-08-27 20:06:52 +02:00
mask = ( ( size_t ) 1 < < ( tp - > tshift ) ) - 1 ;
2010-01-01 18:44:10 +01:00
/* search for hash table slot matching name */
2012-12-08 00:46:38 +01:00
j = perturb = h ;
2010-01-01 18:44:10 +01:00
goto find_first_slot ;
find_next_slot :
j = ( j < < 2 ) + j + perturb + 1 ;
perturb > > = PERTURB_SHIFT ;
find_first_slot :
pp = & tp - > tbls [ j & mask ] ;
if ( ( p = * pp ) ! = NULL & & ( p - > ua . hval ! = h | | ! ( p - > flag & DEFINED ) | |
strcmp ( p - > name , name ) ) )
goto find_next_slot ;
/* p == NULL if not found, correct found entry otherwise */
2009-08-28 22:30:59 +02:00
if ( ppp )
* ppp = pp ;
return ( p ) ;
}
2009-08-28 20:54:01 +02:00
/* table, name (key) to enter, hash(n) */
2005-05-23 05:06:10 +02:00
struct tbl *
2009-08-28 22:30:59 +02:00
ktenter ( struct table * tp , const char * n , uint32_t h )
2005-05-23 05:06:10 +02:00
{
struct tbl * * pp , * p ;
2010-09-14 23:26:19 +02:00
size_t len ;
2005-05-23 05:06:10 +02:00
2006-08-01 15:43:28 +02:00
Search :
2009-08-28 22:30:59 +02:00
if ( ( p = ktscan ( tp , n , h , & pp ) ) )
return ( p ) ;
2005-05-23 05:06:10 +02:00
2011-06-04 18:42:31 +02:00
if ( tp - > nfree = = 0 ) {
2009-08-28 22:30:59 +02:00
/* too full */
2011-06-05 21:58:21 +02:00
tgrow ( tp ) ;
2005-05-23 05:06:10 +02:00
goto Search ;
}
2009-08-28 22:30:59 +02:00
2005-05-23 05:06:10 +02:00
/* create new tbl entry */
2010-09-14 23:26:19 +02:00
len = strlen ( n ) ;
checkoktoadd ( len , offsetof ( struct tbl , name [ 0 ] ) + 1 ) ;
p = alloc ( offsetof ( struct tbl , name [ 0 ] ) + + + len , tp - > areap ) ;
2005-05-23 05:06:10 +02:00
p - > flag = 0 ;
p - > type = 0 ;
p - > areap = tp - > areap ;
2009-08-28 23:01:27 +02:00
p - > ua . hval = h ;
2005-05-23 05:06:10 +02:00
p - > u2 . field = 0 ;
p - > u . array = NULL ;
memcpy ( p - > name , n , len ) ;
/* enter in tp->tbls */
tp - > nfree - - ;
* pp = p ;
2009-06-08 22:06:50 +02:00
return ( p ) ;
2005-05-23 05:06:10 +02:00
}
void
2006-01-29 21:04:54 +01:00
ktwalk ( struct tstate * ts , struct table * tp )
2005-05-23 05:06:10 +02:00
{
2011-08-27 20:06:52 +02:00
ts - > left = ( size_t ) 1 < < ( tp - > tshift ) ;
2005-05-23 05:06:10 +02:00
ts - > next = tp - > tbls ;
}
struct tbl *
2006-01-29 21:04:54 +01:00
ktnext ( struct tstate * ts )
2005-05-23 05:06:10 +02:00
{
while ( - - ts - > left > = 0 ) {
struct tbl * p = * ts - > next + + ;
2005-06-09 00:22:24 +02:00
if ( p ! = NULL & & ( p - > flag & DEFINED ) )
2009-06-08 22:06:50 +02:00
return ( p ) ;
2005-05-23 05:06:10 +02:00
}
2009-06-08 22:06:50 +02:00
return ( NULL ) ;
2005-05-23 05:06:10 +02:00
}
static int
2006-11-10 04:23:50 +01:00
tnamecmp ( const void * p1 , const void * p2 )
2005-05-23 05:06:10 +02:00
{
2009-08-08 15:08:53 +02:00
const struct tbl * a = * ( ( const struct tbl * const * ) p1 ) ;
const struct tbl * b = * ( ( const struct tbl * const * ) p2 ) ;
2006-11-10 04:23:50 +01:00
2017-04-21 22:06:06 +02:00
return ( ascstrcmp ( a - > name , b - > name ) ) ;
2005-05-23 05:06:10 +02:00
}
struct tbl * *
2006-01-29 21:04:54 +01:00
ktsort ( struct table * tp )
2005-05-23 05:06:10 +02:00
{
2006-11-10 04:23:50 +01:00
size_t i ;
2005-05-23 05:06:10 +02:00
struct tbl * * p , * * sp , * * dp ;
2011-06-05 21:58:21 +02:00
/*
* since the table is never entirely full , no need to reserve
* additional space for the trailing NULL appended below
*/
2011-08-27 20:06:52 +02:00
i = ( size_t ) 1 < < ( tp - > tshift ) ;
2011-06-05 21:58:21 +02:00
p = alloc2 ( i , sizeof ( struct tbl * ) , ATEMP ) ;
2005-05-23 05:06:10 +02:00
sp = tp - > tbls ; /* source */
dp = p ; /* dest */
2009-08-28 20:54:01 +02:00
while ( i - - )
2005-06-09 00:22:24 +02:00
if ( ( * dp = * sp + + ) ! = NULL & & ( ( ( * dp ) - > flag & DEFINED ) | |
( ( * dp ) - > flag & ARRAY ) ) )
2005-05-23 05:06:10 +02:00
dp + + ;
2011-06-05 21:58:21 +02:00
qsort ( p , ( i = dp - p ) , sizeof ( struct tbl * ) , tnamecmp ) ;
2005-05-23 05:06:10 +02:00
p [ i ] = NULL ;
2009-06-08 22:06:50 +02:00
return ( p ) ;
2005-05-23 05:06:10 +02:00
}
2010-07-04 19:45:17 +02:00
# ifdef SIGWINCH
static void
x_sigwinch ( int sig MKSH_A_UNUSED )
{
/* this runs inside interrupt context, with errno saved */
got_winch = 1 ;
}
# endif
2012-03-23 20:38:12 +01:00
# ifdef DF
void
DF ( const char * fmt , . . . )
{
va_list args ;
struct timeval tv ;
2012-10-21 19:16:45 +02:00
mirtime_mjd mjd ;
2012-03-23 20:38:12 +01:00
2012-03-28 00:36:53 +02:00
mksh_lockfd ( shl_dbg_fd ) ;
2012-05-04 23:47:04 +02:00
mksh_TIME ( tv ) ;
2012-10-21 19:16:45 +02:00
timet2mjd ( & mjd , tv . tv_sec ) ;
shf_fprintf ( shl_dbg , " [%02u:%02u:%02u (%u) %u.%06u] " ,
( unsigned ) mjd . sec / 3600 , ( ( unsigned ) mjd . sec / 60 ) % 60 ,
( unsigned ) mjd . sec % 60 , ( unsigned ) getpid ( ) ,
( unsigned ) tv . tv_sec , ( unsigned ) tv . tv_usec ) ;
2012-03-23 20:38:12 +01:00
va_start ( args , fmt ) ;
shf_vfprintf ( shl_dbg , fmt , args ) ;
va_end ( args ) ;
shf_putc ( ' \n ' , shl_dbg ) ;
shf_flush ( shl_dbg ) ;
2012-03-28 00:36:53 +02:00
mksh_unlkfd ( shl_dbg_fd ) ;
2012-03-23 20:38:12 +01:00
}
# endif
2012-05-05 19:32:33 +02:00
void
x_mkraw ( int fd , mksh_ttyst * ocb , bool forread )
{
mksh_ttyst cb ;
if ( ocb )
mksh_tcget ( fd , ocb ) ;
else
ocb = & tty_state ;
cb = * ocb ;
if ( forread ) {
2013-11-17 23:23:29 +01:00
cb . c_iflag & = ~ ( ISTRIP ) ;
2012-05-05 19:32:33 +02:00
cb . c_lflag & = ~ ( ICANON ) | ECHO ;
} else {
2013-11-17 23:23:29 +01:00
cb . c_iflag & = ~ ( INLCR | ICRNL | ISTRIP ) ;
2012-05-05 19:32:33 +02:00
cb . c_lflag & = ~ ( ISIG | ICANON | ECHO ) ;
}
# if defined(VLNEXT) && defined(_POSIX_VDISABLE)
/* OSF/1 processes lnext when ~icanon */
cb . c_cc [ VLNEXT ] = _POSIX_VDISABLE ;
# endif
/* SunOS 4.1.x & OSF/1 processes discard(flush) when ~icanon */
# if defined(VDISCARD) && defined(_POSIX_VDISABLE)
cb . c_cc [ VDISCARD ] = _POSIX_VDISABLE ;
# endif
cb . c_cc [ VTIME ] = 0 ;
cb . c_cc [ VMIN ] = 1 ;
mksh_tcset ( fd , & cb ) ;
}