2023-03-07 12:50:17 -05:00
# include "log.h"
2022-06-04 13:04:51 -04:00
# include "mem.h"
2022-02-09 22:58:33 -05:00
# include "ssb.db.h"
2021-08-22 15:34:28 -04:00
# include "ssb.export.h"
2023-09-13 19:39:52 -04:00
# include "ssb.h"
# include "ssb.import.h"
2021-01-02 13:10:00 -05:00
# include "task.h"
2021-10-24 11:46:30 -04:00
# include "taskstub.js.h"
2021-08-19 15:29:37 -04:00
# include "tests.h"
2022-06-03 23:01:12 -04:00
# include "util.js.h"
2021-01-02 13:10:00 -05:00
2023-05-21 17:36:51 -04:00
# include "backtrace.h"
# include "sqlite3.h"
# include "xopt.h"
2021-01-02 13:10:00 -05:00
2023-03-19 20:29:46 -04:00
# include <stdlib.h>
2021-01-02 13:10:00 -05:00
# include <string.h>
2023-10-25 22:56:33 -04:00
# if !defined(_WIN32) && !defined(__APPLE__) && !defined(__HAIKU__)
2021-01-02 13:10:00 -05:00
# include <signal.h>
# include <sys/resource.h>
2023-10-04 19:20:57 -04:00
# endif
2023-11-07 22:36:08 -05:00
# if defined(__linux__)
# include <sys/prctl.h>
# endif
2023-10-13 22:11:20 -04:00
# if defined(__APPLE__)
# include <TargetConditionals.h>
# endif
2023-10-04 19:20:57 -04:00
# if !defined(_WIN32)
2021-01-02 13:10:00 -05:00
# include <unistd.h>
# endif
# if !defined(_countof)
# define _countof(a) ((int)(sizeof((a)) / sizeof(*(a))))
# endif
2023-10-13 22:11:20 -04:00
struct backtrace_state * g_backtrace_state ;
2023-10-15 12:55:25 -04:00
const char * k_db_path_default = " db.sqlite " ;
2021-01-02 13:10:00 -05:00
# define XOPT_PARSE(name, flags, options, config_ptr, argc, argv, extrac_ptr, extrav_ptr, err_ptr, autohelp_file, autohelp_usage, autohelp_prefix, autohelp_suffix, autohelp_spacer) do { \
xoptContext * _xopt_ctx ; \
* ( err_ptr ) = NULL ; \
_xopt_ctx = xopt_context ( ( name ) , ( options ) , ( ( flags ) ^ XOPT_CTX_POSIXMEHARDER ) , ( err_ptr ) ) ; \
if ( * ( err_ptr ) ) break ; \
* extrac_ptr = xopt_parse ( _xopt_ctx , ( argc ) , ( argv ) , ( config_ptr ) , ( extrav_ptr ) , ( err_ptr ) ) ; \
2021-10-10 17:51:38 -04:00
if ( ( config_ptr ) - > help ) \
{ \
2021-01-02 13:10:00 -05:00
xoptAutohelpOptions __xopt_autohelp_opts ; \
__xopt_autohelp_opts . usage = ( autohelp_usage ) ; \
__xopt_autohelp_opts . prefix = ( autohelp_prefix ) ; \
__xopt_autohelp_opts . suffix = ( autohelp_suffix ) ; \
__xopt_autohelp_opts . spacer = ( autohelp_spacer ) ; \
xopt_autohelp ( _xopt_ctx , ( autohelp_file ) , & __xopt_autohelp_opts , ( err_ptr ) ) ; \
if ( * ( err_ptr ) ) goto __xopt_end_free_extrav ; \
free ( _xopt_ctx ) ; \
goto xopt_help ; \
} \
if ( * ( err_ptr ) ) goto __xopt_end_free_ctx ; \
__xopt_end_free_ctx : \
free ( _xopt_ctx ) ; \
break ; \
__xopt_end_free_extrav : \
free ( * ( extrav_ptr ) ) ; \
free ( _xopt_ctx ) ; \
break ; \
} while ( false )
2023-10-17 18:43:13 -04:00
# if !TARGET_OS_IPHONE && !defined(__ANDROID__)
2021-01-02 13:10:00 -05:00
static int _tf_command_test ( const char * file , int argc , char * argv [ ] ) ;
static int _tf_command_import ( const char * file , int argc , char * argv [ ] ) ;
static int _tf_command_export ( const char * file , int argc , char * argv [ ] ) ;
static int _tf_command_run ( const char * file , int argc , char * argv [ ] ) ;
static int _tf_command_sandbox ( const char * file , int argc , char * argv [ ] ) ;
2022-02-09 22:58:33 -05:00
static int _tf_command_check ( const char * file , int argc , char * argv [ ] ) ;
2021-01-02 13:10:00 -05:00
static int _tf_command_usage ( const char * file , int argc , char * argv [ ] ) ;
typedef struct _command_t {
const char * name ;
int ( * callback ) ( const char * file , int argc , char * argv [ ] ) ;
const char * description ;
} command_t ;
const command_t k_commands [ ] = {
{ " run " , _tf_command_run , " Run tildefriends (default). " } ,
{ " sandbox " , _tf_command_sandbox , " Run a sandboxed tildefriends sandbox process (used internally). " } ,
{ " import " , _tf_command_import , " Import apps to SSB. " } ,
{ " export " , _tf_command_export , " Export apps from SSB. " } ,
{ " test " , _tf_command_test , " Test SSB. " } ,
2022-02-09 22:58:33 -05:00
{ " check " , _tf_command_check , " Validate messages in the SSB database. " } ,
2021-01-02 13:10:00 -05:00
} ;
static int _tf_command_test ( const char * file , int argc , char * argv [ ] )
{
2023-03-19 20:29:46 -04:00
# if !defined(__ANDROID__)
2021-01-02 13:10:00 -05:00
typedef struct args_t {
2021-09-06 14:23:22 -04:00
const char * tests ;
2021-01-02 13:10:00 -05:00
bool help ;
} args_t ;
xoptOption options [ ] = {
2021-09-06 14:23:22 -04:00
{ " tests " , ' t ' , offsetof ( args_t , tests ) , NULL , XOPT_TYPE_STRING , NULL , " Comma-separated list of test names to run. " } ,
2021-01-02 13:10:00 -05:00
{ " help " , ' h ' , offsetof ( args_t , help ) , NULL , XOPT_TYPE_BOOL , NULL , " Shows this help message. " } ,
XOPT_NULLOPTION ,
} ;
args_t args = { 0 } ;
const char * * extras = NULL ;
int extra_count = 0 ;
const char * err = NULL ;
2021-10-15 15:44:10 -04:00
XOPT_PARSE ( file , XOPT_CTX_KEEPFIRST | XOPT_CTX_STRICT , options , & args , argc , ( const char * * ) argv , & extra_count , & extras , & err , stderr , " test [options] " , " options: " , NULL , 15 ) ;
2021-10-10 17:51:38 -04:00
if ( err )
{
2021-01-02 13:10:00 -05:00
fprintf ( stderr , " Error: %s \n " , err ) ;
return 2 ;
}
2021-09-06 14:23:22 -04:00
tf_test_options_t test_options =
{
. exe_path = file ,
. tests = args . tests ,
} ;
tf_tests ( & test_options ) ;
2023-08-25 16:57:55 -04:00
if ( extras )
{
free ( ( void * ) extras ) ;
}
2021-01-02 13:10:00 -05:00
return 0 ;
xopt_help :
2021-10-10 17:51:38 -04:00
if ( extras )
{
2021-01-02 13:10:00 -05:00
free ( ( void * ) extras ) ;
}
2023-03-19 20:29:46 -04:00
# endif
2021-01-02 13:10:00 -05:00
return 1 ;
}
static int _tf_command_import ( const char * file , int argc , char * argv [ ] )
{
typedef struct args_t {
const char * user ;
const char * db_path ;
bool help ;
} args_t ;
xoptOption options [ ] = {
{ " user " , ' u ' , offsetof ( args_t , user ) , NULL , XOPT_TYPE_STRING , NULL , " User into whose account apps will be imported (default: \" import \" ). " } ,
{ " db-path " , ' d ' , offsetof ( args_t , db_path ) , NULL , XOPT_TYPE_STRING , NULL , " Sqlite database path (default: db.sqlite). " } ,
{ " help " , ' h ' , offsetof ( args_t , help ) , NULL , XOPT_TYPE_BOOL , NULL , " Shows this help message. " } ,
XOPT_NULLOPTION ,
} ;
2023-02-14 21:43:08 -05:00
args_t args = { . user = " import " , . db_path = k_db_path_default } ;
2021-01-02 13:10:00 -05:00
const char * * extras = NULL ;
int extra_count = 0 ;
const char * err = NULL ;
2021-10-15 15:44:10 -04:00
XOPT_PARSE ( file , XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER | XOPT_CTX_STRICT , options , & args , argc , ( const char * * ) argv , & extra_count , & extras , & err , stderr , " import [options] [paths] ... " , " options: " , NULL , 15 ) ;
2021-10-10 17:51:38 -04:00
if ( err )
{
2021-01-02 13:10:00 -05:00
fprintf ( stderr , " Error: %s \n " , err ) ;
return 2 ;
}
2023-02-07 20:29:44 -05:00
tf_ssb_t * ssb = tf_ssb_create ( NULL , NULL , args . db_path ) ;
2021-10-10 17:51:38 -04:00
if ( extra_count )
{
for ( int i = 0 ; i < extra_count ; i + + )
{
2023-03-07 12:50:17 -05:00
tf_printf ( " Importing %s... \n " , extras [ i ] ) ;
2021-01-02 13:10:00 -05:00
tf_ssb_import ( ssb , args . user , extras [ i ] ) ;
}
2021-10-10 17:51:38 -04:00
}
else
{
2023-03-07 12:50:17 -05:00
tf_printf ( " Importing %s... \n " , " apps " ) ;
2021-01-02 13:10:00 -05:00
tf_ssb_import ( ssb , args . user , " apps " ) ;
}
tf_ssb_destroy ( ssb ) ;
2021-10-10 17:51:38 -04:00
if ( extras )
{
2021-01-02 13:10:00 -05:00
free ( ( void * ) extras ) ;
}
return 0 ;
xopt_help :
2021-10-10 17:51:38 -04:00
if ( extras )
{
2021-01-02 13:10:00 -05:00
free ( ( void * ) extras ) ;
}
return 1 ;
}
static int _tf_command_export ( const char * file , int argc , char * argv [ ] )
{
typedef struct args_t {
2022-11-30 19:26:51 -05:00
const char * user ;
2022-01-23 14:14:43 -05:00
const char * db_path ;
2021-01-02 13:10:00 -05:00
bool help ;
} args_t ;
xoptOption options [ ] = {
2022-01-23 14:14:43 -05:00
{ " db-path " , ' d ' , offsetof ( args_t , db_path ) , NULL , XOPT_TYPE_STRING , NULL , " Sqlite database path (default: db.sqlite). " } ,
2023-02-01 21:09:05 -05:00
{ " user " , ' u ' , offsetof ( args_t , user ) , NULL , XOPT_TYPE_STRING , NULL , " User into whose apps will be exported (default: \" core \" ). " } ,
2021-01-02 13:10:00 -05:00
{ " help " , ' h ' , offsetof ( args_t , help ) , NULL , XOPT_TYPE_BOOL , NULL , " Shows this help message. " } ,
XOPT_NULLOPTION ,
} ;
2023-02-14 21:43:08 -05:00
args_t args = { . user = " core " , . db_path = k_db_path_default } ;
2021-01-02 13:10:00 -05:00
const char * * extras = NULL ;
int extra_count = 0 ;
const char * err = NULL ;
2021-10-15 15:44:10 -04:00
XOPT_PARSE ( file , XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER | XOPT_CTX_STRICT , options , & args , argc , ( const char * * ) argv , & extra_count , & extras , & err , stderr , " export [options] [paths] ... " , " options: " , NULL , 15 ) ;
2021-10-10 17:51:38 -04:00
if ( err )
{
2021-01-02 13:10:00 -05:00
fprintf ( stderr , " Error: %s \n " , err ) ;
return 2 ;
}
2023-02-07 20:29:44 -05:00
tf_ssb_t * ssb = tf_ssb_create ( NULL , NULL , args . db_path ) ;
2021-10-10 17:51:38 -04:00
if ( extra_count )
{
for ( int i = 0 ; i < extra_count ; i + + )
{
2023-03-07 12:50:17 -05:00
tf_printf ( " Exporting %s... \n " , extras [ i ] ) ;
2021-01-02 13:10:00 -05:00
tf_ssb_export ( ssb , extras [ i ] ) ;
}
2021-10-10 17:51:38 -04:00
}
else
{
2021-01-02 13:10:00 -05:00
const char * k_export [ ] = {
2022-11-30 19:26:51 -05:00
" admin " ,
" api " ,
" apps " ,
2023-03-25 10:33:52 -04:00
" appstore " ,
2022-11-30 19:26:51 -05:00
" db " ,
" docs " ,
" follow " ,
2022-12-28 12:16:50 -05:00
" ssb " ,
2022-11-30 19:26:51 -05:00
" todo " ,
2021-01-02 13:10:00 -05:00
} ;
2022-05-16 18:30:14 -04:00
for ( int i = 0 ; i < ( int ) _countof ( k_export ) ; i + + )
2021-10-10 17:51:38 -04:00
{
2022-11-30 19:26:51 -05:00
char buffer [ 256 ] ;
snprintf ( buffer , sizeof ( buffer ) , " /~%s/%s " , args . user , k_export [ i ] ) ;
2023-03-07 12:50:17 -05:00
tf_printf ( " Exporting %s... \n " , buffer ) ;
2022-11-30 19:26:51 -05:00
tf_ssb_export ( ssb , buffer ) ;
2021-01-02 13:10:00 -05:00
}
}
tf_ssb_destroy ( ssb ) ;
2021-10-10 17:51:38 -04:00
if ( extras )
{
2021-01-02 13:10:00 -05:00
free ( ( void * ) extras ) ;
}
return 0 ;
xopt_help :
2021-10-10 17:51:38 -04:00
if ( extras )
{
2021-01-02 13:10:00 -05:00
free ( ( void * ) extras ) ;
}
return 1 ;
}
2023-10-15 12:55:25 -04:00
# endif
2021-01-02 13:10:00 -05:00
2021-11-14 17:55:21 -05:00
typedef struct tf_run_args_t {
const char * script ;
int ssb_port ;
int http_port ;
int https_port ;
const char * db_path ;
int count ;
2021-12-01 18:29:53 -05:00
const char * args ;
2023-03-08 18:59:11 -05:00
const char * zip ;
2023-10-15 13:33:36 -04:00
bool one_proc ;
2023-11-08 19:28:34 -05:00
bool verbose ;
2021-11-14 17:55:21 -05:00
bool help ;
} tf_run_args_t ;
typedef struct _tf_run_thread_data_t
2021-01-02 13:10:00 -05:00
{
2021-11-14 17:55:21 -05:00
tf_run_args_t args ;
int index ;
int result ;
} tf_run_thread_data_t ;
static int _tf_run_task ( const tf_run_args_t * args , int index )
{
int result = - 1 ;
tf_task_t * task = tf_task_create ( ) ;
tf_task_set_trusted ( task , true ) ;
2023-03-08 19:32:42 -05:00
tf_printf ( " setting zip path to %s \n " , args - > zip ) ;
2023-03-08 18:59:11 -05:00
tf_task_set_zip_path ( task , args - > zip ) ;
2021-11-14 17:55:21 -05:00
tf_task_set_ssb_port ( task , args - > ssb_port ? args - > ssb_port + index : 0 ) ;
tf_task_set_http_port ( task , args - > http_port ? args - > http_port + index : 0 ) ;
tf_task_set_https_port ( task , args - > https_port ? args - > https_port + index : 0 ) ;
2021-12-01 18:29:53 -05:00
tf_task_set_args ( task , args - > args ) ;
2023-10-15 13:33:36 -04:00
tf_task_set_one_proc ( task , args - > one_proc ) ;
2021-11-14 17:55:21 -05:00
const char * db_path = args - > db_path ;
char db_path_buffer [ 256 ] ;
if ( index )
{
snprintf ( db_path_buffer , sizeof ( db_path_buffer ) , " %s.%d " , args - > db_path , index ) ;
db_path = db_path_buffer ;
}
tf_task_set_db_path ( task , db_path ) ;
tf_task_activate ( task ) ;
2023-11-08 19:28:34 -05:00
tf_ssb_set_verbose ( tf_task_get_ssb ( task ) , args - > verbose ) ;
2023-11-08 18:03:21 -05:00
tf_ssb_start_periodic ( tf_task_get_ssb ( task ) ) ;
2023-08-02 20:30:48 -04:00
if ( args - > zip )
2022-06-04 11:43:35 -04:00
{
2023-08-02 20:30:48 -04:00
tf_ssb_import_from_zip ( tf_task_get_ssb ( task ) , args - > zip , " core " , " apps " ) ;
}
else
{
tf_ssb_import ( tf_task_get_ssb ( task ) , " core " , " apps " ) ;
2022-06-04 11:43:35 -04:00
}
2021-11-14 17:55:21 -05:00
if ( tf_task_execute ( task , args - > script ) )
{
tf_task_run ( task ) ;
result = 0 ;
}
tf_task_destroy ( task ) ;
2023-03-07 21:49:41 -05:00
tf_printf ( " _tf_run_task is done. Goodbye. \n " ) ;
2021-11-14 17:55:21 -05:00
return result ;
}
2021-01-02 13:10:00 -05:00
2021-11-14 17:55:21 -05:00
static void _tf_run_task_thread ( void * data )
{
tf_run_thread_data_t * info = data ;
info - > result = _tf_run_task ( & info - > args , info - > index ) ;
}
2023-10-15 12:55:25 -04:00
# if !TARGET_OS_IPHONE
2023-10-17 18:43:13 -04:00
static void _shed_privileges ( )
{
2023-10-25 22:56:33 -04:00
# if !defined(_WIN32) && !defined(__HAIKU__)
2023-10-17 18:43:13 -04:00
struct rlimit zeroLimit ;
zeroLimit . rlim_cur = 0 ;
zeroLimit . rlim_max = 0 ;
// RLIMIT_AS
// RLIMIT_CORE
// RLIMIT_CPU
// RLIMIT_DATA
// RLIMIT_FSIZE
// RLIMIT_RSS
// RLIMIT_RTPRIO
// RLIMIT_RTTIME
// RLIMIT_SIGPENDING
// RLIMIT_STACK
if ( setrlimit ( RLIMIT_FSIZE , & zeroLimit ) ! = 0 )
{
perror ( " setrlimit(RLIMIT_FSIZE, {0, 0}) " ) ;
exit ( - 1 ) ;
}
if ( setrlimit ( RLIMIT_NOFILE , & zeroLimit ) ! = 0 )
{
perror ( " setrlimit(RLIMIT_NOFILE, {0, 0}) " ) ;
exit ( - 1 ) ;
}
if ( setrlimit ( RLIMIT_NPROC , & zeroLimit ) ! = 0 )
{
perror ( " setrlimit(RLIMIT_NPROC, {0, 0}) " ) ;
exit ( - 1 ) ;
}
2023-11-07 22:36:08 -05:00
# if !defined(__MACH__) && !defined(__OpenBSD__)
2023-10-17 18:43:13 -04:00
if ( setrlimit ( RLIMIT_LOCKS , & zeroLimit ) ! = 0 )
{
perror ( " setrlimit(RLIMIT_LOCKS, {0, 0}) " ) ;
exit ( - 1 ) ;
}
if ( setrlimit ( RLIMIT_MSGQUEUE , & zeroLimit ) ! = 0 )
{
perror ( " setrlimit(RLIMIT_MSGQUEUE, {0, 0}) " ) ;
exit ( - 1 ) ;
}
# endif
# endif
}
2021-11-14 17:55:21 -05:00
static int _tf_command_run ( const char * file , int argc , char * argv [ ] )
{
2021-01-02 13:10:00 -05:00
xoptOption options [ ] = {
2021-11-14 17:55:21 -05:00
{ " script " , ' s ' , offsetof ( tf_run_args_t , script ) , NULL , XOPT_TYPE_STRING , NULL , " Script to run (default: core/core.js). " } ,
2023-08-25 14:51:14 -04:00
{ " ssb-port " , ' b ' , offsetof ( tf_run_args_t , ssb_port ) , NULL , XOPT_TYPE_INT , NULL , " Port on which to run SSB (default: 8008). " } ,
2021-11-14 17:55:21 -05:00
{ " http-port " , ' p ' , offsetof ( tf_run_args_t , http_port ) , NULL , XOPT_TYPE_INT , NULL , " Port on which to run Tilde Friends web server (default: 12345). " } ,
{ " https-port " , ' q ' , offsetof ( tf_run_args_t , https_port ) , NULL , XOPT_TYPE_INT , NULL , " Port on which to run secure Tilde Friends web server (default: 12346). " } ,
{ " db-path " , ' d ' , offsetof ( tf_run_args_t , db_path ) , NULL , XOPT_TYPE_STRING , NULL , " Sqlite database path (default: db.sqlite). " } ,
{ " count " , ' n ' , offsetof ( tf_run_args_t , count ) , NULL , XOPT_TYPE_INT , NULL , " Number of instances to run. " } ,
2021-12-01 18:29:53 -05:00
{ " args " , ' a ' , offsetof ( tf_run_args_t , args ) , NULL , XOPT_TYPE_STRING , NULL , " Arguments of the form key=value,foo=bar,verbose=true. " } ,
2023-10-15 13:33:36 -04:00
{ " one-proc " , ' o ' , offsetof ( tf_run_args_t , one_proc ) , NULL , XOPT_TYPE_BOOL , NULL , " Run everything in one process (unsafely!). " } ,
2023-03-08 18:59:11 -05:00
{ " zip " , ' z ' , offsetof ( tf_run_args_t , zip ) , NULL , XOPT_TYPE_STRING , NULL , " Zip archive from which to load files. " } ,
2023-11-08 19:28:34 -05:00
{ " verbose " , ' v ' , offsetof ( tf_run_args_t , verbose ) , NULL , XOPT_TYPE_BOOL , NULL , " Log raw messages. " } ,
2021-11-14 17:55:21 -05:00
{ " help " , ' h ' , offsetof ( tf_run_args_t , help ) , NULL , XOPT_TYPE_BOOL , NULL , " Shows this help message. " } ,
2021-01-02 13:10:00 -05:00
XOPT_NULLOPTION ,
} ;
2021-11-14 17:55:21 -05:00
tf_run_args_t args =
{
. count = 1 ,
2021-01-02 13:10:00 -05:00
. script = " core/core.js " ,
. http_port = 12345 ,
2022-01-04 20:58:12 -05:00
. https_port = 12346 ,
2023-08-25 14:51:14 -04:00
. ssb_port = 8008 ,
2023-02-14 21:43:08 -05:00
. db_path = k_db_path_default ,
2021-01-02 13:10:00 -05:00
} ;
const char * * extras = NULL ;
int extra_count = 0 ;
const char * err = NULL ;
2021-10-15 15:44:10 -04:00
XOPT_PARSE ( file , XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER | XOPT_CTX_STRICT , options , & args , argc , ( const char * * ) argv , & extra_count , & extras , & err , stderr , " run [options] [paths] ... " , " options: " , NULL , 15 ) ;
2021-01-02 13:10:00 -05:00
2021-10-10 17:51:38 -04:00
if ( err )
{
2021-01-02 13:10:00 -05:00
fprintf ( stderr , " Error: %s \n " , err ) ;
return 2 ;
}
int result = 0 ;
2022-05-16 18:30:14 -04:00
# if !defined(_WIN32) && !defined(__MACH__)
2021-01-02 13:10:00 -05:00
setpgid ( 0 , 0 ) ;
# endif
2021-11-14 17:55:21 -05:00
if ( args . count = = 1 )
2021-01-02 13:10:00 -05:00
{
2021-11-14 17:55:21 -05:00
_tf_run_task ( & args , 0 ) ;
2021-01-02 13:10:00 -05:00
}
2021-11-14 17:55:21 -05:00
if ( args . count > 1 )
2021-01-02 13:10:00 -05:00
{
2022-06-04 13:04:51 -04:00
uv_thread_t * threads = tf_malloc ( sizeof ( uv_thread_t ) * args . count ) ;
tf_run_thread_data_t * data = tf_malloc ( sizeof ( tf_run_thread_data_t ) * args . count ) ;
2021-11-14 17:55:21 -05:00
for ( int i = 0 ; i < args . count ; i + + )
{
data [ i ] = ( tf_run_thread_data_t )
{
. args = args ,
. index = i ,
} ;
uv_thread_create ( & threads [ i ] , _tf_run_task_thread , & data [ i ] ) ;
}
for ( int i = 0 ; i < args . count ; i + + )
{
uv_thread_join ( & threads [ i ] ) ;
if ( data [ i ] . result ! = 0 )
{
result = data [ i ] . result ;
}
}
2022-06-04 13:04:51 -04:00
tf_free ( data ) ;
tf_free ( threads ) ;
2021-01-02 13:10:00 -05:00
}
2021-11-14 17:55:21 -05:00
2023-08-25 16:57:55 -04:00
if ( extras )
{
free ( ( void * ) extras ) ;
}
2021-01-02 13:10:00 -05:00
return result ;
xopt_help :
2021-10-10 17:51:38 -04:00
if ( extras )
{
2021-01-02 13:10:00 -05:00
free ( ( void * ) extras ) ;
}
return 1 ;
}
static int _tf_command_sandbox ( const char * file , int argc , char * argv [ ] )
{
typedef struct args_t {
const char * script ;
bool help ;
} args_t ;
xoptOption options [ ] = {
{ " help " , ' h ' , offsetof ( args_t , help ) , NULL , XOPT_TYPE_BOOL , NULL , " Shows this help message. " } ,
XOPT_NULLOPTION ,
} ;
args_t args = { 0 } ;
const char * * extras = NULL ;
int extra_count = 0 ;
const char * err = NULL ;
2021-10-15 15:44:10 -04:00
XOPT_PARSE ( file , XOPT_CTX_KEEPFIRST | XOPT_CTX_POSIXMEHARDER | XOPT_CTX_STRICT , options , & args , argc , ( const char * * ) argv , & extra_count , & extras , & err , stderr , " sandbox [options] " , " options: " , NULL , 15 ) ;
2021-10-10 17:51:38 -04:00
if ( err )
{
2021-01-02 13:10:00 -05:00
fprintf ( stderr , " Error: %s \n " , err ) ;
return 2 ;
}
2023-11-07 22:36:08 -05:00
# if defined(__linux__)
2021-01-02 13:10:00 -05:00
prctl ( PR_SET_PDEATHSIG , SIGHUP ) ;
# endif
tf_task_t * task = tf_task_create ( ) ;
2023-10-15 13:33:36 -04:00
tf_task_configure_from_fd ( task , STDIN_FILENO ) ;
2023-10-17 18:43:13 -04:00
_shed_privileges ( ) ;
2022-01-02 13:17:58 -05:00
/* The caller will trigger tf_task_activate with a message. */
2021-01-02 13:10:00 -05:00
tf_task_run ( task ) ;
tf_task_destroy ( task ) ;
2023-08-25 16:57:55 -04:00
if ( extras )
{
free ( ( void * ) extras ) ;
}
2021-01-02 13:10:00 -05:00
return 0 ;
xopt_help :
2021-10-10 17:51:38 -04:00
if ( extras )
{
2021-01-02 13:10:00 -05:00
free ( ( void * ) extras ) ;
}
return 1 ;
}
2023-10-17 18:43:13 -04:00
# if !defined(__ANDROID__)
2022-02-09 22:58:33 -05:00
static int _tf_command_check ( const char * file , int argc , char * argv [ ] )
{
typedef struct args_t {
bool help ;
} args_t ;
xoptOption options [ ] = {
{ " help " , ' h ' , offsetof ( args_t , help ) , NULL , XOPT_TYPE_BOOL , NULL , " Shows this help message. " } ,
XOPT_NULLOPTION ,
} ;
args_t args = { 0 } ;
const char * * extras = NULL ;
int extra_count = 0 ;
const char * err = NULL ;
2023-02-26 14:51:54 -05:00
XOPT_PARSE ( file , XOPT_CTX_KEEPFIRST | XOPT_CTX_STRICT , options , & args , argc , ( const char * * ) argv , & extra_count , & extras , & err , stderr , " check [options] " , " options: " , NULL , 15 ) ;
2022-02-09 22:58:33 -05:00
if ( err )
{
fprintf ( stderr , " Error: %s \n " , err ) ;
return 2 ;
}
2022-02-10 21:44:27 -05:00
bool result = true ;
2022-02-09 22:58:33 -05:00
sqlite3 * db = NULL ;
2023-02-14 21:43:08 -05:00
sqlite3_open ( k_db_path_default , & db ) ;
2022-02-10 21:44:27 -05:00
if ( extra_count )
{
for ( int i = 0 ; i < extra_count ; i + + )
{
result = result & & tf_ssb_db_check ( db , extras [ i ] ) ;
}
}
else
{
result = tf_ssb_db_check ( db , NULL ) ;
}
2022-02-09 22:58:33 -05:00
sqlite3_close ( db ) ;
2022-02-10 21:44:27 -05:00
if ( extras )
{
free ( ( void * ) extras ) ;
}
2022-02-09 22:58:33 -05:00
return result ? EXIT_SUCCESS : EXIT_FAILURE ;
xopt_help :
if ( extras )
{
free ( ( void * ) extras ) ;
}
return 1 ;
}
2021-01-02 13:10:00 -05:00
static int _tf_command_usage ( const char * file , int argc , char * argv [ ] )
{
2023-03-07 12:50:17 -05:00
tf_printf ( " Usage: %s command [command-options] \n " , file ) ;
tf_printf ( " commands: \n " ) ;
2022-05-16 18:30:14 -04:00
for ( int i = 0 ; i < ( int ) _countof ( k_commands ) ; i + + )
2021-10-10 17:51:38 -04:00
{
2023-03-07 12:50:17 -05:00
tf_printf ( " %s - %s \n " , k_commands [ i ] . name , k_commands [ i ] . description ) ;
2021-01-02 13:10:00 -05:00
}
return 0 ;
}
2023-10-16 09:57:40 -04:00
# endif
2023-10-17 18:43:13 -04:00
# endif
2021-01-02 13:10:00 -05:00
2022-09-24 16:54:54 -04:00
static void _backtrace_error ( void * data , const char * message , int errnum )
{
2023-03-07 12:50:17 -05:00
tf_printf ( " libbacktrace error %d: %s \n " , errnum , message ) ;
2022-09-24 16:54:54 -04:00
}
2023-08-04 23:10:24 -04:00
static void _error_handler ( int sig )
{
const char * stack = tf_util_backtrace_string ( ) ;
tf_printf ( " ERROR: \n %s \n " , stack ) ;
tf_free ( ( void * ) stack ) ;
_exit ( 1 ) ;
}
2023-10-16 09:57:40 -04:00
static void _startup ( int argc , char * argv [ ] )
2021-01-02 13:10:00 -05:00
{
2023-03-12 18:16:18 -04:00
bool tracking = false ;
2023-02-18 16:00:39 -05:00
for ( int i = 1 ; i < argc ; i + + )
{
if ( strcmp ( argv [ i ] , " sandbox " ) = = 0 )
{
tracking = false ;
}
}
2023-05-23 19:06:59 -04:00
# if defined(__ANDROID__)
setenv ( " UV_USE_IO_URING " , " 0 " , 1 ) ;
# endif
2023-02-18 16:00:39 -05:00
tf_mem_startup ( tracking ) ;
2022-09-24 16:54:54 -04:00
g_backtrace_state = backtrace_create_state (
argv [ 0 ] ,
0 ,
_backtrace_error ,
NULL ) ;
2023-11-07 22:36:08 -05:00
# if defined(__linux__)
2021-08-19 15:29:37 -04:00
prctl ( PR_SET_PDEATHSIG , SIGKILL ) ;
2022-05-16 18:30:14 -04:00
# endif
2022-06-04 13:04:51 -04:00
tf_mem_replace_uv_allocator ( ) ;
tf_mem_replace_tls_allocator ( ) ;
2023-02-18 14:14:06 -05:00
tf_mem_replace_sqlite_allocator ( ) ;
2021-01-02 13:10:00 -05:00
uv_setup_args ( argc , argv ) ;
tf_taskstub_startup ( ) ;
2022-05-16 18:30:14 -04:00
# if !defined(_WIN32)
2021-10-10 17:51:38 -04:00
if ( signal ( SIGPIPE , SIG_IGN ) = = SIG_ERR )
{
2021-01-02 13:10:00 -05:00
perror ( " signal " ) ;
}
# endif
2023-08-04 23:10:24 -04:00
bool use_error_handler = false ;
# if defined(__ANDROID__)
use_error_handler = true ;
# endif
2023-08-22 12:48:12 -04:00
if ( use_error_handler )
2023-08-04 23:10:24 -04:00
{
2023-08-22 12:49:42 -04:00
if (
# if !defined(_WIN32)
signal ( SIGSYS , _error_handler ) = = SIG_ERR | |
# endif
signal ( SIGSEGV , _error_handler ) = = SIG_ERR )
2023-08-22 12:48:12 -04:00
{
perror ( " signal " ) ;
}
2023-08-04 23:10:24 -04:00
}
2023-10-16 09:57:40 -04:00
}
2023-10-17 18:43:13 -04:00
# if defined(__ANDROID__)
2023-10-16 09:57:40 -04:00
int main ( int argc , char * argv [ ] )
{
_startup ( argc , argv ) ;
2023-10-17 18:43:13 -04:00
int result = - 1 ;
if ( argc > 1 )
2021-10-10 17:51:38 -04:00
{
2023-10-17 18:43:13 -04:00
if ( strcmp ( argv [ 1 ] , " run " ) = = 0 )
2021-10-10 17:51:38 -04:00
{
2023-10-17 18:43:13 -04:00
result = _tf_command_run ( argv [ 0 ] , argc - 2 , argv + 2 ) ;
}
else if ( strcmp ( argv [ 1 ] , " sandbox " ) = = 0 )
{
result = _tf_command_sandbox ( argv [ 0 ] , argc - 2 , argv + 2 ) ;
2021-01-02 13:10:00 -05:00
}
2023-02-18 16:00:39 -05:00
}
tf_mem_shutdown ( ) ;
return result ;
2021-01-02 13:10:00 -05:00
}
2023-10-19 20:16:01 -04:00
# elif TARGET_OS_IPHONE
2023-10-15 12:55:25 -04:00
void tf_run_thread_start ( const char * zip_path )
{
2023-10-16 09:57:40 -04:00
_startup ( 0 , NULL ) ;
2023-10-15 12:55:25 -04:00
uv_thread_t * thread = tf_malloc ( sizeof ( uv_thread_t ) ) ;
tf_run_thread_data_t * data = tf_malloc ( sizeof ( tf_run_thread_data_t ) ) ;
tf_run_args_t args =
{
. count = 1 ,
. script = " core/core.js " ,
. http_port = 12345 ,
. https_port = 12346 ,
. ssb_port = 8008 ,
. db_path = k_db_path_default ,
2023-10-15 13:42:04 -04:00
. one_proc = true ,
2023-10-15 12:55:25 -04:00
. zip = zip_path ,
} ;
* data = ( tf_run_thread_data_t )
{
. args = args ,
} ;
uv_thread_create ( thread , _tf_run_task_thread , data ) ;
}
2023-10-17 18:43:13 -04:00
# else
int main ( int argc , char * argv [ ] )
{
_startup ( argc , argv ) ;
int result = 0 ;
if ( argc > = 2 )
{
for ( int i = 0 ; i < ( int ) _countof ( k_commands ) ; i + + )
{
const command_t * command = & k_commands [ i ] ;
if ( strcmp ( argv [ 1 ] , command - > name ) = = 0 )
{
result = command - > callback ( argv [ 0 ] , argc - 2 , argv + 2 ) ;
goto done ;
}
}
result = _tf_command_usage ( argv [ 0 ] , argc , argv ) ;
}
else
{
result = _tf_command_run ( argv [ 0 ] , argc - 1 , argv + 1 ) ;
}
done :
tf_mem_shutdown ( ) ;
return result ;
}
2023-10-16 21:30:38 -04:00
# endif