static int file_cmd_delete(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int force = Jim_CompareStringImmediate(interp, argv[0], "-force"); if (force || Jim_CompareStringImmediate(interp, argv[0], "--")) { argc++; argv--; } while (argc--) { const char *path = Jim_String(argv[0]); if (unlink(path) == -1 && errno != ENOENT) { if (rmdir(path) == -1) { /* Maybe try using the script helper */ if (!force || Jim_EvalPrefix(interp, "file delete force", 1, argv) != JIM_OK) { Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path, strerror(errno)); return JIM_ERR; } } } argv++; } return JIM_OK; }
static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { AioFile *af = Jim_CmdPrivData(interp); int orig = SEEK_SET; long offset; if (argc == 2) { if (Jim_CompareStringImmediate(interp, argv[1], "start")) orig = SEEK_SET; else if (Jim_CompareStringImmediate(interp, argv[1], "current")) orig = SEEK_CUR; else if (Jim_CompareStringImmediate(interp, argv[1], "end")) orig = SEEK_END; else { return -1; } } if (Jim_GetLong(interp, argv[0], &offset) != JIM_OK) { return JIM_ERR; } if (fseek(af->fp, offset, orig) == -1) { JimAioSetError(interp, af->filename); return JIM_ERR; } return JIM_OK; }
static int aio_cmd_puts(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { AioFile *af = Jim_CmdPrivData(interp); int wlen; const char *wdata; Jim_Obj *strObj; if (argc == 2) { if (!Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) { return -1; } strObj = argv[1]; } else { strObj = argv[0]; } wdata = Jim_GetString(strObj, &wlen); if (fwrite(wdata, 1, wlen, af->fp) == (unsigned)wlen) { if (argc == 2 || putc('\n', af->fp) != EOF) { return JIM_OK; } } JimAioSetError(interp, af->filename); return JIM_ERR; }
static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int i; int len; Jim_Obj *resultObj; Jim_Obj *objPtr; Jim_Obj **dictValuesObj; if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { /* Unset the whole array */ Jim_UnsetVariable(interp, argv[0], JIM_NONE); return JIM_OK; } objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) { return JIM_ERR; } /* Create a new object with the values which don't match */ resultObj = Jim_NewDictObj(interp, NULL, 0); for (i = 0; i < len; i += 2) { if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) { Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]); } } Jim_Free(dictValuesObj); Jim_SetVariable(interp, argv[0], resultObj); return JIM_OK; }
static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); if (!objPtr) { return JIM_OK; } if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { /* Optimise the "all" case */ if (Jim_IsList(objPtr)) { if (Jim_ListLength(interp, objPtr) % 2 != 0) { /* A list with an odd number of elements */ return JIM_ERR; } } else if (Jim_DictSize(interp, objPtr) < 0) { /* Can't be converted to a dictionary */ return JIM_ERR; } Jim_SetResult(interp, objPtr); return JIM_OK; } /* Return a list of keys and values where the keys match the pattern */ return Jim_DictValues(interp, objPtr, argv[1]); }
static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { /* How big is big enough? */ char buf[100]; time_t t; long seconds; const char *format = "%a %b %d %H:%M:%S %Z %Y"; if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) { return -1; } if (argc == 3) { format = Jim_String(argv[2]); } if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) { return JIM_ERR; } t = seconds; /*@@if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) { Jim_SetResultString(interp, "format string too long", -1); return JIM_ERR; }*/ Jim_SetResultString(interp, buf, -1); return JIM_OK; }
/* * os.wait ?-nohang? pid * * An interface to waitpid(2) * * Returns a 3 element list. * * If -nohang is specified, and the process is still alive, returns * * {0 none 0} * * If the process does not exist or has already been waited for, returns: * * {-1 error <error-description>} * * If the process exited normally, returns: * * {<pid> exit <exit-status>} * * If the process terminated on a signal, returns: * * {<pid> signal <signal-number>} * * Otherwise (core dump, stopped, continued, ...), returns: * * {<pid> other 0} */ static int Jim_PosixWaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int nohang = 0; long pid; int status; Jim_Obj *listObj; const char *type; int value; if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-nohang")) { nohang = 1; } if (argc != nohang + 2) { Jim_WrongNumArgs(interp, 1, argv, "?-nohang? pid"); return JIM_ERR; } if (Jim_GetLong(interp, argv[nohang + 1], &pid) != JIM_OK) { return JIM_ERR; } pid = waitpid(pid, &status, nohang ? WNOHANG : 0); listObj = Jim_NewListObj(interp, NULL, 0); Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, pid)); if (pid < 0) { type = "error"; value = errno; } else if (pid == 0) { type = "none"; value = 0; } else if (WIFEXITED(status)) { type = "exit"; value = WEXITSTATUS(status); } else if (WIFSIGNALED(status)) { type = "signal"; value = WTERMSIG(status); } else { type = "other"; value = 0; } Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, type, -1)); if (pid < 0) { Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, strerror(value), -1)); } else { Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value)); } Jim_SetResult(interp, listObj); return JIM_OK; }
/* *----------------------------------------------------------------------------- * * Jim_ReaddirCmd -- * Implements the rename TCL command: * readdir ?-nocomplain? dirPath * * Results: * Standard TCL result. *----------------------------------------------------------------------------- */ int Jim_ReaddirCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { const char *dirPath; DIR *dirPtr; struct dirent *entryPtr; int nocomplain = 0; if (argc == 3 && Jim_CompareStringImmediate(interp, argv[1], "-nocomplain")) { nocomplain = 1; } if (argc != 2 && !nocomplain) { Jim_WrongNumArgs(interp, 1, argv, "?-nocomplain? dirPath"); return JIM_ERR; } dirPath = Jim_String(argv[1 + nocomplain]); dirPtr = opendir(dirPath); if (dirPtr == NULL) { if (nocomplain) { return JIM_OK; } Jim_SetResultString(interp, strerror(errno), -1); return JIM_ERR; } else { Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); while ((entryPtr = readdir(dirPtr)) != NULL) { if (entryPtr->d_name[0] == '.') { if (entryPtr->d_name[1] == '\0') { continue; } if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0')) continue; } Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, entryPtr->d_name, -1)); } closedir(dirPtr); Jim_SetResult(interp, listObj); return JIM_OK; } }
int BuiltInProc::call(struct Jim_Interp * interp, int argc, Jim_Obj * const * argv) { // Check for the help command if (argc == 2 && Jim_CompareStringImmediate(interp, argv[1], "-help")) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "Usage: \"", Jim_String(argv[0]), NULL); if (strlen(args_) > 0) Jim_AppendStrings(interp, Jim_GetResult(interp), " ", args_, NULL); Jim_AppendStrings(interp, Jim_GetResult(interp), "\""); if (strlen(desc_) > 0) Jim_AppendStrings(interp, Jim_GetResult(interp), " ", desc_, NULL); return JIM_OK; } return proc_(interp, argc, argv); }
static int signal_cmd_check(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int clear = 0; jim_wide mask = 0; jim_wide blocked; if (argc > 0 && Jim_CompareStringImmediate(interp, argv[0], "-clear")) { clear++; } if (argc > clear) { int i; /* Signals specified */ for (i = clear; i < argc; i++) { int sig = find_signal_by_name(interp, Jim_String(argv[i])); if (sig < 0 || sig >= MAX_SIGNALS) { return -1; } mask |= sig_to_bit(sig); } } else { /* No signals specified, so check/clear all */ mask = ~mask; } if ((sigsblocked & mask) == 0) { /* No matching signals, so empty result and nothing to do */ return JIM_OK; } /* Be careful we don't have a race condition where signals are cleared but not returned */ blocked = sigsblocked & mask; if (clear) { sigsblocked &= ~blocked; } /* Set the result */ signal_set_sigmask_result(interp, blocked); return JIM_OK; }
static int Jim_Gzip(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { long level = Z_DEFAULT_COMPRESSION; const char *in; int len; if (argc == 3) { if (!Jim_CompareStringImmediate(interp, argv[1], "-level")) { return -1; } if (Jim_GetLong(interp, argv[2], &level) != JIM_OK) { return -1; } } else if (argc != 1) { return -1; } in = Jim_GetString(argv[0], &len); return Jim_Compress(interp, in, len, level, WBITS_GZIP); }
static int Jim_Gunzip(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { long bufsiz = DEF_DECOMPRESS_BUFSIZ; const char *in; int len; if (argc == 3) { if (!Jim_CompareStringImmediate(interp, argv[1], "-buffersize")) { return -1; } if (Jim_GetLong(interp, argv[2], &bufsiz) != JIM_OK) { return -1; } } else if (argc != 1) { return -1; } in = Jim_GetString(argv[0], &len); return Jim_Decompress(interp, in, len, bufsiz, WBITS_GZIP); }
static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { char *pt; struct tm tm; time_t now = time(0); if (!Jim_CompareStringImmediate(interp, argv[1], "-format")) { return -1; } /* Initialise with the current date/time */ localtime_r(&now, &tm); /*@@pt = strptime(Jim_String(argv[0]), Jim_String(argv[2]), &tm); if (pt == 0 || *pt != 0) { Jim_SetResultString(interp, "Failed to parse time according to format", -1); return JIM_ERR; }*/ /* Now convert into a time_t */ Jim_SetResultInt(interp, mktime(&tm)); return JIM_OK; }
static int JimNamespaceCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *nsObj; Jim_Obj *objPtr; int option; static const char * const options[] = { "eval", "current", "canonical", "qualifiers", "parent", "tail", "delete", "origin", "code", "inscope", "import", "export", "which", "upvar", NULL }; enum { OPT_EVAL, OPT_CURRENT, OPT_CANONICAL, OPT_QUALIFIERS, OPT_PARENT, OPT_TAIL, OPT_DELETE, OPT_ORIGIN, OPT_CODE, OPT_INSCOPE, OPT_IMPORT, OPT_EXPORT, OPT_WHICH, OPT_UPVAR, }; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arg ...?"); return JIM_ERR; } if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { return JIM_ERR; } switch (option) { case OPT_EVAL: if (argc < 4) { Jim_WrongNumArgs(interp, 2, argv, "name arg ?arg...?"); return JIM_ERR; } if (argc == 4) { objPtr = argv[3]; } else { objPtr = Jim_ConcatObj(interp, argc - 3, argv + 3); } nsObj = JimCanonicalNamespace(interp, interp->framePtr->nsObj, argv[2]); return Jim_EvalNamespace(interp, objPtr, nsObj); case OPT_CURRENT: if (argc != 2) { Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } Jim_SetResult(interp, JimNamespaceCurrent(interp)); return JIM_OK; case OPT_CANONICAL: if (argc > 4) { Jim_WrongNumArgs(interp, 2, argv, "?current? ?name?"); return JIM_ERR; } if (argc == 2) { Jim_SetResult(interp, interp->framePtr->nsObj); } else if (argc == 3) { Jim_SetResult(interp, JimCanonicalNamespace(interp, interp->framePtr->nsObj, argv[2])); } else { Jim_SetResult(interp, JimCanonicalNamespace(interp, argv[2], argv[3])); } return JIM_OK; case OPT_QUALIFIERS: if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "string"); return JIM_ERR; } Jim_SetResult(interp, Jim_NamespaceQualifiers(interp, argv[2])); return JIM_OK; case OPT_EXPORT: return JIM_OK; case OPT_TAIL: if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "string"); return JIM_ERR; } Jim_SetResult(interp, Jim_NamespaceTail(interp, argv[2])); return JIM_OK; case OPT_PARENT: if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "?name?"); return JIM_ERR; } else { const char *name; if (argc == 3) { objPtr = argv[2]; } else { objPtr = interp->framePtr->nsObj; } if (Jim_Length(objPtr) == 0 || Jim_CompareStringImmediate(interp, objPtr, "::")) { return JIM_OK; } objPtr = Jim_NamespaceQualifiers(interp, objPtr); name = Jim_String(objPtr); if (name[0] != ':' || name[1] != ':') { /* Make it fully scoped */ Jim_SetResultString(interp, "::", 2); Jim_AppendObj(interp, Jim_GetResult(interp), objPtr); Jim_IncrRefCount(objPtr); Jim_DecrRefCount(interp, objPtr); } else { Jim_SetResult(interp, objPtr); } } return JIM_OK; } /* Implemented as a Tcl helper proc. * Note that calling a proc will change the current namespace, * so helper procs must call [uplevel namespace canon] to get the callers * namespace. */ return Jim_EvalEnsemble(interp, "namespace", options[option], argc - 2, argv + 2); }
static int JimAioOpenCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { FILE *fp; AioFile *af; char buf[AIO_CMD_LEN]; const char *mode = "r"; Jim_Obj *objPtr; long fileId; const char *options[] = {"input", "output", "error", NULL}; enum {OPT_INPUT, OPT_OUTPUT, OPT_ERROR}; int OpenFlags = 0; int modeLen; if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?"); return JIM_ERR; } if (argc == 3) mode = Jim_GetString(argv[2], &modeLen); if (argc == 3 && Jim_CompareStringImmediate(interp, argv[1], "standard") && modeLen >= 3) { int option; if (Jim_GetEnum(interp, argv[2], options, &option, "standard channel", JIM_ERRMSG) != JIM_OK) return JIM_ERR; OpenFlags |= AIO_KEEPOPEN; switch (option) { case OPT_INPUT: fp = stdin; break; case OPT_OUTPUT: fp = stdout; break; case OPT_ERROR: fp = stderr; break; default: fp = NULL; Jim_Panic(interp,"default reached in JimAioOpenCommand()"); break; } } else { fp = fopen(Jim_GetString(argv[1], NULL), mode); if (fp == NULL) { JimAioSetError(interp); return JIM_ERR; } } /* Get the next file id */ if (Jim_EvalGlobal(interp, "if {[catch {incr aio.fileId}]} {set aio.fileId 0}") != JIM_OK) return JIM_ERR; objPtr = Jim_GetGlobalVariableStr(interp, "aio.fileId", JIM_ERRMSG); if (objPtr == NULL) return JIM_ERR; if (Jim_GetLong(interp, objPtr, &fileId) != JIM_OK) return JIM_ERR; /* Create the file command */ af = Jim_Alloc(sizeof(*af)); af->fp = fp; af->fd = fileno(fp); af->flags = fcntl(af->fd,F_GETFL); af->OpenFlags = OpenFlags; // fprintf(stderr,"hallo\n"); af->rEvent = NULL; af->wEvent = NULL; af->eEvent = NULL; sprintf(buf, "aio.handle%ld", fileId); Jim_CreateCommand(interp, buf, JimAioHandlerCommand, af, JimAioDelProc); Jim_SetResultString(interp, buf, -1); return JIM_OK; }
/* Calls to [aio.file] create commands that are implemented by this * C command. */ static int JimAioHandlerCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { AioFile *af = Jim_CmdPrivData(interp); int option; const char *options[] = { "close", "seek", "tell", "gets", "read", "puts", "flush", "eof", "ndelay", "readable", "writable", "onexception", "accept", NULL }; enum {OPT_CLOSE, OPT_SEEK, OPT_TELL, OPT_GETS, OPT_READ, OPT_PUTS, OPT_FLUSH, OPT_EOF, OPT_NDELAY, OPT_READABLE, OPT_WRITABLE, OPT_EXCEPTION, OPT_ACCEPT }; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "method ?args ...?"); return JIM_ERR; } if (Jim_GetEnum(interp, argv[1], options, &option, "AIO method", JIM_ERRMSG) != JIM_OK) return JIM_ERR; /* CLOSE */ if (option == OPT_CLOSE) { if (argc != 2) { Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } Jim_DeleteCommand(interp, Jim_GetString(argv[0], NULL)); return JIM_OK; } else if (option == OPT_SEEK) { /* SEEK */ int orig = SEEK_SET; long offset; if (argc != 3 && argc != 4) { Jim_WrongNumArgs(interp, 2, argv, "offset ?origin?"); return JIM_ERR; } if (argc == 4) { if (Jim_CompareStringImmediate(interp, argv[3], "start")) orig = SEEK_SET; else if (Jim_CompareStringImmediate(interp, argv[3], "current")) orig = SEEK_CUR; else if (Jim_CompareStringImmediate(interp, argv[3], "end")) orig = SEEK_END; else { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "bad origin \"", Jim_GetString(argv[3], NULL), "\" must be: start, current, or end", NULL); return JIM_ERR; } } if (Jim_GetLong(interp, argv[2], &offset) != JIM_OK) return JIM_ERR; if (fseek(af->fp, offset, orig) == -1) { JimAioSetError(interp); return JIM_ERR; } return JIM_OK; } else if (option == OPT_TELL) { /* TELL */ long position; if (argc != 2) { Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } position = ftell(af->fp); Jim_SetResult(interp, Jim_NewIntObj(interp, position)); return JIM_OK; } else if (option == OPT_GETS) { /* GETS */ char buf[AIO_BUF_LEN]; Jim_Obj *objPtr; if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "?varName?"); return JIM_ERR; } objPtr = Jim_NewStringObj(interp, NULL, 0); while (1) { int more = 0; buf[AIO_BUF_LEN-1] = '_'; if (fgets(buf, AIO_BUF_LEN, af->fp) == NULL) break; if (buf[AIO_BUF_LEN-1] == '\0' && buf[AIO_BUF_LEN-2] != '\n') more = 1; if (more) { Jim_AppendString(interp, objPtr, buf, AIO_BUF_LEN-1); } else { /* strip "\n" */ Jim_AppendString(interp, objPtr, buf, strlen(buf)-1); } if (!more) break; } if (ferror(af->fp) && (errno != EAGAIN)) { /* I/O error */ Jim_IncrRefCount(objPtr); Jim_DecrRefCount(interp, objPtr); JimAioSetError(interp); return JIM_ERR; } /* On EOF returns -1 if varName was specified, or the empty string. */ if (feof(af->fp) && Jim_Length(objPtr) == 0) { Jim_IncrRefCount(objPtr); Jim_DecrRefCount(interp, objPtr); if (argc == 3) Jim_SetResult(interp, Jim_NewIntObj(interp, -1)); return JIM_OK; } if (argc == 3) { int totLen; Jim_GetString(objPtr, &totLen); if (Jim_SetVariable(interp, argv[2], objPtr) != JIM_OK) { Jim_IncrRefCount(objPtr); Jim_DecrRefCount(interp, objPtr); return JIM_ERR; } Jim_SetResult(interp, Jim_NewIntObj(interp, totLen)); } else { Jim_SetResult(interp, objPtr); } return JIM_OK; } else if (option == OPT_READ) { /* READ */ char buf[AIO_BUF_LEN]; Jim_Obj *objPtr; int nonewline = 0; int neededLen = -1; /* -1 is "read as much as possible" */ if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "?-nonewline? ?len?"); return JIM_ERR; } if (argc == 3 && Jim_CompareStringImmediate(interp, argv[2], "-nonewline")) { nonewline = 1; argv++; argc--; } if (argc == 3) { jim_wide wideValue; if (Jim_GetWide(interp, argv[2], &wideValue) != JIM_OK) return JIM_ERR; if (wideValue < 0) { Jim_SetResultString(interp, "invalid parameter: negative len", -1); return JIM_ERR; } neededLen = (int) wideValue; } objPtr = Jim_NewStringObj(interp, NULL, 0); while (neededLen != 0) { int retval; int readlen; if (neededLen == -1) { readlen = AIO_BUF_LEN; } else { readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen); } retval = fread(buf, 1, readlen, af->fp); if (retval > 0) { Jim_AppendString(interp, objPtr, buf, retval); if (neededLen != -1) { neededLen -= retval; } } if (retval != readlen) break; } /* Check for error conditions */ if (ferror(af->fp)) { /* I/O error */ Jim_FreeNewObj(interp, objPtr); JimAioSetError(interp); return JIM_ERR; } if (nonewline) { int len; const char *s = Jim_GetString(objPtr, &len); if (len > 0 && s[len-1] == '\n') { objPtr->length--; objPtr->bytes[objPtr->length] = '\0'; } } Jim_SetResult(interp, objPtr); return JIM_OK; } else if (option == OPT_PUTS) { /* PUTS */ int wlen; const char *wdata; if (argc != 3 && (argc != 4 || !Jim_CompareStringImmediate( interp, argv[2], "-nonewline"))) { Jim_WrongNumArgs(interp, 2, argv, "?-nonewline? string"); return JIM_ERR; } wdata = Jim_GetString(argv[2+(argc==4)], &wlen); if (fwrite(wdata, 1, wlen, af->fp) != (unsigned)wlen || (argc == 3 && fwrite("\n", 1, 1, af->fp) != 1)) { JimAioSetError(interp); return JIM_ERR; } return JIM_OK; } else if (option == OPT_FLUSH) { /* FLUSH */ if (argc != 2) { Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } if (fflush(af->fp) == EOF) { JimAioSetError(interp); return JIM_ERR; } return JIM_OK; } else if (option == OPT_EOF) { /* EOF */ if (argc != 2) { Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } Jim_SetResult(interp, Jim_NewIntObj(interp, feof(af->fp))); return JIM_OK; } else if (option == OPT_NDELAY) { #ifdef O_NDELAY int fmode = af->flags; if (argc == 3) { jim_wide wideValue; if (Jim_GetWide(interp, argv[2], &wideValue) != JIM_OK) return JIM_ERR; switch (wideValue) { case 0: fmode &= ~O_NDELAY; break ; case 1: fmode |= O_NDELAY; break ; } fcntl(af->fd,F_SETFL,fmode); af->flags = fmode; } Jim_SetResult(interp, Jim_NewIntObj(interp, (fmode & O_NONBLOCK)?1:0)); return JIM_OK; #else return JIM_ERR; #endif } else if ( (option == OPT_READABLE) || (option == OPT_WRITABLE) || (option == OPT_EXCEPTION) ) { int mask = 0; Jim_Obj **scrListObjpp = NULL; Jim_Obj *listObj; const char *dummy = NULL; int scrlen = 0; if (!(Jim_CreateFileHandler && Jim_DeleteFileHandler)) { Jim_SetResultString(interp, "Eventloop not present ( or loaded too late ) !", -1); return JIM_ERR; } switch (option) { case OPT_READABLE: mask = JIM_EVENT_READABLE; scrListObjpp = &af->rEvent; if (argc == 4) mask |= JIM_EVENT_FEOF ; break; case OPT_WRITABLE: mask = JIM_EVENT_WRITABLE; scrListObjpp = &af->wEvent; break; case OPT_EXCEPTION: mask = JIM_EVENT_EXCEPTION; scrListObjpp = &af->eEvent; break; } switch (argc) { case 4: case 3: if (*scrListObjpp) { Jim_DeleteFileHandler(interp, af->fp); //,mask); Jim_DecrRefCount(interp, *scrListObjpp); *scrListObjpp = NULL; } if ( dummy = Jim_GetString(argv[2],&scrlen),(scrlen == 0)) { break; } else { *scrListObjpp = Jim_NewListObj(interp, NULL, 0); Jim_IncrRefCount(*scrListObjpp); // fprintf(stderr,"0 %p \n",*scrListObjpp); listObj = argv[2]; if (Jim_IsShared(listObj)) listObj = Jim_DuplicateObj(interp, listObj); // Jim_IncrRefCount(listObj); // fprintf(stderr,"script:\"%s\" argp: %p objp1: %p\n", Jim_GetString(argv[2], NULL),argv[2],listObj); // fprintf(stderr,"1"); Jim_ListAppendElement(interp,*scrListObjpp,listObj); // fprintf(stderr,"2"); if (mask & JIM_EVENT_FEOF) { listObj = argv[3]; if (Jim_IsShared(listObj)) listObj = Jim_DuplicateObj(interp, listObj); // Jim_IncrRefCount(listObj); // fprintf(stderr,"script:\"%s\" argp: %p objp2: %p\n", Jim_GetString(argv[3], NULL),argv[3],listObj); // fprintf(stderr,"3"); Jim_ListAppendElement(interp,*scrListObjpp,listObj); // fprintf(stderr,"4"); } // fprintf(stderr,"event readable fd: %d, script:\"%s\" objp3: %p\n",af->fd, Jim_GetString(argv[2], NULL),argv[2]); Jim_IncrRefCount(*scrListObjpp); // fprintf(stderr,"6 %p \n",Jim_CreateFileHandler); Jim_CreateFileHandler(interp, af->fp, mask, JimAioFileEventHandler, *scrListObjpp, JimAioFileEventFinalizer); // fprintf(stderr,"7"); } break; case 2: if (*scrListObjpp) Jim_SetResult(interp,*scrListObjpp); return JIM_OK; default: Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } } else if (option == OPT_ACCEPT) { int ret; fprintf(stderr,"ACCEPT\n"); ret = JimAioAcceptHelper(interp,af); fprintf(stderr,"ret %d\n",ret); return (ret); } return JIM_OK; }
/* * The main [exec] command */ static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { fdtype outputId; /* File id for output pipe. -1 * means command overrode. */ fdtype errorId; /* File id for temporary file * containing error output. */ pidtype *pidPtr; int numPids, result; /* * See if the command is to be run in background; if so, create * the command, detach it, and return. */ if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) { Jim_Obj *listObj; int i; argc--; numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL); if (numPids < 0) { return JIM_ERR; } /* The return value is a list of the pids */ listObj = Jim_NewListObj(interp, NULL, 0); for (i = 0; i < numPids; i++) { Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i])); } Jim_SetResult(interp, listObj); JimDetachPids(interp, numPids, pidPtr); Jim_Free(pidPtr); return JIM_OK; } /* * Create the command's pipeline. */ numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, &outputId, &errorId); if (numPids < 0) { return JIM_ERR; } /* * Read the child's output (if any) and put it into the result. */ Jim_SetResultString(interp, "", 0); result = JIM_OK; if (outputId != JIM_BAD_FD) { result = JimAppendStreamToString(interp, outputId, Jim_GetResult(interp)); if (result < 0) { Jim_SetResultErrno(interp, "error reading from output pipe"); } } if (JimCleanupChildren(interp, numPids, pidPtr, errorId) != JIM_OK) { result = JIM_ERR; } return result; }
/* Syslog_Log - * implements syslog tcl command. General format: syslog ?options? level text * options -facility -ident -options * * syslog ?-facility cron|daemon|...? ?-ident string? ?-options int? ?debug|info|...? text */ int Jim_SyslogCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int priority = LOG_INFO; int i = 1; SyslogInfo *info = Jim_CmdPrivData(interp); if (argc <= 1) { wrongargs: Jim_WrongNumArgs(interp, 1, argv, "?-facility cron|daemon|...? ?-ident string? ?-options int? ?debug|info|...? message"); return JIM_ERR; } while (i < argc - 1) { if (Jim_CompareStringImmediate(interp, argv[i], "-facility")) { int entry = Jim_FindByName(Jim_String(argv[i + 1]), facilities, sizeof(facilities) / sizeof(*facilities)); if (entry < 0) { Jim_SetResultString(interp, "Unknown facility", -1); return JIM_ERR; } if (info->facility != entry) { info->facility = entry; if (info->logOpened) { closelog(); info->logOpened = 0; } } } else if (Jim_CompareStringImmediate(interp, argv[i], "-options")) { long tmp; if (Jim_GetLong(interp, argv[i + 1], &tmp) == JIM_ERR) { return JIM_ERR; } info->options = tmp; if (info->logOpened) { closelog(); info->logOpened = 0; } } else if (Jim_CompareStringImmediate(interp, argv[i], "-ident")) { strncpy(info->ident, Jim_String(argv[i + 1]), sizeof(info->ident)); info->ident[sizeof(info->ident) - 1] = 0; if (info->logOpened) { closelog(); info->logOpened = 0; } } else { break; } i += 2; } /* There should be either 0, 1 or 2 args left */ if (i == argc) { /* No args, but they have set some options, so OK */ return JIM_OK; } if (i < argc - 1) { priority = Jim_FindByName(Jim_String(argv[i]), priorities, sizeof(priorities) / sizeof(*priorities)); if (priority < 0) { Jim_SetResultString(interp, "Unknown priority", -1); return JIM_ERR; } i++; } if (i != argc - 1) { goto wrongargs; } if (!info->logOpened) { if (!info->ident[0]) { Jim_Obj *argv0 = Jim_GetGlobalVariableStr(interp, "argv0", JIM_NONE); if (argv0) { strncpy(info->ident, Jim_String(argv0), sizeof(info->ident)); } else { strcpy(info->ident, "Tcl script"); } info->ident[sizeof(info->ident) - 1] = 0; } openlog(info->ident, info->options, info->facility); info->logOpened = 1; } syslog(priority, "%s", Jim_String(argv[i])); return JIM_OK; }
/* Calls to [sqlite.open] create commands that are implemented by this * C command. */ static int JimSqliteHandlerCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { sqlite3 *db = Jim_CmdPrivData(interp); int option; static const char * const options[] = { "close", "query", "lastid", "changes", NULL }; enum { OPT_CLOSE, OPT_QUERY, OPT_LASTID, OPT_CHANGES }; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "method ?args ...?"); return JIM_ERR; } if (Jim_GetEnum(interp, argv[1], options, &option, "Sqlite method", JIM_ERRMSG) != JIM_OK) return JIM_ERR; /* CLOSE */ if (option == OPT_CLOSE) { if (argc != 2) { Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } Jim_DeleteCommand(interp, Jim_String(argv[0])); return JIM_OK; } else if (option == OPT_QUERY) { /* QUERY */ Jim_Obj *objPtr, *rowsListPtr; sqlite3_stmt *stmt; const char *query, *tail; int columns, rows, len; int retcode = JIM_ERR; Jim_Obj *nullStrObj; if (argc >= 4 && Jim_CompareStringImmediate(interp, argv[2], "-null")) { nullStrObj = argv[3]; argv += 2; argc -= 2; } else { nullStrObj = Jim_NewEmptyStringObj(interp); } Jim_IncrRefCount(nullStrObj); if (argc < 3) { Jim_WrongNumArgs(interp, 2, argv, "query ?args?"); goto err; } objPtr = JimSqliteFormatQuery(interp, argv[2], argc - 3, argv + 3); if (objPtr == NULL) { return JIM_ERR; } query = Jim_GetString(objPtr, &len); Jim_IncrRefCount(objPtr); /* Compile the query into VM code */ if (sqlite3_prepare_v2(db, query, len, &stmt, &tail) != SQLITE_OK) { Jim_DecrRefCount(interp, objPtr); Jim_SetResultString(interp, sqlite3_errmsg(db), -1); goto err; } Jim_DecrRefCount(interp, objPtr); /* query no longer needed. */ /* Build a list of rows (that are lists in turn) */ rowsListPtr = Jim_NewListObj(interp, NULL, 0); Jim_IncrRefCount(rowsListPtr); rows = 0; columns = sqlite3_column_count(stmt); while (sqlite3_step(stmt) == SQLITE_ROW) { int i; objPtr = Jim_NewListObj(interp, NULL, 0); for (i = 0; i < columns; i++) { Jim_Obj *vObj = NULL; Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, sqlite3_column_name(stmt, i), -1)); switch (sqlite3_column_type(stmt, i)) { case SQLITE_NULL: vObj = nullStrObj; break; case SQLITE_INTEGER: vObj = Jim_NewIntObj(interp, sqlite3_column_int(stmt, i)); break; case SQLITE_FLOAT: vObj = Jim_NewDoubleObj(interp, sqlite3_column_double(stmt, i)); break; case SQLITE_TEXT: case SQLITE_BLOB: vObj = Jim_NewStringObj(interp, sqlite3_column_blob(stmt, i), sqlite3_column_bytes(stmt, i)); break; } Jim_ListAppendElement(interp, objPtr, vObj); } Jim_ListAppendElement(interp, rowsListPtr, objPtr); rows++; } /* Finalize */ if (sqlite3_finalize(stmt) != SQLITE_OK) { Jim_SetResultString(interp, sqlite3_errmsg(db), -1); } else { Jim_SetResult(interp, rowsListPtr); retcode = JIM_OK; } Jim_DecrRefCount(interp, rowsListPtr); err: Jim_DecrRefCount(interp, nullStrObj); return retcode; } else if (option == OPT_LASTID) { if (argc != 2) { Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } Jim_SetResult(interp, Jim_NewIntObj(interp, sqlite3_last_insert_rowid(db))); return JIM_OK; } else if (option == OPT_CHANGES) { if (argc != 2) { Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } Jim_SetResult(interp, Jim_NewIntObj(interp, sqlite3_changes(db))); return JIM_OK; } return JIM_OK; }
static int JimAioSockCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { const char *hdlfmt = "aio.unknown%ld"; const char *socktypes[] = { "unix", "unix.server", "dgram", "dgram.server", "stream", "stream.server", "pipe", NULL }; enum { SOCK_UNIX, SOCK_UNIX_SERVER, SOCK_DGRAM_CLIENT, SOCK_DGRAM_SERVER, SOCK_STREAM_CLIENT, SOCK_STREAM_SERVER, SOCK_STREAM_PIPE, SOCK_DGRAM6_CLIENT, SOCK_DGRAM6_SERVER, SOCK_STREAM6_CLIENT, SOCK_STREAM6_SERVER, }; int socktype; int sock; const char *hostportarg = NULL; int res; int on = 1; const char *mode = "r+"; int family = PF_INET; Jim_Obj *argv0 = argv[0]; int ipv6 = 0; if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-ipv6")) { if (!IPV6) { Jim_SetResultString(interp, "ipv6 not supported", -1); return JIM_ERR; } ipv6 = 1; family = PF_INET6; } argc -= ipv6; argv += ipv6; if (argc < 2) { wrongargs: Jim_WrongNumArgs(interp, 1, &argv0, "?-ipv6? type ?address?"); return JIM_ERR; } if (Jim_GetEnum(interp, argv[1], socktypes, &socktype, "socket type", JIM_ERRMSG) != JIM_OK) return JIM_ERR; Jim_SetEmptyResult(interp); hdlfmt = "aio.sock%ld"; if (argc > 2) { hostportarg = Jim_String(argv[2]); } switch (socktype) { case SOCK_DGRAM_CLIENT: if (argc == 2) { /* No address, so an unconnected dgram socket */ sock = socket(family, SOCK_DGRAM, 0); if (sock < 0) { JimAioSetError(interp, NULL); return JIM_ERR; } break; } /* fall through */ case SOCK_STREAM_CLIENT: { union sockaddr_any sa; int salen; if (argc != 3) { goto wrongargs; } if (ipv6) { if (JimParseIPv6Address(interp, hostportarg, &sa, &salen) != JIM_OK) { return JIM_ERR; } } else if (JimParseIpAddress(interp, hostportarg, &sa, &salen) != JIM_OK) { return JIM_ERR; } sock = socket(family, (socktype == SOCK_DGRAM_CLIENT) ? SOCK_DGRAM : SOCK_STREAM, 0); if (sock < 0) { JimAioSetError(interp, NULL); return JIM_ERR; } res = connect(sock, &sa.sa, salen); if (res) { JimAioSetError(interp, argv[2]); close(sock); return JIM_ERR; } } break; case SOCK_STREAM_SERVER: case SOCK_DGRAM_SERVER: { union sockaddr_any sa; int salen; if (argc != 3) { goto wrongargs; } if (ipv6) { if (JimParseIPv6Address(interp, hostportarg, &sa, &salen) != JIM_OK) { return JIM_ERR; } } else if (JimParseIpAddress(interp, hostportarg, &sa, &salen) != JIM_OK) { return JIM_ERR; } sock = socket(family, (socktype == SOCK_DGRAM_SERVER) ? SOCK_DGRAM : SOCK_STREAM, 0); if (sock < 0) { JimAioSetError(interp, NULL); return JIM_ERR; } /* Enable address reuse */ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); res = bind(sock, &sa.sa, salen); if (res) { JimAioSetError(interp, argv[2]); close(sock); return JIM_ERR; } if (socktype == SOCK_STREAM_SERVER) { res = listen(sock, 5); if (res) { JimAioSetError(interp, NULL); close(sock); return JIM_ERR; } } hdlfmt = "aio.socksrv%ld"; } break; #ifdef HAVE_SYS_UN_H case SOCK_UNIX: { struct sockaddr_un sa; socklen_t len; if (argc != 3 || ipv6) { goto wrongargs; } if (JimParseDomainAddress(interp, hostportarg, &sa) != JIM_OK) { JimAioSetError(interp, argv[2]); return JIM_ERR; } family = PF_UNIX; sock = socket(PF_UNIX, SOCK_STREAM, 0); if (sock < 0) { JimAioSetError(interp, NULL); return JIM_ERR; } len = strlen(sa.sun_path) + 1 + sizeof(sa.sun_family); res = connect(sock, (struct sockaddr *)&sa, len); if (res) { JimAioSetError(interp, argv[2]); close(sock); return JIM_ERR; } hdlfmt = "aio.sockunix%ld"; break; } case SOCK_UNIX_SERVER: { struct sockaddr_un sa; socklen_t len; if (argc != 3 || ipv6) { goto wrongargs; } if (JimParseDomainAddress(interp, hostportarg, &sa) != JIM_OK) { JimAioSetError(interp, argv[2]); return JIM_ERR; } family = PF_UNIX; sock = socket(PF_UNIX, SOCK_STREAM, 0); if (sock < 0) { JimAioSetError(interp, NULL); return JIM_ERR; } len = strlen(sa.sun_path) + 1 + sizeof(sa.sun_family); res = bind(sock, (struct sockaddr *)&sa, len); if (res) { JimAioSetError(interp, argv[2]); close(sock); return JIM_ERR; } res = listen(sock, 5); if (res) { JimAioSetError(interp, NULL); close(sock); return JIM_ERR; } hdlfmt = "aio.sockunixsrv%ld"; break; } #endif #ifdef HAVE_PIPE case SOCK_STREAM_PIPE: { int p[2]; if (argc != 2 || ipv6) { goto wrongargs; } if (pipe(p) < 0) { JimAioSetError(interp, NULL); return JIM_ERR; } if (JimMakeChannel(interp, NULL, p[0], argv[1], "aio.pipe%ld", 0, "r") == JIM_OK) { Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); if (JimMakeChannel(interp, NULL, p[1], argv[1], "aio.pipe%ld", 0, "w") == JIM_OK) { Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); Jim_SetResult(interp, objPtr); return JIM_OK; } } /* Can only be here if fdopen() failed */ close(p[0]); close(p[1]); JimAioSetError(interp, NULL); return JIM_ERR; } break; #endif default: Jim_SetResultString(interp, "Unsupported socket type", -1); return JIM_ERR; } return JimMakeChannel(interp, NULL, sock, argv[1], hdlfmt, family, mode); }
int BuiltInSubProc::call(struct Jim_Interp * interp, int argc, Jim_Obj * const * argv) { bool help = false; const char * cmdName = Jim_String(argv[0]); if (argc < 2) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "wrong # args: should be \"", cmdName, " command ...\"\n", NULL); Jim_AppendStrings(interp, Jim_GetResult(interp), "Use \"", cmdName, " -help ?command?\" for help about the command", NULL); return JIM_ERR; } Jim_Obj * cmd = argv[1]; // Check for the help command if (Jim_CompareStringImmediate(interp, cmd, "-help")) { if (argc == 2) { showCommandUsage(interp, argc, argv, subCommands_); return JIM_OK; } help = true; cmd = argv[2]; } // Check for special builtin '-commands' command first if (Jim_CompareStringImmediate(interp, cmd, "-commands")) { /* Build the result here */ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); addSubCommands(interp, subCommands_, " "); return JIM_OK; } for (int i = 0; i < subCommands_.size() / 3; ++i) { if (Jim_CompareStringImmediate(interp, cmd, subCommands_[i * 3])) { if (help) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "Usage: \"", cmdName, " ", subCommands_[i * 3], NULL); if (strlen(subCommands_[i * 3 + 1]) > 0) Jim_AppendStrings(interp, Jim_GetResult(interp), " ", subCommands_[i * 3 + 1], NULL); Jim_AppendStrings(interp, Jim_GetResult(interp), "\""); if (strlen(subCommands_[i * 3 + 2]) > 0) Jim_AppendStrings(interp, Jim_GetResult(interp), " ", subCommands_[i * 3 + 2], NULL); return JIM_OK; } else { return proc_(interp, i, argc - 2, argv + 2); } } } Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), cmdName, ", unknown command \"", Jim_String(cmd), "\" should be one of: ", NULL); addSubCommands(interp, subCommands_, ", "); return JIM_ERR; }
static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { AioFile *af = Jim_CmdPrivData(interp); char buf[AIO_BUF_LEN]; Jim_Obj *objPtr; int nonewline = 0; int neededLen = -1; /* -1 is "read as much as possible" */ if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) { nonewline = 1; argv++; argc--; } if (argc == 1) { jim_wide wideValue; if (Jim_GetWide(interp, argv[0], &wideValue) != JIM_OK) return JIM_ERR; if (wideValue < 0) { Jim_SetResultString(interp, "invalid parameter: negative len", -1); return JIM_ERR; } neededLen = (int)wideValue; } else if (argc) { return -1; } objPtr = Jim_NewStringObj(interp, NULL, 0); while (neededLen != 0) { int retval; int readlen; if (neededLen == -1) { readlen = AIO_BUF_LEN; } else { readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen); } retval = fread(buf, 1, readlen, af->fp); if (retval > 0) { Jim_AppendString(interp, objPtr, buf, retval); if (neededLen != -1) { neededLen -= retval; } } if (retval != readlen) break; } /* Check for error conditions */ if (JimCheckStreamError(interp, af)) { Jim_FreeNewObj(interp, objPtr); return JIM_ERR; } if (nonewline) { int len; const char *s = Jim_GetString(objPtr, &len); if (len > 0 && s[len - 1] == '\n') { objPtr->length--; objPtr->bytes[objPtr->length] = '\0'; } } Jim_SetResult(interp, objPtr); return JIM_OK; }
/* Calls to [aio.file] create commands that are implemented by this * C command. */ static int JimAioHandlerCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { AioFile *af = Jim_CmdPrivData(interp); int option; const char *options[] = { "close", "seek", "tell", "gets", "read", "puts", "flush", "eof", NULL }; enum {OPT_CLOSE, OPT_SEEK, OPT_TELL, OPT_GETS, OPT_READ, OPT_PUTS, OPT_FLUSH, OPT_EOF }; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "method ?args ...?"); return JIM_ERR; } if (Jim_GetEnum(interp, argv[1], options, &option, "AIO method", JIM_ERRMSG) != JIM_OK) return JIM_ERR; /* CLOSE */ if (option == OPT_CLOSE) { if (argc != 2) { Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } Jim_DeleteCommand(interp, Jim_GetString(argv[0], NULL)); return JIM_OK; } else if (option == OPT_SEEK) { /* SEEK */ int orig = SEEK_SET; long offset; if (argc != 3 && argc != 4) { Jim_WrongNumArgs(interp, 2, argv, "offset ?origin?"); return JIM_ERR; } if (argc == 4) { if (Jim_CompareStringImmediate(interp, argv[3], "start")) orig = SEEK_SET; else if (Jim_CompareStringImmediate(interp, argv[3], "current")) orig = SEEK_CUR; else if (Jim_CompareStringImmediate(interp, argv[3], "end")) orig = SEEK_END; else { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "bad origin \"", Jim_GetString(argv[3], NULL), "\" must be: start, current, or end", NULL); return JIM_ERR; } } if (Jim_GetLong(interp, argv[2], &offset) != JIM_OK) return JIM_ERR; if (fseek(af->fp, offset, orig) == -1) { JimAioSetError(interp); return JIM_ERR; } return JIM_OK; } else if (option == OPT_TELL) { /* TELL */ long position; if (argc != 2) { Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } position = ftell(af->fp); Jim_SetResult(interp, Jim_NewIntObj(interp, position)); return JIM_OK; } else if (option == OPT_GETS) { /* GETS */ char buf[AIO_BUF_LEN]; Jim_Obj *objPtr; if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "?varName?"); return JIM_ERR; } objPtr = Jim_NewStringObj(interp, NULL, 0); while (1) { int more = 0; buf[AIO_BUF_LEN-1] = '_'; if (fgets(buf, AIO_BUF_LEN, af->fp) == NULL) break; if (buf[AIO_BUF_LEN-1] == '\0' && buf[AIO_BUF_LEN] == '\n') more = 1; if (more) { Jim_AppendString(interp, objPtr, buf, AIO_BUF_LEN-1); } else { /* strip "\n" */ Jim_AppendString(interp, objPtr, buf, strlen(buf)-1); } if (!more) break; } if (ferror(af->fp)) { /* I/O error */ Jim_IncrRefCount(objPtr); Jim_DecrRefCount(interp, objPtr); JimAioSetError(interp); return JIM_ERR; } /* On EOF returns -1 if varName was specified, or the empty string. */ if (feof(af->fp) && Jim_Length(objPtr) == 0) { Jim_IncrRefCount(objPtr); Jim_DecrRefCount(interp, objPtr); if (argc == 3) Jim_SetResult(interp, Jim_NewIntObj(interp, -1)); return JIM_OK; } if (argc == 3) { int totLen; Jim_GetString(objPtr, &totLen); if (Jim_SetVariable(interp, argv[2], objPtr) != JIM_OK) { Jim_IncrRefCount(objPtr); Jim_DecrRefCount(interp, objPtr); return JIM_ERR; } Jim_SetResult(interp, Jim_NewIntObj(interp, totLen)); } else { Jim_SetResult(interp, objPtr); } return JIM_OK; } else if (option == OPT_READ) { /* READ */ char buf[AIO_BUF_LEN]; Jim_Obj *objPtr; int nonewline = 0; int neededLen = -1; /* -1 is "read as much as possible" */ if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "?-nonewline? ?len?"); return JIM_ERR; } if (argc == 3 && Jim_CompareStringImmediate(interp, argv[2], "-nonewline")) { nonewline = 1; argv++; argc--; } if (argc == 3) { jim_wide wideValue; if (Jim_GetWide(interp, argv[2], &wideValue) != JIM_OK) return JIM_ERR; if (wideValue < 0) { Jim_SetResultString(interp, "invalid parameter: negative len", -1); return JIM_ERR; } neededLen = (int) wideValue; } objPtr = Jim_NewStringObj(interp, NULL, 0); while (neededLen != 0) { int retval; int readlen; if (neededLen == -1) { readlen = AIO_BUF_LEN; } else { readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen); } retval = fread(buf, 1, readlen, af->fp); if (retval > 0) { Jim_AppendString(interp, objPtr, buf, retval); if (neededLen != -1) { neededLen -= retval; } } if (retval != readlen) break; } /* Check for error conditions */ if (ferror(af->fp)) { /* I/O error */ Jim_FreeNewObj(interp, objPtr); JimAioSetError(interp); return JIM_ERR; } if (nonewline) { int len; const char *s = Jim_GetString(objPtr, &len); if (len > 0 && s[len-1] == '\n') { objPtr->length--; objPtr->bytes[objPtr->length] = '\0'; } } Jim_SetResult(interp, objPtr); return JIM_OK; } else if (option == OPT_PUTS) { /* PUTS */ int wlen; const char *wdata; if (argc != 3 && (argc != 4 || !Jim_CompareStringImmediate( interp, argv[2], "-nonewline"))) { Jim_WrongNumArgs(interp, 2, argv, "?-nonewline? string"); return JIM_ERR; } wdata = Jim_GetString(argv[2+(argc==4)], &wlen); if (fwrite(wdata, 1, wlen, af->fp) != (unsigned)wlen || (argc == 3 && fwrite("\n", 1, 1, af->fp) != 1)) { JimAioSetError(interp); return JIM_ERR; } return JIM_OK; } else if (option == OPT_FLUSH) { /* FLUSH */ if (argc != 2) { Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } if (fflush(af->fp) == EOF) { JimAioSetError(interp); return JIM_ERR; } return JIM_OK; } else if (option == OPT_EOF) { /* EOF */ if (argc != 2) { Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } Jim_SetResult(interp, Jim_NewIntObj(interp, feof(af->fp))); return JIM_OK; } return JIM_OK; }
const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc, Jim_Obj *const *argv) { const jim_subcmd_type *ct; const jim_subcmd_type *partial = 0; int cmdlen; Jim_Obj *cmd; const char *cmdstr; const char *cmdname; int help = 0; cmdname = Jim_String(argv[0]); if (argc < 2) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "wrong # args: should be \"", cmdname, " command ...\"\n", NULL); Jim_AppendStrings(interp, Jim_GetResult(interp), "Use \"", cmdname, " -help ?command?\" for help", NULL); return 0; } cmd = argv[1]; /* Check for the help command */ if (Jim_CompareStringImmediate(interp, cmd, "-help")) { if (argc == 2) { /* Usage for the command, not the subcommand */ show_cmd_usage(interp, command_table, argc, argv); return &dummy_subcmd; } help = 1; /* Skip the 'help' command */ cmd = argv[2]; } /* Check for special builtin '-commands' command first */ if (Jim_CompareStringImmediate(interp, cmd, "-commands")) { /* Build the result here */ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); add_commands(interp, command_table, " "); return &dummy_subcmd; } cmdstr = Jim_GetString(cmd, &cmdlen); for (ct = command_table; ct->cmd; ct++) { if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) { /* Found an exact match */ break; } if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) { if (partial) { /* Ambiguous */ if (help) { /* Just show the top level help here */ show_cmd_usage(interp, command_table, argc, argv); return &dummy_subcmd; } bad_subcmd(interp, command_table, "ambiguous", argv[0], argv[1 + help]); return 0; } partial = ct; } continue; } /* If we had an unambiguous partial match */ if (partial && !ct->cmd) { ct = partial; } if (!ct->cmd) { /* No matching command */ if (help) { /* Just show the top level help here */ show_cmd_usage(interp, command_table, argc, argv); return &dummy_subcmd; } bad_subcmd(interp, command_table, "unknown", argv[0], argv[1 + help]); return 0; } if (help) { Jim_SetResultString(interp, "Usage: ", -1); /* subcmd */ add_cmd_usage(interp, ct, argv[0]); return &dummy_subcmd; } /* Check the number of args */ if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) { Jim_SetResultString(interp, "wrong # args: should be \"", -1); /* subcmd */ add_cmd_usage(interp, ct, argv[0]); Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); return 0; } /* Good command */ return ct; }