예제 #1
0
/* This extension is not dynamically loaded, instead it's linked statically,
   which is why we shouldn't use the unspecific 'Jim_OnLoad' name */
int Jim_EventLoopOnLoad(Jim_Interp *interp)
{
    Jim_EventLoop *eventLoop;

    Jim_InitExtension(interp);
    if (Jim_PackageProvide(interp, "eventloop", "1.0", JIM_ERRMSG) != JIM_OK)
        return JIM_ERR;

    eventLoop = Jim_Alloc(sizeof(*eventLoop));
    eventLoop->fileEventHead = NULL;
    eventLoop->timeEventHead = NULL;
    eventLoop->timeEventNextId = 1;
    Jim_SetAssocData(interp, "eventloop", JimELAssocDataDeleProc, eventLoop);

    Jim_CreateCommand(interp, "vwait", JimELVwaitCommand, NULL, NULL);
    Jim_CreateCommand(interp, "after", JimELAfterCommand, NULL, NULL);

    /* Export events API */
    Jim_RegisterApi(interp, "Jim_CreateFileHandler", Jim_CreateFileHandler);
    Jim_RegisterApi(interp, "Jim_DeleteFileHandler", Jim_DeleteFileHandler);
    Jim_RegisterApi(interp, "Jim_CreateTimeHandler", Jim_CreateTimeHandler);
    Jim_RegisterApi(interp, "Jim_DeleteTimeHandler", Jim_DeleteTimeHandler);
    Jim_RegisterApi(interp, "Jim_ProcessEvents", Jim_ProcessEvents);
    return JIM_OK;
}
예제 #2
0
jim_wide Jim_CreateTimeHandler(Jim_Interp *interp, jim_wide milliseconds,
        Jim_TimeProc *proc, void *clientData,
        Jim_EventFinalizerProc *finalizerProc)
{
    Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");
    jim_wide id = eventLoop->timeEventNextId++;
    Jim_TimeEvent *te;
    long cur_sec, cur_ms;

    JimGetTime(&cur_sec, &cur_ms);

    te = Jim_Alloc(sizeof(*te));
    te->id = id;
    te->mode = 0;
    te->initialms = milliseconds;
    te->when_sec = cur_sec + milliseconds/1000;
    te->when_ms = cur_ms + milliseconds%1000;
    if (te->when_ms >= 1000) {
        te->when_sec ++;
        te->when_ms -= 1000;
    }
    te->timeProc = proc;
    te->finalizerProc = finalizerProc;
    te->clientData = clientData;
    te->next = eventLoop->timeEventHead;
    eventLoop->timeEventHead = te;
    return id;
}
예제 #3
0
jim_wide Jim_CreateTimeHandler(Jim_Interp *interp, jim_wide us,
    Jim_TimeProc * proc, void *clientData, Jim_EventFinalizerProc * finalizerProc)
{
    Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");
    jim_wide id = ++eventLoop->timeEventNextId;
    Jim_TimeEvent *te, *e, *prev;

    te = Jim_Alloc(sizeof(*te));
    te->id = id;
    te->initialus = us;
    te->when = JimGetTimeUsec(eventLoop) + us;
    te->timeProc = proc;
    te->finalizerProc = finalizerProc;
    te->clientData = clientData;

    /* Add to the appropriate place in the list */
    prev = NULL;
    for (e = eventLoop->timeEventHead; e; e = e->next) {
        if (te->when < e->when) {
            break;
        }
        prev = e;
    }
    if (prev) {
        te->next = prev->next;
        prev->next = te;
    }
    else {
        te->next = eventLoop->timeEventHead;
        eventLoop->timeEventHead = te;
    }

    return id;
}
예제 #4
0
/**
 * Creates a channel for fh/fd/filename.
 *
 * If fh is not NULL, uses that as the channel (and set AIO_KEEPOPEN).
 * Otherwise, if fd is >= 0, uses that as the chanel.
 * Otherwise opens 'filename' with mode 'mode'.
 *
 * hdlfmt is a sprintf format for the filehandle. Anything with %ld at the end will do.
 * mode is used for open or fdopen.
 *
 * Creates the command and sets the name as the current result.
 */
static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
    const char *hdlfmt, int family, const char *mode)
{
    AioFile *af;
    char buf[AIO_CMD_LEN];
    int OpenFlags = 0;

    if (filename == NULL) {
        filename = Jim_NewStringObj(interp, hdlfmt, -1);
    }

    Jim_IncrRefCount(filename);

    if (fh == NULL) {
        if (fd < 0) {
            fh = fopen(Jim_String(filename), mode);
        }
        else {
            fh = fdopen(fd, mode);
        }
    }
    else {
        OpenFlags = AIO_KEEPOPEN;
    }

    if (fh == NULL) {
        JimAioSetError(interp, filename);
#if !defined(JIM_ANSIC)
        if (fd >= 0) {
            close(fd);
        }
#endif
        Jim_DecrRefCount(interp, filename);
        return JIM_ERR;
    }

    /* Create the file command */
    af = Jim_Alloc(sizeof(*af));
    memset(af, 0, sizeof(*af));
    af->fp = fh;
    af->fd = fileno(fh);
    af->filename = filename;
#ifdef FD_CLOEXEC
    if ((OpenFlags & AIO_KEEPOPEN) == 0) {
        fcntl(af->fd, F_SETFD, FD_CLOEXEC);
    }
#endif
    af->OpenFlags = OpenFlags;
#ifdef O_NDELAY
    af->flags = fcntl(af->fd, F_GETFL);
#endif
    af->addr_family = family;
    snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
    Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);

    Jim_SetResultString(interp, buf, -1);

    return JIM_OK;
}
예제 #5
0
파일: jim-exec.c 프로젝트: dokterp/jimtcl
static struct WaitInfoTable *JimAllocWaitInfoTable(void)
{
    struct WaitInfoTable *table = Jim_Alloc(sizeof(*table));
    table->info = NULL;
    table->size = table->used = 0;

    return table;
}
예제 #6
0
static int Jim_Decompress(Jim_Interp *interp, const char *in, int len, long bufsiz, int wbits)
{
    z_stream strm = {0};
    void *buf;
    Jim_Obj *out;
    int ret;

    if (JimZlibCheckBufSize(interp, bufsiz)) {
        return JIM_ERR;
    }

    if (inflateInit2(&strm, wbits) != Z_OK) {
        return JIM_ERR;
    }

    /* allocate a buffer - decompression is done in chunks, into this buffer;
     * when the decompressed data size is given, decompression is faster because
     * it's done in one pass, with less memcpy() overhead */
    buf = Jim_Alloc((int)bufsiz);

    out = Jim_NewEmptyStringObj(interp);
    Jim_IncrRefCount(out);

    strm.next_in = (Bytef*)in;
    strm.avail_in = (uInt)len;
    do {
        do {
            strm.next_out = buf;
            strm.avail_out = (uInt)bufsiz;

            ret = inflate(&strm, Z_NO_FLUSH);
            switch (ret) {
            case Z_OK:
            case Z_STREAM_END:
                /* append each chunk to the output object */
                Jim_AppendString(interp, out, buf, (int)(bufsiz - (long)strm.avail_out));
                break;

            default:
                Jim_DecrRefCount(interp, out);
                Jim_Free(buf);
                inflateEnd(&strm);
                if (strm.msg != NULL)
                    Jim_SetResultString(interp, strm.msg, -1);
                return JIM_ERR;
            }
        } while (strm.avail_out == 0);
    } while (ret != Z_STREAM_END);

    /* free memory used for decompression before we assign the return value */
    Jim_Free(buf);
    inflateEnd(&strm);

    Jim_SetResult(interp, out);
    Jim_DecrRefCount(interp, out);

    return JIM_OK;
}
예제 #7
0
파일: jim-load.c 프로젝트: AllardJ/Tomato
/**
 * Note that Jim_LoadLibrary() requires a path to an existing file.
 *
 * If it is necessary to search JIM_LIBPATH, use Jim_PackageRequire() instead.
 */
int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName)
{
    void *handle = dlopen(pathName, RTLD_NOW | RTLD_LOCAL);
    if (handle == NULL) {
        Jim_SetResultFormatted(interp, "error loading extension \"%s\": %s", pathName,
            dlerror());
    }
    else {
        /* We use a unique init symbol depending on the extension name.
         * This is done for compatibility between static and dynamic extensions.
         * For extension readline.so, the init symbol is "Jim_readlineInit"
         */
        const char *pt;
        const char *pkgname;
        int pkgnamelen;
        char initsym[40];
        int (*onload) (Jim_Interp *);

        pt = strrchr(pathName, '/');
        if (pt) {
            pkgname = pt + 1;
        }
        else {
            pkgname = pathName;
        }
        pt = strchr(pkgname, '.');
        if (pt) {
            pkgnamelen = pt - pkgname;
        }
        else {
            pkgnamelen = strlen(pkgname);
        }
        snprintf(initsym, sizeof(initsym), "Jim_%.*sInit", pkgnamelen, pkgname);

        if ((onload = dlsym(handle, initsym)) == NULL) {
            Jim_SetResultFormatted(interp,
                "No %s symbol found in extension %s", initsym, pathName);
        }
        else if (onload(interp) != JIM_ERR) {
            /* Add this handle to the stack of handles to be freed */
            if (!interp->loadHandles) {
                interp->loadHandles = Jim_Alloc(sizeof(*interp->loadHandles));
                Jim_InitStack(interp->loadHandles);
            }
            Jim_StackPush(interp->loadHandles, handle);

            Jim_SetEmptyResult(interp);

            return JIM_OK;
        }
    }
    if (handle) {
        dlclose(handle);
    }
    return JIM_ERR;
}
예제 #8
0
int Jim_historyInit(Jim_Interp *interp)
{
    void **history;
    if (Jim_PackageProvide(interp, "history", "1.0", JIM_ERRMSG))
        return JIM_ERR;

    history = Jim_Alloc(sizeof(*history));
    *history = NULL;

    Jim_CreateCommand(interp, "history", JimHistorySubCmdProc, history, JimHistoryDelProc);
    return JIM_OK;
}
예제 #9
0
static int aio_cmd_recvfrom(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    AioFile *af = Jim_CmdPrivData(interp);
    char *buf;
    union sockaddr_any sa;
    long len;
    socklen_t salen = sizeof(sa);
    int rlen;

    if (Jim_GetLong(interp, argv[0], &len) != JIM_OK) {
        return JIM_ERR;
    }

    buf = Jim_Alloc(len + 1);

    rlen = recvfrom(fileno(af->fp), buf, len, 0, &sa.sa, &salen);
    if (rlen < 0) {
        Jim_Free(buf);
        JimAioSetError(interp, NULL);
        return JIM_ERR;
    }
    buf[rlen] = 0;
    Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, rlen));

    if (argc > 1) {
        /* INET6_ADDRSTRLEN is 46. Add some for [] and port */
        char addrbuf[60];

#if IPV6
        if (sa.sa.sa_family == PF_INET6) {
            addrbuf[0] = '[';
            /* Allow 9 for []:65535\0 */
            inet_ntop(sa.sa.sa_family, &sa.sin6.sin6_addr, addrbuf + 1, sizeof(addrbuf) - 9);
            snprintf(addrbuf + strlen(addrbuf), 8, "]:%d", ntohs(sa.sin.sin_port));
        }
        else
#endif
        {
            /* Allow 7 for :65535\0 */
            inet_ntop(sa.sa.sa_family, &sa.sin.sin_addr, addrbuf, sizeof(addrbuf) - 7);
            snprintf(addrbuf + strlen(addrbuf), 7, ":%d", ntohs(sa.sin.sin_port));
        }

        if (Jim_SetVariable(interp, argv[1], Jim_NewStringObj(interp, addrbuf, -1)) != JIM_OK) {
            return JIM_ERR;
        }
    }

    return JIM_OK;
}
예제 #10
0
void Jim_CreateFileHandler(Jim_Interp *interp, int fd, int mask,
    Jim_FileProc * proc, void *clientData, Jim_EventFinalizerProc * finalizerProc)
{
    Jim_FileEvent *fe;
    Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");

    fe = Jim_Alloc(sizeof(*fe));
    fe->fd = fd;
    fe->mask = mask;
    fe->fileProc = proc;
    fe->finalizerProc = finalizerProc;
    fe->clientData = clientData;
    fe->next = eventLoop->fileEventHead;
    eventLoop->fileEventHead = fe;
}
예제 #11
0
jim_wide Jim_CreateTimeHandler(Jim_Interp *interp, jim_wide milliseconds,
    Jim_TimeProc * proc, void *clientData, Jim_EventFinalizerProc * finalizerProc)
{
    Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");
    jim_wide id = eventLoop->timeEventNextId++;
    Jim_TimeEvent *te, *e, *prev;
    long cur_sec, cur_ms;

    JimGetTime(&cur_sec, &cur_ms);

    te = Jim_Alloc(sizeof(*te));
    te->id = id;
    te->mode = 0;
    te->initialms = milliseconds;
    te->when_sec = cur_sec + milliseconds / 1000;
    te->when_ms = cur_ms + milliseconds % 1000;
    if (te->when_ms >= 1000) {
        te->when_sec++;
        te->when_ms -= 1000;
    }
    te->timeProc = proc;
    te->finalizerProc = finalizerProc;
    te->clientData = clientData;

    /* Add to the appropriate place in the list */
    if (eventLoop->timeEventHead) {
        prev = NULL;
        for (e = eventLoop->timeEventHead; e; e = e->next) {
            if (te->when_sec < e->when_sec || (te->when_sec == e->when_sec && te->when_ms < e->when_ms)) {
                break;
            }
            prev = e;
        }
        if (prev) {
            te->next = prev->next;
            prev->next = te;
            return id;
        }
    }

    te->next = eventLoop->timeEventHead;
    eventLoop->timeEventHead = te;

    return id;
}
예제 #12
0
int Jim_eventloopInit(Jim_Interp *interp)
{
    Jim_EventLoop *eventLoop;

    if (Jim_PackageProvide(interp, "eventloop", "1.0", JIM_ERRMSG))
        return JIM_ERR;

    eventLoop = Jim_Alloc(sizeof(*eventLoop));
    memset(eventLoop, 0, sizeof(*eventLoop));

    Jim_SetAssocData(interp, "eventloop", JimELAssocDataDeleProc, eventLoop);

    Jim_CreateCommand(interp, "vwait", JimELVwaitCommand, eventLoop, NULL);
    Jim_CreateCommand(interp, "update", JimELUpdateCommand, eventLoop, NULL);
    Jim_CreateCommand(interp, "after", JimELAfterCommand, eventLoop, NULL);

    return JIM_OK;
}
예제 #13
0
파일: jim-syslog.c 프로젝트: marrero/jimtcl
int Jim_syslogInit(Jim_Interp *interp)
{
    SyslogInfo *info;
    
    if (Jim_PackageProvide(interp, "syslog", "1.0", JIM_ERRMSG))
        return JIM_ERR;

    info = Jim_Alloc(sizeof(*info));

    info->logOpened = 0;
    info->options = 0;
    info->facility = LOG_USER;
    info->ident[0] = 0;

    Jim_CreateCommand(interp, "syslog", Jim_SyslogCmd, info, Jim_SyslogCmdDelete);

    return JIM_OK;
}
예제 #14
0
void Jim_CreateFileHandler(Jim_Interp *interp, void *handle, int mask,
        Jim_FileProc *proc, void *clientData,
        Jim_EventFinalizerProc *finalizerProc)
{
    Jim_FileEvent *fe;
    Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");

	// fprintf(stderr,"rein\n");
    fe = Jim_Alloc(sizeof(*fe));
    fe->handle = handle;
    fe->mask = mask;
    fe->fileProc = proc;
    fe->finalizerProc = finalizerProc;
    fe->clientData = clientData;
    fe->next = eventLoop->fileEventHead;
    eventLoop->fileEventHead = fe;
	// fprintf(stderr,"raus\n");
}
예제 #15
0
static int Jim_Compress(Jim_Interp *interp, const char *in, int len, long level, int wbits)
{
    z_stream strm = {0};
    Bytef *buf;

    if ((level != Z_DEFAULT_COMPRESSION) && ((level < Z_NO_COMPRESSION) || (level > Z_BEST_COMPRESSION))) {
        Jim_SetResultString(interp, "level must be 0 to 9", -1);
        return JIM_ERR;
    }

    if (deflateInit2(&strm, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) {
        return JIM_ERR;
    }

    strm.avail_out = deflateBound(&strm, (uLong)len);
    if (strm.avail_out > INT_MAX) {
        deflateEnd(&strm);
        return JIM_ERR;
    }
    buf = (Bytef *)Jim_Alloc((int)strm.avail_out);
    strm.next_out = buf;
    strm.next_in = (Bytef *)in;
    strm.avail_in = (uInt)len;

    /* always compress in one pass - the return value holds the entire
     * decompressed data anyway, so there's no reason to do chunked
     * decompression */
    if (deflate(&strm, Z_FINISH) != Z_STREAM_END) {
        Jim_Free(strm.next_out);
        deflateEnd(&strm);
        return JIM_ERR;
    }

    deflateEnd(&strm);

    if (strm.total_out > INT_MAX) {
        Jim_Free(strm.next_out);
        return JIM_ERR;
    }

    Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, (char *)buf, (int)strm.total_out));
    return JIM_OK;
}
예제 #16
0
파일: jim-posix.c 프로젝트: marrero/jimtcl
static int Jim_PosixGethostnameCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    char *buf;
    int rc = JIM_OK;

    if (argc != 1) {
        Jim_WrongNumArgs(interp, 1, argv, "");
        return JIM_ERR;
    }
    buf = Jim_Alloc(JIM_HOST_NAME_MAX);
    if (gethostname(buf, JIM_HOST_NAME_MAX) == -1) {
        Jim_PosixSetError(interp);
        rc = JIM_ERR;
    }
    else {
        Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, -1));
    }
    return rc;
}
예제 #17
0
int Jim_eventloopInit(Jim_Interp *interp)
{
    Jim_EventLoop *eventLoop;

    if (Jim_PackageProvide(interp, "eventloop", "1.0", JIM_ERRMSG))
        return JIM_ERR;

    eventLoop = Jim_Alloc(sizeof(*eventLoop));
    eventLoop->fileEventHead = NULL;
    eventLoop->timeEventHead = NULL;
    eventLoop->timeEventNextId = 1;
    eventLoop->suppress_bgerror = 0;
    Jim_SetAssocData(interp, "eventloop", JimELAssocDataDeleProc, eventLoop);

    Jim_CreateCommand(interp, "vwait", JimELVwaitCommand, eventLoop, NULL);
    Jim_CreateCommand(interp, "update", JimELUpdateCommand, eventLoop, NULL);
    Jim_CreateCommand(interp, "after", JimELAfterCommand, eventLoop, NULL);

    return JIM_OK;
}
예제 #18
0
static char *JimSqliteQuoteString(const char *str, int len, int *newLenPtr)
{
    int i, newLen, c = 0;
    const char *s;
    char *d, *buf;

    for (i = 0; i < len; i++)
        if (str[i] == '\'')
            c++;
    newLen = len + c;
    s = str;
    d = buf = Jim_Alloc(newLen);
    while (len--) {
        if (*s == '\'')
            *d++ = '\'';
        *d++ = *s++;
    }
    *newLenPtr = newLen;
    return buf;
}
예제 #19
0
static int file_cmd_normalize(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
#ifdef HAVE_REALPATH
    const char *path = Jim_String(argv[0]);
    char *newname = Jim_Alloc(MAXPATHLEN + 1);

    if (realpath(path, newname)) {
        Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, -1));
        return JIM_OK;
    }
    else {
        Jim_Free(newname);
        Jim_SetResultFormatted(interp, "can't normalize \"%#s\": %s", argv[0], strerror(errno));
        return JIM_ERR;
    }
#else
    Jim_SetResultString(interp, "Not implemented", -1);
    return JIM_ERR;
#endif
}
예제 #20
0
파일: jim-aio.c 프로젝트: Johnicholas/Jim
static int JimAioAcceptHelper(Jim_Interp *interp, AioFile *serv_af )
{
    int sock;
    int addrlen = sizeof(struct sockaddr_in);
    AioFile *af;
    char buf[AIO_CMD_LEN];
    Jim_Obj *objPtr;
    long fileId;
	fprintf(stderr,"accepting connection for %d \n",serv_af->fd);
    sock = accept(serv_af->fd,(struct sockaddr*)&serv_af->sa,&addrlen);
	fprintf(stderr,"done, got %d \n",sock);
    if (sock < 0)
	return JIM_ERR;

    /* Get the next file id */
    fprintf(stderr,"getting fileid:");
    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;
    fprintf(stderr," %ld\n", fileId);

    /* Create the file command */
    af = Jim_Alloc(sizeof(*af));
    af->fd = sock;
    af->fp = fdopen(sock,"r+");
    af->OpenFlags = AIO_FDOPEN;
    af->flags = fcntl(af->fd,F_GETFL);
    // fprintf(stderr,"hallo\n");
    af->rEvent = NULL;
    af->wEvent = NULL;
    af->eEvent = NULL;
    sprintf(buf, "aio.sockstream%ld", fileId);
    Jim_CreateCommand(interp, buf, JimAioHandlerCommand, af, JimAioDelProc);
    Jim_SetResultString(interp, buf, -1);
    fprintf(stderr,"returning\n");
    return JIM_OK;
}
예제 #21
0
static int JimSdlSurfaceCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    JimSdlSurface *jss;
    char buf[AIO_CMD_LEN];
    Jim_Obj *objPtr;
    long screenId, xres, yres;
    SDL_Surface *screen;

    if (argc != 3) {
        Jim_WrongNumArgs(interp, 1, argv, "xres yres");
        return JIM_ERR;
    }
    if (Jim_GetLong(interp, argv[1], &xres) != JIM_OK ||
        Jim_GetLong(interp, argv[2], &yres) != JIM_OK)
        return JIM_ERR;

    /* Try to create the surface */
    screen = SDL_SetVideoMode(xres, yres, 32, SDL_SWSURFACE | SDL_ANYFORMAT);
    if (screen == NULL) {
        JimSdlSetError(interp);
        return JIM_ERR;
    }
    /* Get the next file id */
    if (Jim_EvalGlobal(interp, "if {[catch {incr sdl.surfaceId}]} {set sdl.surfaceId 0}") != JIM_OK)
        return JIM_ERR;
    objPtr = Jim_GetVariableStr(interp, "sdl.surfaceId", JIM_ERRMSG);
    if (objPtr == NULL)
        return JIM_ERR;
    if (Jim_GetLong(interp, objPtr, &screenId) != JIM_OK)
        return JIM_ERR;

    /* Create the SDL screen command */
    jss = Jim_Alloc(sizeof(*jss));
    jss->screen = screen;
    sprintf(buf, "sdl.surface%ld", screenId);
    Jim_CreateCommand(interp, buf, JimSdlHandlerCommand, jss, JimSdlDelProc);
    Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1)));
    return JIM_OK;
}
예제 #22
0
파일: jim-regexp.c 프로젝트: BruceZu/jimtcl
static regex_t *SetRegexpFromAny(Jim_Interp *interp, Jim_Obj *objPtr, unsigned flags)
{
    regex_t *compre;
    const char *pattern;
    int ret;

    /* Check if the object is already an uptodate variable */
    if (objPtr->typePtr == &regexpObjType &&
        objPtr->internalRep.regexpValue.compre && objPtr->internalRep.regexpValue.flags == flags) {
        /* nothing to do */
        return objPtr->internalRep.regexpValue.compre;
    }

    /* Not a regexp or the flags do not match */

    /* Get the string representation */
    pattern = Jim_String(objPtr);
    compre = Jim_Alloc(sizeof(regex_t));

    if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) {
        char buf[100];

        regerror(ret, compre, buf, sizeof(buf));
        Jim_SetResultFormatted(interp, "couldn't compile regular expression pattern: %s", buf);
        regfree(compre);
        Jim_Free(compre);
        return NULL;
    }

    Jim_FreeIntRep(interp, objPtr);

    objPtr->typePtr = &regexpObjType;
    objPtr->internalRep.regexpValue.flags = flags;
    objPtr->internalRep.regexpValue.compre = compre;

    return compre;
}
예제 #23
0
파일: jim-signal.c 프로젝트: dgsb/jimtcl
static int do_signal_cmd(Jim_Interp *interp, int action, int argc, Jim_Obj *const *argv)
{
    struct sigaction sa;
    int i;

    if (argc == 0) {
        Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
        for (i = 1; i < MAX_SIGNALS; i++) {
            if (siginfo[i].status == action) {
                /* Add signal name to the list  */
                Jim_ListAppendElement(interp, Jim_GetResult(interp),
                    Jim_NewStringObj(interp, Jim_SignalId(i), -1));
            }
        }
        return JIM_OK;
    }

    /* Catch all the signals we care about */
    if (action != SIGNAL_ACTION_DEFAULT) {
        sa.sa_flags = 0;
        sigemptyset(&sa.sa_mask);
        if (action == SIGNAL_ACTION_HANDLE) {
            sa.sa_handler = signal_handler;
        }
        else {
            sa.sa_handler = signal_ignorer;
        }
    }

    /* Iterate through the provided signals */
    for (i = 0; i < argc; i++) {
        int sig = find_signal_by_name(interp, Jim_String(argv[i]));

        if (sig < 0) {
            return JIM_ERR;
        }
        if (action != siginfo[sig].status) {
            /* Need to change the action for this signal */
            switch (action) {
                case SIGNAL_ACTION_HANDLE:
                case SIGNAL_ACTION_IGNORE:
                    if (siginfo[sig].status == SIGNAL_ACTION_DEFAULT) {
                        if (!sa_old) {
                            /* Allocate the structure the first time through */
                            sa_old = Jim_Alloc(sizeof(*sa_old) * MAX_SIGNALS);
                        }
                        sigaction(sig, &sa, &sa_old[sig]);
                    }
                    else {
                        sigaction(sig, &sa, 0);
                    }
                    break;

                case SIGNAL_ACTION_DEFAULT:
                    /* Restore old handler */
                    if (sa_old) {
                        sigaction(sig, &sa_old[sig], 0);
                    }
            }
            siginfo[sig].status = action;
        }
    }

    return JIM_OK;
}
예제 #24
0
static int file_cmd_join(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    int i;
    char *newname = Jim_Alloc(MAXPATHLEN + 1);
    char *last = newname;

    *newname = 0;

    /* Simple implementation for now */
    for (i = 0; i < argc; i++) {
        int len;
        const char *part = Jim_GetString(argv[i], &len);

        if (*part == '/') {
            /* Absolute component, so go back to the start */
            last = newname;
        }
#if defined(__MINGW32__) || defined(_MSC_VER)
        else if (strchr(part, ':')) {
            /* Absolute compontent on mingw, so go back to the start */
            last = newname;
        }
#endif
        else if (part[0] == '.') {
            if (part[1] == '/') {
                part += 2;
                len -= 2;
            }
            else if (part[1] == 0 && last != newname) {
                /* Adding '.' to an existing path does nothing */
                continue;
            }
        }

        /* Add a slash if needed */
        if (last != newname && last[-1] != '/') {
            *last++ = '/';
        }

        if (len) {
            if (last + len - newname >= MAXPATHLEN) {
                Jim_Free(newname);
                Jim_SetResultString(interp, "Path too long", -1);
                return JIM_ERR;
            }
            memcpy(last, part, len);
            last += len;
        }

        /* Remove a slash if needed */
        if (last > newname + 1 && last[-1] == '/') {
            *--last = 0;
        }
    }

    *last = 0;

    /* Probably need to handle some special cases ... */

    Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname));

    return JIM_OK;
}
예제 #25
0
파일: jim-aio.c 프로젝트: Johnicholas/Jim
static int JimAioSockCommand(Jim_Interp *interp, int argc, 
        Jim_Obj *const *argv)
{
    FILE *fp;
    AioFile *af;
    char buf[AIO_CMD_LEN];
    char *hdlfmt;
    // const char *mode = "r";
    Jim_Obj *objPtr;
    long fileId;
    const char *socktypes[] = {
		"file",
		"pipe",
		"tty",
		"domain", 
		"dgram", 
		"stream", 
		"stream.server",
		
		NULL
    };
    enum {
		FILE_FILE,
		FILE_PIPE,
		FILE_TTY,
		SOCK_DOMAIN, 
		SOCK_DGRAM_CL, 
		SOCK_STREAM_CL, 
		SOCK_STREAM_SERV 
    };
    int socktype;
    int sock;
    const char *hostportarg;
    int hostportlen;
    char a[0x20];
    char b[0x20];
    char c[0x20];
    char np[] = "0";
    char nh[] = "0.0.0.0";
    char* stsrcport; 
    char* sthost; 
    char* stport;
    unsigned int srcport;
    unsigned int port;
    struct sockaddr_in sa;
    struct hostent *he;
    int res;

    if (argc <= 2 ) {
        Jim_WrongNumArgs(interp, 1, argv, "sockspec  ?script?");
        return JIM_ERR;
    }

    if (Jim_GetEnum(interp, argv[1], socktypes, &socktype, "socket type",
                    JIM_ERRMSG) != JIM_OK)
            return JIM_ERR;
    fprintf(stderr,"socktype: %s \n",socktypes[socktype]);
    hostportarg = Jim_GetString(argv[2], &hostportlen);
    fprintf(stderr,"hostportarg: %s %d \n",hostportarg,hostportlen);
    switch (sscanf(hostportarg,"%[^:]:%[^:]:%[^:]",a,b,c)) {
	case 3: stsrcport = a; sthost = b; stport = c; break;
	case 2: stsrcport = np; sthost = a; stport = b; break;
	case 1: stsrcport = np; sthost = nh; stport = a; break;
	default:
            return JIM_ERR;
    }
    fprintf(stderr,"socktype: %d srcport: %s host:%s port %s \n",
		socktype,stsrcport,sthost,stport);
    if (0 == strncmp(sthost,"ANY",3))
	sthost = "0.0.0.0";
    srcport = atol(stsrcport);
    port = atol(stport);
    he = gethostbyname(sthost);
    /* FIX!!!! this still results in null pointer exception here.  
    /* FIXED!!!! debug output but no JIM_ERR done UK.  
    if (!he) {
        Jim_SetResultString(interp,hstrerror(h_errno),-1);
        return JIM_ERR;
    }

    fprintf(stderr,"Official name is: %s\n", he->h_name);
    fprintf(stderr,"IP address: %s\n", inet_ntoa(*(struct in_addr*)he->h_addr));
     */

    sock = socket(PF_INET,SOCK_STREAM,0);
    fprintf(stderr,"srcp: %x port: %x IP: %x sock: %d type: %d\n",srcport,port,he->h_addr,sock,socktype);
    switch (socktype) {
    case SOCK_DGRAM_CL:
		hdlfmt = "aio.sockdgram%ld" ;
		break;
    case SOCK_STREAM_CL:	
    		fprintf(stderr,"setting up client socket\n");
    		sa.sin_family= he->h_addrtype;
		bcopy(he->h_addr,(char *)&sa.sin_addr,he->h_length); /* set address */
		sa.sin_port = htons(port);
		res = connect(sock,(struct sockaddr*)&sa,sizeof(sa));
		if (res) {
			close(sock);
			JimAioSetError(interp);
			return JIM_ERR;
		}
		hdlfmt = "aio.sockstrm%ld" ;
		break;
    case SOCK_STREAM_SERV: 
    		fprintf(stderr,"setting up listening socket\n");
    		sa.sin_family= he->h_addrtype;
		bcopy(he->h_addr,(char *)&sa.sin_addr,he->h_length); /* set address */
		sa.sin_port = htons(port);
		res = bind(sock,(struct sockaddr*)&sa,sizeof(sa));	
		if (res) {
			close(sock);
			JimAioSetError(interp);
			return JIM_ERR;
		}
		res = listen(sock,5);	
		if (res) {
			close(sock);
			JimAioSetError(interp);
			return JIM_ERR;
		}
		hdlfmt = "aio.socksrv%ld" ;
		break;
    }
    fp = fdopen(sock, "r+" );
    fprintf(stderr,"fp: %p \n",fp);
    if (fp == NULL) {
	close(sock);
        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 = sock;
    af->OpenFlags = AIO_FDOPEN;
    af->flags = fcntl(af->fd,F_GETFL);
    fprintf(stderr,"hallo\n");
    af->rEvent = NULL;
    af->wEvent = NULL;
    af->eEvent = NULL;
    sprintf(buf, hdlfmt, fileId);
    fprintf(stderr,"hallo:%s\n",buf);
    Jim_CreateCommand(interp, buf, JimAioHandlerCommand, af, JimAioDelProc);
    Jim_SetResultString(interp, buf, -1);
    return JIM_OK;
}
예제 #26
0
파일: jim-aio.c 프로젝트: Johnicholas/Jim
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;
}
int Jim_InteractivePrompt(Jim_Interp *interp)
{
    int retcode = JIM_OK;
    char *history_file = NULL;
#ifdef USE_LINENOISE
    const char *home;

    home = getenv("HOME");
    if (home && isatty(STDIN_FILENO)) {
        int history_len = strlen(home) + sizeof("/.jim_history");
        history_file = Jim_Alloc(history_len);
        snprintf(history_file, history_len, "%s/.jim_history", home);
        Jim_HistoryLoad(history_file);
    }
#endif

    printf("Welcome to Jim version %d.%d" JIM_NL,
        JIM_VERSION / 100, JIM_VERSION % 100);
    Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");

    while (1) {
        Jim_Obj *scriptObjPtr;
        const char *result;
        int reslen;
        char prompt[20];
        const char *str;

        if (retcode != 0) {
            const char *retcodestr = Jim_ReturnCode(retcode);

            if (*retcodestr == '?') {
                snprintf(prompt, sizeof(prompt) - 3, "[%d] ", retcode);
            }
            else {
                snprintf(prompt, sizeof(prompt) - 3, "[%s] ", retcodestr);
            }
        }
        else {
            prompt[0] = '\0';
        }
        strcat(prompt, ". ");

        scriptObjPtr = Jim_NewStringObj(interp, "", 0);
        Jim_IncrRefCount(scriptObjPtr);
        while (1) {
            char state;
            int len;
            char *line;

            line = Jim_HistoryGetline(prompt);
            if (line == NULL) {
                if (errno == EINTR) {
                    continue;
                }
                Jim_DecrRefCount(interp, scriptObjPtr);
                retcode = JIM_OK;
                goto out;
            }
            if (Jim_Length(scriptObjPtr) != 0) {
                Jim_AppendString(interp, scriptObjPtr, "\n", 1);
            }
            Jim_AppendString(interp, scriptObjPtr, line, -1);
            free(line);
            str = Jim_GetString(scriptObjPtr, &len);
            if (len == 0) {
                continue;
            }
            if (Jim_ScriptIsComplete(str, len, &state))
                break;

            snprintf(prompt, sizeof(prompt), "%c> ", state);
        }
#ifdef USE_LINENOISE
        if (strcmp(str, "h") == 0) {
            /* built-in history command */
            Jim_HistoryShow();
            Jim_DecrRefCount(interp, scriptObjPtr);
            continue;
        }

        Jim_HistoryAdd(Jim_String(scriptObjPtr));
        if (history_file) {
            Jim_HistorySave(history_file);
        }
#endif
        retcode = Jim_EvalObj(interp, scriptObjPtr);
        Jim_DecrRefCount(interp, scriptObjPtr);

        if (retcode == JIM_EXIT) {
            retcode = JIM_EXIT;
            break;
        }
        if (retcode == JIM_ERR) {
            Jim_MakeErrorMessage(interp);
        }
        result = Jim_GetString(Jim_GetResult(interp), &reslen);
        if (reslen) {
            printf("%s\n", result);
        }
    }
  out:
    Jim_Free(history_file);
    return retcode;
}
예제 #28
0
파일: jim-exec.c 프로젝트: dokterp/jimtcl
/*
 *----------------------------------------------------------------------
 *
 * JimCreatePipeline --
 *
 *  Given an argc/argv array, instantiate a pipeline of processes
 *  as described by the argv.
 *
 * Results:
 *  The return value is a count of the number of new processes
 *  created, or -1 if an error occurred while creating the pipeline.
 *  *pidArrayPtr is filled in with the address of a dynamically
 *  allocated array giving the ids of all of the processes.  It
 *  is up to the caller to free this array when it isn't needed
 *  anymore.  If inPipePtr is non-NULL, *inPipePtr is filled in
 *  with the file id for the input pipe for the pipeline (if any):
 *  the caller must eventually close this file.  If outPipePtr
 *  isn't NULL, then *outPipePtr is filled in with the file id
 *  for the output pipe from the pipeline:  the caller must close
 *  this file.  If errFilePtr isn't NULL, then *errFilePtr is filled
 *  with a file id that may be used to read error output after the
 *  pipeline completes.
 *
 * Side effects:
 *  Processes and pipes are created.
 *
 *----------------------------------------------------------------------
 */
static int
JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr,
    fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr)
{
    pidtype *pidPtr = NULL;         /* Points to malloc-ed array holding all
                                 * the pids of child processes. */
    int numPids = 0;            /* Actual number of processes that exist
                                 * at *pidPtr right now. */
    int cmdCount;               /* Count of number of distinct commands
                                 * found in argc/argv. */
    const char *input = NULL;   /* Describes input for pipeline, depending
                                 * on "inputFile".  NULL means take input
                                 * from stdin/pipe. */
    int input_len = 0;          /* Length of input, if relevant */

#define FILE_NAME   0           /* input/output: filename */
#define FILE_APPEND 1           /* output only:  filename, append */
#define FILE_HANDLE 2           /* input/output: filehandle */
#define FILE_TEXT   3           /* input only:   input is actual text */

    int inputFile = FILE_NAME;  /* 1 means input is name of input file.
                                 * 2 means input is filehandle name.
                                 * 0 means input holds actual
                                 * text to be input to command. */

    int outputFile = FILE_NAME; /* 0 means output is the name of output file.
                                 * 1 means output is the name of output file, and append.
                                 * 2 means output is filehandle name.
                                 * All this is ignored if output is NULL
                                 */
    int errorFile = FILE_NAME;  /* 0 means error is the name of error file.
                                 * 1 means error is the name of error file, and append.
                                 * 2 means error is filehandle name.
                                 * All this is ignored if error is NULL
                                 */
    const char *output = NULL;  /* Holds name of output file to pipe to,
                                 * or NULL if output goes to stdout/pipe. */
    const char *error = NULL;   /* Holds name of stderr file to pipe to,
                                 * or NULL if stderr goes to stderr/pipe. */
    fdtype inputId = JIM_BAD_FD;
                                 /* Readable file id input to current command in
                                 * pipeline (could be file or pipe).  JIM_BAD_FD
                                 * means use stdin. */
    fdtype outputId = JIM_BAD_FD;
                                 /* Writable file id for output from current
                                 * command in pipeline (could be file or pipe).
                                 * JIM_BAD_FD means use stdout. */
    fdtype errorId = JIM_BAD_FD;
                                 /* Writable file id for all standard error
                                 * output from all commands in pipeline.  JIM_BAD_FD
                                 * means use stderr. */
    fdtype lastOutputId = JIM_BAD_FD;
                                 /* Write file id for output from last command
                                 * in pipeline (could be file or pipe).
                                 * -1 means use stdout. */
    fdtype pipeIds[2];           /* File ids for pipe that's being created. */
    int firstArg, lastArg;      /* Indexes of first and last arguments in
                                 * current command. */
    int lastBar;
    int i;
    pidtype pid;
    char **save_environ;
    struct WaitInfoTable *table = Jim_CmdPrivData(interp);

    /* Holds the args which will be used to exec */
    char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1));
    int arg_count = 0;

    JimReapDetachedPids(table);

    if (inPipePtr != NULL) {
        *inPipePtr = JIM_BAD_FD;
    }
    if (outPipePtr != NULL) {
        *outPipePtr = JIM_BAD_FD;
    }
    if (errFilePtr != NULL) {
        *errFilePtr = JIM_BAD_FD;
    }
    pipeIds[0] = pipeIds[1] = JIM_BAD_FD;

    /*
     * First, scan through all the arguments to figure out the structure
     * of the pipeline.  Count the number of distinct processes (it's the
     * number of "|" arguments).  If there are "<", "<<", or ">" arguments
     * then make note of input and output redirection and remove these
     * arguments and the arguments that follow them.
     */
    cmdCount = 1;
    lastBar = -1;
    for (i = 0; i < argc; i++) {
        const char *arg = Jim_String(argv[i]);

        if (arg[0] == '<') {
            inputFile = FILE_NAME;
            input = arg + 1;
            if (*input == '<') {
                inputFile = FILE_TEXT;
                input_len = Jim_Length(argv[i]) - 2;
                input++;
            }
            else if (*input == '@') {
                inputFile = FILE_HANDLE;
                input++;
            }

            if (!*input && ++i < argc) {
                input = Jim_GetString(argv[i], &input_len);
            }
        }
        else if (arg[0] == '>') {
            int dup_error = 0;

            outputFile = FILE_NAME;

            output = arg + 1;
            if (*output == '>') {
                outputFile = FILE_APPEND;
                output++;
            }
            if (*output == '&') {
                /* Redirect stderr too */
                output++;
                dup_error = 1;
            }
            if (*output == '@') {
                outputFile = FILE_HANDLE;
                output++;
            }
            if (!*output && ++i < argc) {
                output = Jim_String(argv[i]);
            }
            if (dup_error) {
                errorFile = outputFile;
                error = output;
            }
        }
        else if (arg[0] == '2' && arg[1] == '>') {
            error = arg + 2;
            errorFile = FILE_NAME;

            if (*error == '@') {
                errorFile = FILE_HANDLE;
                error++;
            }
            else if (*error == '>') {
                errorFile = FILE_APPEND;
                error++;
            }
            if (!*error && ++i < argc) {
                error = Jim_String(argv[i]);
            }
        }
        else {
            if (strcmp(arg, "|") == 0 || strcmp(arg, "|&") == 0) {
                if (i == lastBar + 1 || i == argc - 1) {
                    Jim_SetResultString(interp, "illegal use of | or |& in command", -1);
                    goto badargs;
                }
                lastBar = i;
                cmdCount++;
            }
            /* Either |, |& or a "normal" arg, so store it in the arg array */
            arg_array[arg_count++] = (char *)arg;
            continue;
        }

        if (i >= argc) {
            Jim_SetResultFormatted(interp, "can't specify \"%s\" as last word in command", arg);
            goto badargs;
        }
    }

    if (arg_count == 0) {
        Jim_SetResultString(interp, "didn't specify command to execute", -1);
badargs:
        Jim_Free(arg_array);
        return -1;
    }

    /* Must do this before vfork(), so do it now */
    save_environ = JimSaveEnv(JimBuildEnv(interp));

    /*
     * Set up the redirected input source for the pipeline, if
     * so requested.
     */
    if (input != NULL) {
        if (inputFile == FILE_TEXT) {
            /*
             * Immediate data in command.  Create temporary file and
             * put data into file.
             */
            inputId = JimCreateTemp(interp, input, input_len);
            if (inputId == JIM_BAD_FD) {
                goto error;
            }
        }
        else if (inputFile == FILE_HANDLE) {
            /* Should be a file descriptor */
            FILE *fh = JimGetAioFilehandle(interp, input);

            if (fh == NULL) {
                goto error;
            }
            inputId = JimDupFd(JimFileno(fh));
        }
        else {
            /*
             * File redirection.  Just open the file.
             */
            inputId = JimOpenForRead(input);
            if (inputId == JIM_BAD_FD) {
                Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, JimStrError());
                goto error;
            }
        }
    }
    else if (inPipePtr != NULL) {
        if (JimPipe(pipeIds) != 0) {
            Jim_SetResultErrno(interp, "couldn't create input pipe for command");
            goto error;
        }
        inputId = pipeIds[0];
        *inPipePtr = pipeIds[1];
        pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
    }

    /*
     * Set up the redirected output sink for the pipeline from one
     * of two places, if requested.
     */
    if (output != NULL) {
        if (outputFile == FILE_HANDLE) {
            FILE *fh = JimGetAioFilehandle(interp, output);
            if (fh == NULL) {
                goto error;
            }
            fflush(fh);
            lastOutputId = JimDupFd(JimFileno(fh));
        }
        else {
            /*
             * Output is to go to a file.
             */
            lastOutputId = JimOpenForWrite(output, outputFile == FILE_APPEND);
            if (lastOutputId == JIM_BAD_FD) {
                Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, JimStrError());
                goto error;
            }
        }
    }
    else if (outPipePtr != NULL) {
        /*
         * Output is to go to a pipe.
         */
        if (JimPipe(pipeIds) != 0) {
            Jim_SetResultErrno(interp, "couldn't create output pipe");
            goto error;
        }
        lastOutputId = pipeIds[1];
        *outPipePtr = pipeIds[0];
        pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
    }
    /* If we are redirecting stderr with 2>filename or 2>@fileId, then we ignore errFilePtr */
    if (error != NULL) {
        if (errorFile == FILE_HANDLE) {
            if (strcmp(error, "1") == 0) {
                /* Special 2>@1 */
                if (lastOutputId != JIM_BAD_FD) {
                    errorId = JimDupFd(lastOutputId);
                }
                else {
                    /* No redirection of stdout, so just use 2>@stdout */
                    error = "stdout";
                }
            }
            if (errorId == JIM_BAD_FD) {
                FILE *fh = JimGetAioFilehandle(interp, error);
                if (fh == NULL) {
                    goto error;
                }
                fflush(fh);
                errorId = JimDupFd(JimFileno(fh));
            }
        }
        else {
            /*
             * Output is to go to a file.
             */
            errorId = JimOpenForWrite(error, errorFile == FILE_APPEND);
            if (errorId == JIM_BAD_FD) {
                Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, JimStrError());
                goto error;
            }
        }
    }
    else if (errFilePtr != NULL) {
        /*
         * Set up the standard error output sink for the pipeline, if
         * requested.  Use a temporary file which is opened, then deleted.
         * Could potentially just use pipe, but if it filled up it could
         * cause the pipeline to deadlock:  we'd be waiting for processes
         * to complete before reading stderr, and processes couldn't complete
         * because stderr was backed up.
         */
        errorId = JimCreateTemp(interp, NULL, 0);
        if (errorId == JIM_BAD_FD) {
            goto error;
        }
        *errFilePtr = JimDupFd(errorId);
    }

    /*
     * Scan through the argc array, forking off a process for each
     * group of arguments between "|" arguments.
     */

    pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr));
    for (i = 0; i < numPids; i++) {
        pidPtr[i] = JIM_BAD_PID;
    }
    for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) {
        int pipe_dup_err = 0;
        fdtype origErrorId = errorId;

        for (lastArg = firstArg; lastArg < arg_count; lastArg++) {
            if (arg_array[lastArg][0] == '|') {
                if (arg_array[lastArg][1] == '&') {
                    pipe_dup_err = 1;
                }
                break;
            }
        }
        /* Replace | with NULL for execv() */
        arg_array[lastArg] = NULL;
        if (lastArg == arg_count) {
            outputId = lastOutputId;
        }
        else {
            if (JimPipe(pipeIds) != 0) {
                Jim_SetResultErrno(interp, "couldn't create pipe");
                goto error;
            }
            outputId = pipeIds[1];
        }

        /* Now fork the child */

#ifdef __MINGW32__
        pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
        if (pid == JIM_BAD_PID) {
            Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
            goto error;
        }
#else
        /*
         * Disable SIGPIPE signals:  if they were allowed, this process
         * might go away unexpectedly if children misbehave.  This code
         * can potentially interfere with other application code that
         * expects to handle SIGPIPEs;  what's really needed is an
         * arbiter for signals to allow them to be "shared".
         */
        if (table->info == NULL) {
            (void)signal(SIGPIPE, SIG_IGN);
        }

        /* Need to do this befor vfork() */
        if (pipe_dup_err) {
            errorId = outputId;
        }

        /*
         * Make a new process and enter it into the table if the fork
         * is successful.
         */
        pid = vfork();
        if (pid < 0) {
            Jim_SetResultErrno(interp, "couldn't fork child process");
            goto error;
        }
        if (pid == 0) {
            /* Child */

            if (inputId != -1) dup2(inputId, 0);
            if (outputId != -1) dup2(outputId, 1);
            if (errorId != -1) dup2(errorId, 2);

            for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
                close(i);
            }

            execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());

            /* Need to prep an error message before vfork(), just in case */
            fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]);
            _exit(127);
        }
#endif

        /* parent */

        /*
         * Enlarge the wait table if there isn't enough space for a new
         * entry.
         */
        if (table->used == table->size) {
            table->size += WAIT_TABLE_GROW_BY;
            table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info));
        }

        table->info[table->used].pid = pid;
        table->info[table->used].flags = 0;
        table->used++;

        pidPtr[numPids] = pid;

        /* Restore in case of pipe_dup_err */
        errorId = origErrorId;

        /*
         * Close off our copies of file descriptors that were set up for
         * this child, then set up the input for the next child.
         */

        if (inputId != JIM_BAD_FD) {
            JimCloseFd(inputId);
        }
        if (outputId != JIM_BAD_FD) {
            JimCloseFd(outputId);
        }
        inputId = pipeIds[0];
        pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
    }
    *pidArrayPtr = pidPtr;

    /*
     * All done.  Cleanup open files lying around and then return.
     */

  cleanup:
    if (inputId != JIM_BAD_FD) {
        JimCloseFd(inputId);
    }
    if (lastOutputId != JIM_BAD_FD) {
        JimCloseFd(lastOutputId);
    }
    if (errorId != JIM_BAD_FD) {
        JimCloseFd(errorId);
    }
    Jim_Free(arg_array);

    JimRestoreEnv(save_environ);

    return numPids;

    /*
     * An error occurred.  There could have been extra files open, such
     * as pipes between children.  Clean them all up.  Detach any child
     * processes that have been created.
     */

  error:
    if ((inPipePtr != NULL) && (*inPipePtr != JIM_BAD_FD)) {
        JimCloseFd(*inPipePtr);
        *inPipePtr = JIM_BAD_FD;
    }
    if ((outPipePtr != NULL) && (*outPipePtr != JIM_BAD_FD)) {
        JimCloseFd(*outPipePtr);
        *outPipePtr = JIM_BAD_FD;
    }
    if ((errFilePtr != NULL) && (*errFilePtr != JIM_BAD_FD)) {
        JimCloseFd(*errFilePtr);
        *errFilePtr = JIM_BAD_FD;
    }
    if (pipeIds[0] != JIM_BAD_FD) {
        JimCloseFd(pipeIds[0]);
    }
    if (pipeIds[1] != JIM_BAD_FD) {
        JimCloseFd(pipeIds[1]);
    }
    if (pidPtr != NULL) {
        for (i = 0; i < numPids; i++) {
            if (pidPtr[i] != JIM_BAD_PID) {
                JimDetachPids(interp, 1, &pidPtr[i]);
            }
        }
        Jim_Free(pidPtr);
    }
    numPids = -1;
    goto cleanup;
}
예제 #29
0
/* [tcl::prefix]
 */
static int Jim_TclPrefixCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    Jim_Obj *objPtr;
    Jim_Obj *stringObj;
    int option;
    static const char * const options[] = { "match", "all", "longest", NULL };
    enum { OPT_MATCH, OPT_ALL, OPT_LONGEST };

    if (argc < 2) {
        Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arg ...?");
        return JIM_ERR;
    }
    if (Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
        return Jim_CheckShowCommands(interp, argv[1], options);

    switch (option) {
        case OPT_MATCH:{
            int i;
            int ret;
            int tablesize;
            const char **table;
            Jim_Obj *tableObj;
            Jim_Obj *errorObj = NULL;
            const char *message = "option";
            static const char * const matchoptions[] = { "-error", "-exact", "-message", NULL };
            enum { OPT_MATCH_ERROR, OPT_MATCH_EXACT, OPT_MATCH_MESSAGE };
            int flags = JIM_ERRMSG | JIM_ENUM_ABBREV;

            if (argc < 4) {
                Jim_WrongNumArgs(interp, 2, argv, "?options? table string");
                return JIM_ERR;
            }
            tableObj = argv[argc - 2];
            stringObj = argv[argc - 1];
            argc -= 2;
            for (i = 2; i < argc; i++) {
                int matchoption;
                if (Jim_GetEnum(interp, argv[i], matchoptions, &matchoption, "option", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
                    return JIM_ERR;
                switch (matchoption) {
                    case OPT_MATCH_EXACT:
                        flags &= ~JIM_ENUM_ABBREV;
                        break;

                    case OPT_MATCH_ERROR:
                        if (++i == argc) {
                            Jim_SetResultString(interp, "missing error options", -1);
                            return JIM_ERR;
                        }
                        errorObj = argv[i];
                        if (Jim_Length(errorObj) % 2) {
                            Jim_SetResultString(interp, "error options must have an even number of elements", -1);
                            return JIM_ERR;
                        }
                        break;

                    case OPT_MATCH_MESSAGE:
                        if (++i == argc) {
                            Jim_SetResultString(interp, "missing message", -1);
                            return JIM_ERR;
                        }
                        message = Jim_String(argv[i]);
                        break;
                }
            }
            /* Do the match */
            tablesize = Jim_ListLength(interp, tableObj);
            table = Jim_Alloc((tablesize + 1) * sizeof(*table));
            for (i = 0; i < tablesize; i++) {
                Jim_ListIndex(interp, tableObj, i, &objPtr, JIM_NONE);
                table[i] = Jim_String(objPtr);
            }
            table[i] = NULL;

            ret = Jim_GetEnum(interp, stringObj, table, &i, message, flags);
            Jim_Free(table);
            if (ret == JIM_OK) {
                Jim_ListIndex(interp, tableObj, i, &objPtr, JIM_NONE);
                Jim_SetResult(interp, objPtr);
                return JIM_OK;
            }
            if (tablesize == 0) {
                Jim_SetResultFormatted(interp, "bad %s \"%#s\": no valid options", message, stringObj);
                return JIM_ERR;
            }
            if (errorObj) {
                if (Jim_Length(errorObj) == 0) {
                    Jim_SetEmptyResult(interp);
                    return JIM_OK;
                }
                /* Do this the easy way. Build a list to evaluate */
                objPtr = Jim_NewStringObj(interp, "return -level 0 -code error", -1);
                Jim_ListAppendList(interp, objPtr, errorObj);
                Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
                return Jim_EvalObjList(interp, objPtr);
            }
            return JIM_ERR;
        }

        case OPT_ALL:
            if (argc != 4) {
                Jim_WrongNumArgs(interp, 2, argv, "table string");
                return JIM_ERR;
            }
            else {
                int i;
                int listlen = Jim_ListLength(interp, argv[2]);
                objPtr = Jim_NewListObj(interp, NULL, 0);
                for (i = 0; i < listlen; i++) {
                    Jim_Obj *valObj = Jim_ListGetIndex(interp, argv[2], i);
                    if (Jim_StringCompareLenObj(interp, argv[3], valObj, 0) == 0) {
                        Jim_ListAppendElement(interp, objPtr, valObj);
                    }
                }
                Jim_SetResult(interp, objPtr);
                return JIM_OK;
            }

        case OPT_LONGEST:
            if (argc != 4) {
                Jim_WrongNumArgs(interp, 2, argv, "table string");
                return JIM_ERR;
            }
            else if (Jim_ListLength(interp, argv[2])) {
                const char *longeststr = NULL;
                int longestlen = 0;
                int i;
                int listlen = Jim_ListLength(interp, argv[2]);

                stringObj = argv[3];

                for (i = 0; i < listlen; i++) {
                    Jim_Obj *valObj = Jim_ListGetIndex(interp, argv[2], i);

                    if (Jim_StringCompareLenObj(interp, stringObj, valObj, 0)) {
                        /* Does not begin with 'string' */
                        continue;
                    }

                    if (longeststr == NULL) {
                        longestlen = Jim_Utf8Length(interp, valObj);
                        longeststr = Jim_String(valObj);
                    }
                    else {
                        longestlen = JimStringCommonLength(longeststr, longestlen, Jim_String(valObj), Jim_Utf8Length(interp, valObj));
                    }
                }
                if (longeststr) {
                    Jim_SetResultString(interp, longeststr, longestlen);
                }
                return JIM_OK;
            }
    }
    return JIM_ERR; /* Cannot ever get here */
}
예제 #30
0
파일: jim-regexp.c 프로젝트: BruceZu/jimtcl
int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    int opt_indices = 0;
    int opt_all = 0;
    int opt_inline = 0;
    regex_t *regex;
    int match, i, j;
    int offset = 0;
    regmatch_t *pmatch = NULL;
    int source_len;
    int result = JIM_OK;
    const char *pattern;
    const char *source_str;
    int num_matches = 0;
    int num_vars;
    Jim_Obj *resultListObj = NULL;
    int regcomp_flags = 0;
    int eflags = 0;
    int option;
    enum {
        OPT_INDICES,  OPT_NOCASE, OPT_LINE, OPT_ALL, OPT_INLINE, OPT_START, OPT_END
    };
    static const char * const options[] = {
        "-indices", "-nocase", "-line", "-all", "-inline", "-start", "--", NULL
    };

    if (argc < 3) {
      wrongNumArgs:
        Jim_WrongNumArgs(interp, 1, argv,
            "?-switch ...? exp string ?matchVar? ?subMatchVar ...?");
        return JIM_ERR;
    }

    for (i = 1; i < argc; i++) {
        const char *opt = Jim_String(argv[i]);

        if (*opt != '-') {
            break;
        }
        if (Jim_GetEnum(interp, argv[i], options, &option, "switch", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
            return JIM_ERR;
        }
        if (option == OPT_END) {
            i++;
            break;
        }
        switch (option) {
            case OPT_INDICES:
                opt_indices = 1;
                break;

            case OPT_NOCASE:
                regcomp_flags |= REG_ICASE;
                break;

            case OPT_LINE:
                regcomp_flags |= REG_NEWLINE;
                break;

            case OPT_ALL:
                opt_all = 1;
                break;

            case OPT_INLINE:
                opt_inline = 1;
                break;

            case OPT_START:
                if (++i == argc) {
                    goto wrongNumArgs;
                }
                if (Jim_GetIndex(interp, argv[i], &offset) != JIM_OK) {
                    return JIM_ERR;
                }
                break;
        }
    }
    if (argc - i < 2) {
        goto wrongNumArgs;
    }

    regex = SetRegexpFromAny(interp, argv[i], regcomp_flags);
    if (!regex) {
        return JIM_ERR;
    }

    pattern = Jim_String(argv[i]);
    source_str = Jim_GetString(argv[i + 1], &source_len);

    num_vars = argc - i - 2;

    if (opt_inline) {
        if (num_vars) {
            Jim_SetResultString(interp, "regexp match variables not allowed when using -inline",
                -1);
            result = JIM_ERR;
            goto done;
        }
        num_vars = regex->re_nsub + 1;
    }

    pmatch = Jim_Alloc((num_vars + 1) * sizeof(*pmatch));

    /* If an offset has been specified, adjust for that now.
     * If it points past the end of the string, point to the terminating null
     */
    if (offset) {
        if (offset < 0) {
            offset += source_len + 1;
        }
        if (offset > source_len) {
            source_str += source_len;
        }
        else if (offset > 0) {
            source_str += offset;
        }
        eflags |= REG_NOTBOL;
    }

    if (opt_inline) {
        resultListObj = Jim_NewListObj(interp, NULL, 0);
    }

  next_match:
    match = regexec(regex, source_str, num_vars + 1, pmatch, eflags);
    if (match >= REG_BADPAT) {
        char buf[100];

        regerror(match, regex, buf, sizeof(buf));
        Jim_SetResultFormatted(interp, "error while matching pattern: %s", buf);
        result = JIM_ERR;
        goto done;
    }

    if (match == REG_NOMATCH) {
        goto done;
    }

    num_matches++;

    if (opt_all && !opt_inline) {
        /* Just count the number of matches, so skip the substitution h */
        goto try_next_match;
    }

    /*
     * If additional variable names have been specified, return
     * index information in those variables.
     */

    j = 0;
    for (i += 2; opt_inline ? j < num_vars : i < argc; i++, j++) {
        Jim_Obj *resultObj;

        if (opt_indices) {
            resultObj = Jim_NewListObj(interp, NULL, 0);
        }
        else {
            resultObj = Jim_NewStringObj(interp, "", 0);
        }

        if (pmatch[j].rm_so == -1) {
            if (opt_indices) {
                Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1));
                Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1));
            }
        }
        else {
            int len = pmatch[j].rm_eo - pmatch[j].rm_so;

            if (opt_indices) {
                Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp,
                        offset + pmatch[j].rm_so));
                Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp,
                        offset + pmatch[j].rm_so + len - 1));
            }
            else {
                Jim_AppendString(interp, resultObj, source_str + pmatch[j].rm_so, len);
            }
        }

        if (opt_inline) {
            Jim_ListAppendElement(interp, resultListObj, resultObj);
        }
        else {
            /* And now set the result variable */
            result = Jim_SetVariable(interp, argv[i], resultObj);

            if (result != JIM_OK) {
                Jim_FreeObj(interp, resultObj);
                break;
            }
        }
    }

  try_next_match:
    if (opt_all && (pattern[0] != '^' || (regcomp_flags & REG_NEWLINE)) && *source_str) {
        if (pmatch[0].rm_eo) {
            offset += pmatch[0].rm_eo;
            source_str += pmatch[0].rm_eo;
        }
        else {
            source_str++;
            offset++;
        }
        if (*source_str) {
            eflags = REG_NOTBOL;
            goto next_match;
        }
    }

  done:
    if (result == JIM_OK) {
        if (opt_inline) {
            Jim_SetResult(interp, resultListObj);
        }
        else {
            Jim_SetResultInt(interp, num_matches);
        }
    }

    Jim_Free(pmatch);
    return result;
}