diff --git a/include/ptycon/ptycon.h b/include/ptycon/ptycon.h index ce0fbd7..78282cf 100644 --- a/include/ptycon/ptycon.h +++ b/include/ptycon/ptycon.h @@ -61,6 +61,7 @@ struct ptyc_common_ctx { nt_pty * hpts; nt_pty * hptm; char ** catv; + char ** eargv; }; struct ptyc_driver_ctx { diff --git a/src/driver/ptyc_driver_ctx.c b/src/driver/ptyc_driver_ctx.c index ab4cbdb..459abe2 100644 --- a/src/driver/ptyc_driver_ctx.c +++ b/src/driver/ptyc_driver_ctx.c @@ -51,6 +51,11 @@ struct ptyc_driver_ctx_alloc { const char * units[]; }; +struct ptyc_split_vector { + char ** targv; + char ** eargv; +}; + static int32_t ptyc_once = 0; static int32_t ptyc_vtbl_init(void) @@ -161,6 +166,45 @@ static int ptyc_get_driver_ctx_fail(struct argv_meta * meta) return -1; } +#define PTYC_SARGV_ELEMENTS 1024 + +static int ptyc_split_argv( + char ** argv, + struct ptyc_split_vector * sargv) +{ + ptrdiff_t argc; + char ** parg; + + /* argc */ + for (parg=argv; *parg; ) + parg++; + + if ((argc = parg - argv) >= PTYC_SARGV_ELEMENTS) + return -1; + + /* clone argv into targv */ + ntapi->tt_aligned_block_memset( + (uintptr_t *)sargv->targv, + 0,PTYC_SARGV_ELEMENTS*sizeof(char *)); + + ntapi->tt_aligned_block_memcpy( + (uintptr_t *)sargv->targv, + (uintptr_t *)argv, + argc*sizeof(char *)); + + /* eargv */ + for (parg=sargv->targv; *parg; parg++) { + if (!(strcmp(*parg,"-e")) || !(strcmp(*parg,"--exec"))) { + sargv->eargv = parg; + sargv->eargv++; + *parg = 0; + return 0; + } + } + + return 0; +} + int ptyc_get_driver_ctx( char ** argv, char ** envp, @@ -169,11 +213,13 @@ int ptyc_get_driver_ctx( { struct ptyc_driver_ctx_impl * ctx; struct ptyc_common_ctx cctx; + struct ptyc_split_vector sargv; const struct argv_option * options; struct argv_meta * meta; struct argv_entry * entry; size_t nunits; const char * program; + char * targv[PTYC_SARGV_ELEMENTS]; (void)envp; @@ -185,13 +231,20 @@ int ptyc_get_driver_ctx( options = ptyc_default_options; - if (!(meta = argv_get(argv,options,ptyc_argv_flags(flags)))) + sargv.targv = targv; + sargv.eargv = 0; + + if (ptyc_split_argv(argv,&sargv)) + return -1; + + if (!(meta = argv_get(sargv.targv,options,ptyc_argv_flags(flags)))) return -1; nunits = 0; program = argv_program_name(argv[0]); memset(&cctx,0,sizeof(cctx)); cctx.drvflags = flags; + cctx.eargv = sargv.eargv; if (!argv[1] && (flags & PTYC_DRIVER_VERBOSITY_USAGE)) return ptyc_driver_usage(program,0,options,meta); @@ -243,7 +296,9 @@ int ptyc_get_driver_ctx( cctx.drvflags |= PTYC_DRIVER_DBG_WAIT; break; } - } + } else + /* strict */ + return ptyc_driver_usage(program,0,options,meta); } if (!(ctx = ptyc_driver_ctx_alloc(meta,&cctx,nunits))) diff --git a/src/internal/ptycon_driver_impl.h b/src/internal/ptycon_driver_impl.h index b1eefc7..03f0c9b 100644 --- a/src/internal/ptycon_driver_impl.h +++ b/src/internal/ptycon_driver_impl.h @@ -27,6 +27,7 @@ enum app_tags { TAG_DAEMON, TAG_DEBUG, TAG_CAT, + TAG_EXEC, TAG_WAIT, }; diff --git a/src/skin/ptyc_skin_default.c b/src/skin/ptyc_skin_default.c index 1239947..814f6c2 100644 --- a/src/skin/ptyc_skin_default.c +++ b/src/skin/ptyc_skin_default.c @@ -8,6 +8,15 @@ const struct argv_option ptyc_default_options[] = { {"help", 'h',TAG_HELP,ARGV_OPTARG_OPTIONAL,0,"short|long",0, "show usage information [listing %s options only]"}, + {"-exec", 0,TAG_EXEC,ARGV_OPTARG_REQUIRED, + ARGV_OPTION_HYBRID_ONLY | ARGV_OPTION_HYBRID_SPACE, + 0," ... [argv] ...", + "execute %s; default is /bin/sh."}, + + {"e", 0,TAG_EXEC,ARGV_OPTARG_REQUIRED, + ARGV_OPTION_HYBRID_ONLY | ARGV_OPTION_HYBRID_SPACE, + 0,0,"synonym for --exec."}, + {"daemon", 0,TAG_DAEMON,ARGV_OPTARG_OPTIONAL,0,"default|always|never",0, "create a daemon thread and handle signals sent by the " "application's own controlling terminal. The default is "