diff --git a/include/toksvc/toksvc.h b/include/toksvc/toksvc.h index b1eb2b8..06fcbd2 100644 --- a/include/toksvc/toksvc.h +++ b/include/toksvc/toksvc.h @@ -124,6 +124,9 @@ toks_api int toks_get_driver_ctx (char ** argv, char ** envp, uint32_t fl toks_api void toks_free_driver_ctx (struct toks_driver_ctx *); +toks_api void toks_driver_set_timeout (struct toks_driver_ctx *, int64_t millisecs); +toks_api void toks_driver_unset_timeout (struct toks_driver_ctx *); + /* core api */ /* client api */ diff --git a/src/client/toks_client_acquire.c b/src/client/toks_client_acquire.c index 8dfd205..6ed26c5 100644 --- a/src/client/toks_client_acquire.c +++ b/src/client/toks_client_acquire.c @@ -11,12 +11,33 @@ #include "toksvc_driver_impl.h" #include "toksvc_daemon_impl.h" +static int32_t toks_client_cancel(void * hport) +{ + int32_t status; + struct _nt_tty_ipc_msg msg; + + ntapi->tt_aligned_block_memset( + &msg,0,sizeof(msg)); + + msg.header.msg_type = NT_LPC_NEW_MESSAGE; + msg.header.data_size = sizeof(msg.data); + msg.header.msg_size = sizeof(msg); + msg.data.ttyinfo.opcode = TOKS_DAEMON_CANCEL; + + if ((status = ntapi->zw_request_wait_reply_port(hport,&msg,&msg))) + return status; + + return msg.data.ttyinfo.status; +} + int32_t toks_client_acquire(struct toks_driver_ctx * dctx) { int32_t status; void * hport; struct _nt_tty_ipc_msg msg; struct _nt_port_keys * keys; + int64_t millisecs; + nt_timeout timeout; hport = toks_get_driver_hservice(dctx); keys = toks_get_driver_keys(dctx); @@ -32,6 +53,17 @@ int32_t toks_client_acquire(struct toks_driver_ctx * dctx) msg.data.ipcinfo.ctrlsvc.keys.key[0] = toks_get_driver_tokpid(dctx); msg.data.ipcinfo.hevent = toks_get_driver_hevent(dctx); + if (!(millisecs = toks_get_driver_timeout(dctx))) { + msg.data.ipcinfo.hevent = 0; + + } else if (millisecs == (-1)) { + timeout.ulow = ~(0u); + timeout.ihigh = ~(0x80000000); + + } else { + timeout.quad = (-1) * 10 * 1000 * millisecs; + } + if ((status = ntapi->zw_request_wait_reply_port(hport,&msg,&msg))) return status; @@ -43,7 +75,18 @@ int32_t toks_client_acquire(struct toks_driver_ctx * dctx) status = ntapi->zw_wait_for_single_object( msg.data.ipcinfo.hevent, NT_SYNC_NON_ALERTABLE, - 0); + &timeout); + + if (status != NT_STATUS_SUCCESS) { + switch (toks_client_cancel(hport)) { + case NT_STATUS_NOT_FOUND: + break; + + default: + return status; + } + } + break; default: @@ -57,5 +100,5 @@ int32_t toks_client_acquire(struct toks_driver_ctx * dctx) keys->key[4] = msg.data.ipcinfo.ipckeys[4]; keys->key[5] = msg.data.ipcinfo.ipckeys[5]; - return status; + return NT_STATUS_SUCCESS; } diff --git a/src/driver/toks_amain.c b/src/driver/toks_amain.c index e14f579..2b6bdaa 100644 --- a/src/driver/toks_amain.c +++ b/src/driver/toks_amain.c @@ -13,6 +13,7 @@ #include "toksvc_driver_impl.h" #include "toksvc_dprintf_impl.h" #include "toksvc_nolibc_impl.h" +#include "toksvc_log_impl.h" #ifndef TOKS_DRIVER_FLAGS #define TOKS_DRIVER_FLAGS TOKS_DRIVER_VERBOSITY_ERRORS \ @@ -60,6 +61,7 @@ static int toks_exit(struct toks_driver_ctx * dctx, int nerrors) int toks_main(char ** argv, char ** envp) { int ret; + int32_t status; struct toks_driver_ctx * dctx; struct toks_token_string toks; @@ -76,9 +78,25 @@ int toks_main(char ** argv, char ** envp) return toks_exit(dctx,2); if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_ACQUIRE) { - ret = toks_client_acquire(dctx) + ret = (status = toks_client_acquire(dctx)) ? 2 : 0; + switch (status) { + case NT_STATUS_SUCCESS: + break; + + case NT_STATUS_TIMEOUT: + toks_dprintf(STDERR_FILENO, + "%s: the operataion timed out [0x%x].\n", + toks_log_basename(argv[0]),status); + break; + + default: + toks_dprintf(STDERR_FILENO, + "%s: the operataion has failed [0x%x].\n", + toks_log_basename(argv[0]),status); + } + if (ret == 0) { toks_client_token_to_str(dctx,&toks); toks_dprintf(STDOUT_FILENO,"%s\n",toks.token); diff --git a/src/driver/toks_driver_ctx.c b/src/driver/toks_driver_ctx.c index 8f460f7..dc2730b 100644 --- a/src/driver/toks_driver_ctx.c +++ b/src/driver/toks_driver_ctx.c @@ -182,6 +182,7 @@ int toks_get_driver_ctx( struct argv_entry * entry; struct argv_entry * uuid; struct argv_entry * pid; + struct argv_entry * msecs; struct toks_token_string key; size_t keylen; nt_guid svcguid; @@ -189,6 +190,7 @@ int toks_get_driver_ctx( const char * ch; int ntokens; int32_t tokpid; + int64_t timeout; void * hkernel32; char * targv[TOKS_SARGV_ELEMENTS]; @@ -218,6 +220,7 @@ int toks_get_driver_ctx( tokpid = 0; keylen = 0; ntokens = 0; + timeout = (-1); program = argv_program_name(argv[0]); memset(&cctx,0,sizeof(cctx)); @@ -265,6 +268,19 @@ int toks_get_driver_ctx( tokpid = tokpid * 10 + (*ch - '0'); break; + case TAG_TIMEOUT: + msecs = entry; + + for (timeout=0, ch=entry->arg; *ch && (timeout>=0); ch++) + if ((*ch < '0') || (*ch >'9')) + timeout = -2; + else if ((ch - entry->arg) > 15) + timeout = -2; + else + timeout = timeout * 10 + (*ch - '0'); + + break; + case TAG_TOKENS: for (ntokens=0, ch=entry->arg; *ch && (ntokens>=0); ch++) if ((*ch < '0') || (*ch >'9')) @@ -315,6 +331,14 @@ int toks_get_driver_ctx( return toks_get_driver_ctx_fail(meta); } + if ((cctx.drvflags & TOKS_DRIVER_MODE_CLIENT) && (timeout < (-1))) { + if (flags & TOKS_DRIVER_VERBOSITY_ERRORS) + toks_dprintf(STDERR_FILENO, + "%s: error: %s is not a valid timeout in milliseconds.", + program,msecs->arg); + return toks_get_driver_ctx_fail(meta); + } + if ((cctx.drvflags & TOKS_DRIVER_MODE_SERVER) && (ntokens <= 0)) { if (flags & TOKS_DRIVER_VERBOSITY_ERRORS) toks_dprintf(STDERR_FILENO, @@ -383,6 +407,7 @@ int toks_get_driver_ctx( ctx->tokpid = tokpid; ctx->ntokens = ntokens; + ctx->timeout = timeout; ctx->ctx.program = program; ctx->ctx.cctx = &ctx->cctx; ctx->cctx.uuid = &ctx->uuid; @@ -449,6 +474,16 @@ void toks_free_driver_ctx(struct toks_driver_ctx * ctx) } } +void toks_driver_set_timeout(struct toks_driver_ctx * dctx, int64_t millisecs) +{ + toks_set_driver_timeout(dctx,millisecs); +} + +void toks_driver_unset_timeout(struct toks_driver_ctx * dctx) +{ + toks_set_driver_timeout(dctx,(-1)); +} + const struct toks_source_version * toks_source_version(void) { return &toks_src_version; diff --git a/src/internal/toksvc_driver_impl.h b/src/internal/toksvc_driver_impl.h index d4d1568..cf047b9 100644 --- a/src/internal/toksvc_driver_impl.h +++ b/src/internal/toksvc_driver_impl.h @@ -28,6 +28,7 @@ enum app_tags { TAG_TOKENS, TAG_ACQUIRE, TAG_RELEASE, + TAG_TIMEOUT, TAG_PID, }; @@ -44,6 +45,7 @@ struct toks_driver_ctx_impl { struct toks_token * tokens; struct toks_waiter * waiters; struct _nt_port_keys keys; + int64_t timeout; void * hevent; void * hsvcdir; void * hpiddir; @@ -74,6 +76,20 @@ static inline nt_rtdata * toks_get_driver_rtdata(const struct toks_driver_ctx * return ictx->rtdata; } +static inline int64_t toks_get_driver_timeout(const struct toks_driver_ctx * dctx) +{ + struct toks_driver_ctx_impl * ictx; + ictx = toks_get_driver_ictx(dctx); + return ictx->timeout; +} + +static inline void toks_set_driver_timeout(const struct toks_driver_ctx * dctx, int64_t timeout) +{ + struct toks_driver_ctx_impl * ictx; + ictx = toks_get_driver_ictx(dctx); + ictx->timeout = timeout; +} + static inline void * toks_get_driver_hevent(const struct toks_driver_ctx * dctx) { struct toks_driver_ctx_impl * ictx; diff --git a/src/skin/toks_skin_default.c b/src/skin/toks_skin_default.c index 9acd139..ab625a1 100644 --- a/src/skin/toks_skin_default.c +++ b/src/skin/toks_skin_default.c @@ -39,5 +39,10 @@ const struct argv_option toks_default_options[] = { {"release", 'r',TAG_RELEASE,ARGV_OPTARG_REQUIRED,0,0,"", "release the key specified by %s."}, + {"timeout", 'm',TAG_TIMEOUT,ARGV_OPTARG_REQUIRED,0,0,"", + "set the acquire operation's timeout to %s milliseconds; " + "a timeout of zero milliseconds implies no wait at all; " + "not setting a timeout implies an indefinite wait."}, + {0,0,0,0,0,0,0,0} };