Esempio n. 1
0
File: tcltk.c Progetto: kmillar/rho
SEXP RTcl_ObjAsCharVector(SEXP args)
{
    int count;
    Tcl_Obj **elem, *obj;
    int ret, i;
    SEXP ans;

    obj = (Tcl_Obj *) R_ExternalPtrAddr(CADR(args));
    if (!obj) error(_("invalid tclObj -- perhaps saved from another session?"));
    ret = Tcl_ListObjGetElements(RTcl_interp, obj, &count, &elem);
    if (ret != TCL_OK)
	return RTcl_StringFromObj(args);

    PROTECT(ans = allocVector(STRSXP, count));
    for (i = 0 ; i < count ; i++) {
	char *s;
	Tcl_DString s_ds;
	Tcl_DStringInit(&s_ds);
	/* FIXME: could use UTF-8 here */
	s = Tcl_UtfToExternalDString(NULL,
				     (Tcl_GetStringFromObj(elem[i], NULL)),
				     -1, &s_ds);
	SET_STRING_ELT(ans, i, mkChar(s));
	Tcl_DStringFree(&s_ds);
    }
    UNPROTECT(1);
    return ans;
}
Esempio n. 2
0
Tcl_PackageInitProc *
TclpFindSymbol(
    Tcl_Interp *interp,		/* Place to put error messages. */
    Tcl_LoadHandle loadHandle,	/* Value from TcpDlopen(). */
    const char *symbol)		/* Symbol to look up. */
{
    const char *native;
    Tcl_DString newName, ds;
    void *handle = (void *) loadHandle;
    Tcl_PackageInitProc *proc;

    /*
     * Some platforms still add an underscore to the beginning of symbol
     * names. If we can't find a name without an underscore, try again with
     * the underscore.
     */

    native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
    proc = (Tcl_PackageInitProc *) dlsym(handle,	/* INTL: Native. */
	    native);
    if (proc == NULL) {
	Tcl_DStringInit(&newName);
	Tcl_DStringAppend(&newName, "_", 1);
	native = Tcl_DStringAppend(&newName, native, -1);
	proc = (Tcl_PackageInitProc *) dlsym(handle,	/* INTL: Native. */
		native);
	Tcl_DStringFree(&newName);
    }
    Tcl_DStringFree(&ds);

    return proc;
}
Esempio n. 3
0
TclFile
TclpCreateTempFile(
    const char *contents)	/* String to write into temp file, or NULL. */
{
    int fd = TclUnixOpenTemporaryFile(NULL, NULL, NULL, NULL);

    if (fd == -1) {
        return NULL;
    }
    fcntl(fd, F_SETFD, FD_CLOEXEC);
    if (contents != NULL) {
        Tcl_DString dstring;
        char *native;

        native = Tcl_UtfToExternalDString(NULL, contents, -1, &dstring);
        if (write(fd, native, Tcl_DStringLength(&dstring)) == -1) {
            close(fd);
            Tcl_DStringFree(&dstring);
            return NULL;
        }
        Tcl_DStringFree(&dstring);
        TclOSseek(fd, (Tcl_SeekOffset) 0, SEEK_SET);
    }
    return MakeFile(fd);
}
Esempio n. 4
0
File: tcltk.c Progetto: kmillar/rho
static Tcl_Obj * tk_eval(const char *cmd)
{
    char *cmd_utf8;
    Tcl_DString  cmd_utf8_ds;

    Tcl_DStringInit(&cmd_utf8_ds);
    cmd_utf8 = Tcl_ExternalToUtfDString(NULL, cmd, -1, &cmd_utf8_ds);
    if (Tcl_Eval(RTcl_interp, cmd_utf8) == TCL_ERROR)
    {
	char p[512];
	if (strlen(Tcl_GetStringResult(RTcl_interp)) > 500)
	    strcpy(p, _("tcl error.\n"));
	else {
	    char *res;
	    Tcl_DString  res_ds;

	    Tcl_DStringInit(&res_ds);
	    res = Tcl_UtfToExternalDString(NULL,
					   Tcl_GetStringResult(RTcl_interp),
					   -1, &res_ds);
	    snprintf(p, sizeof(p), "[tcl] %s.\n", res);
	    Tcl_DStringFree(&res_ds);
	}
	error(p);
    }
    Tcl_DStringFree(&cmd_utf8_ds);
    return Tcl_GetObjResult(RTcl_interp);
}
Esempio n. 5
0
int
TclSockGetPort(
    Tcl_Interp *interp,
    const char *string,		/* Integer or service name */
    const char *proto,		/* "tcp" or "udp", typically */
    int *portPtr)		/* Return port number */
{
    struct servent *sp;		/* Protocol info for named services */
    Tcl_DString ds;
    const char *native;

    if (Tcl_GetInt(NULL, string, portPtr) != TCL_OK) {
	/*
	 * Don't bother translating 'proto' to native.
	 */

	native = Tcl_UtfToExternalDString(NULL, string, -1, &ds);
	sp = getservbyname(native, proto);		/* INTL: Native. */
	Tcl_DStringFree(&ds);
	if (sp != NULL) {
	    *portPtr = ntohs((unsigned short) sp->s_port);
	    return TCL_OK;
	}
    }
    if (Tcl_GetInt(interp, string, portPtr) != TCL_OK) {
	return TCL_ERROR;
    }
    if (*portPtr > 0xFFFF) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"couldn't open socket: port number too high", -1));
	return TCL_ERROR;
    }
    return TCL_OK;
}
Esempio n. 6
0
char *
TclpReadlink(
    const char *path,		/* Path of file to readlink (UTF-8). */
    Tcl_DString *linkPtr)	/* Uninitialized or free DString filled with
				 * contents of link (UTF-8). */
{
#ifndef DJGPP
    char link[MAXPATHLEN];
    int length;
    const char *native;
    Tcl_DString ds;

    native = Tcl_UtfToExternalDString(NULL, path, -1, &ds);
    length = readlink(native, link, sizeof(link));	/* INTL: Native. */
    Tcl_DStringFree(&ds);

    if (length < 0) {
	return NULL;
    }

    Tcl_ExternalToUtfDString(NULL, link, length, linkPtr);
    return Tcl_DStringValue(linkPtr);
#else
    return NULL;
#endif /* !DJGPP */
}
Esempio n. 7
0
TclFile
TclpOpenFile(
    const char *fname,		/* The name of the file to open. */
    int mode)			/* In what mode to open the file? */
{
    int fd;
    const char *native;
    Tcl_DString ds;

    native = Tcl_UtfToExternalDString(NULL, fname, -1, &ds);
    fd = TclOSopen(native, mode, 0666);			/* INTL: Native. */
    Tcl_DStringFree(&ds);
    if (fd != -1) {
	fcntl(fd, F_SETFD, FD_CLOEXEC);

	/*
	 * If the file is being opened for writing, seek to the end so we can
	 * append to any data already in the file.
	 */

	if ((mode & O_WRONLY) && !(mode & O_APPEND)) {
	    TclOSseek(fd, (Tcl_SeekOffset) 0, SEEK_END);
	}

	/*
	 * Increment the fd so it can't be 0, which would conflict with the
	 * NULL return for errors.
	 */

	return MakeFile(fd);
    }
    return NULL;
}
int
TclpDlopen(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Obj *pathPtr,		/* Name of the file containing the desired
				 * code (UTF-8). */
    Tcl_LoadHandle *loadHandle,	/* Filled with token for dynamically loaded
				 * file which will be passed back to
				 * (*unloadProcPtr)() to unload the file. */
    Tcl_FSUnloadFileProc **unloadProcPtr)
				/* Filled with address of Tcl_FSUnloadFileProc
				 * function which should be used for this
				 * file. */
{
    shl_t handle;
    CONST char *native;
    char *fileName = Tcl_GetString(pathPtr);

    /*
     * The flags below used to be BIND_IMMEDIATE; they were changed at the
     * suggestion of Wolfgang Kechel ([email protected]): "This enables
     * verbosity for missing symbols when loading a shared lib and allows to
     * load libtk8.0.sl into tclsh8.0 without problems.  In general, this
     * delays resolving symbols until they are actually needed.  Shared libs
     * do no longer need all libraries linked in when they are build."
     */

    /*
     * First try the full path the user gave us.  This is particularly
     * important if the cwd is inside a vfs, and we are trying to load using a
     * relative path.
     */

    native = Tcl_FSGetNativePath(pathPtr);
    handle = shl_load(native, BIND_DEFERRED|BIND_VERBOSE, 0L);

    if (handle == NULL) {
	/*
	 * Let the OS loader examine the binary search path for whatever
	 * string the user gave us which hopefully refers to a file on the
	 * binary path.
	 */

	Tcl_DString ds;

	native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
	handle = shl_load(native, BIND_DEFERRED|BIND_VERBOSE|DYNAMIC_PATH, 0L);
	Tcl_DStringFree(&ds);
    }

    if (handle == NULL) {
	Tcl_AppendResult(interp, "couldn't load file \"", fileName, "\": ",
		Tcl_PosixError(interp), (char *) NULL);
	return TCL_ERROR;
    }
    *loadHandle = (Tcl_LoadHandle) handle;
    *unloadProcPtr = &TclpUnloadFile;
    return TCL_OK;
}
Esempio n. 9
0
File: tcltk.c Progetto: kmillar/rho
SEXP dotTclObjv(SEXP args)
{
    SEXP t,
	avec = CADR(args),
	nm = getAttrib(avec, R_NamesSymbol);
    int objc, i, result;
    Tcl_Obj **objv;
    const void *vmax = vmaxget();

    for (objc = 0, i = 0; i < length(avec); i++){
	if (!isNull(VECTOR_ELT(avec, i)))
	    objc++;
	if (!isNull(nm) && strlen(translateChar(STRING_ELT(nm, i))))
	    objc++;
    }

    objv = (Tcl_Obj **) R_alloc(objc, sizeof(Tcl_Obj *));

    for (objc = i = 0; i < length(avec); i++){
	const char *s;
	char *tmp;
	if (!isNull(nm) && strlen(s = translateChar(STRING_ELT(nm, i)))){
	    tmp = calloc(strlen(s)+2, sizeof(char));
	    *tmp = '-';
	    strcpy(tmp+1, s);
	    objv[objc++] = Tcl_NewStringObj(tmp, -1);
	    free(tmp);
	}
	if (!isNull(t = VECTOR_ELT(avec, i)))
	    objv[objc++] = (Tcl_Obj *) R_ExternalPtrAddr(t);
    }

    for (i = objc; i--; ) Tcl_IncrRefCount(objv[i]);
    result = Tcl_EvalObjv(RTcl_interp, objc, objv, 0);
    for (i = objc; i--; ) Tcl_DecrRefCount(objv[i]);

    if (result == TCL_ERROR)
    {
	char p[512];
	if (strlen(Tcl_GetStringResult(RTcl_interp)) > 500)
	    strcpy(p, _("tcl error.\n"));
	else {
	    char *res;
	    Tcl_DString  res_ds;
	    Tcl_DStringInit(&res_ds);
	    res = Tcl_UtfToExternalDString(NULL,
					   Tcl_GetStringResult(RTcl_interp),
					   -1, &res_ds);
	    snprintf(p, sizeof(p), "[tcl] %s.\n", res);
	    Tcl_DStringFree(&res_ds);
	}
	error(p);
    }

    SEXP res = makeRTclObject(Tcl_GetObjResult(RTcl_interp));
    vmaxset(vmax);
    return res;
}
Esempio n. 10
0
int
TclpDlopen(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Obj *pathPtr,		/* Name of the file containing the desired
				 * code (UTF-8). */
    Tcl_LoadHandle *loadHandle,	/* Filled with token for dynamically loaded
				 * file which will be passed back to
				 * (*unloadProcPtr)() to unload the file. */
    Tcl_FSUnloadFileProc **unloadProcPtr)
				/* Filled with address of Tcl_FSUnloadFileProc
				 * function which should be used for this
				 * file. */
{
    void *handle;
    const char *native;

    /*
     * First try the full path the user gave us. This is particularly
     * important if the cwd is inside a vfs, and we are trying to load using a
     * relative path.
     */

    native = Tcl_FSGetNativePath(pathPtr);
    handle = dlopen(native, RTLD_NOW | RTLD_GLOBAL);
    if (handle == NULL) {
	/*
	 * Let the OS loader examine the binary search path for whatever
	 * string the user gave us which hopefully refers to a file on the
	 * binary path.
	 */

	Tcl_DString ds;
	char *fileName = Tcl_GetString(pathPtr);

	native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
	handle = dlopen(native, RTLD_NOW | RTLD_GLOBAL);
	Tcl_DStringFree(&ds);
    }

    if (handle == NULL) {
	/*
	 * Write the string to a variable first to work around a compiler bug
	 * in the Sun Forte 6 compiler. [Bug 1503729]
	 */

	const char *errorStr = dlerror();

	Tcl_AppendResult(interp, "couldn't load file \"",
		Tcl_GetString(pathPtr), "\": ", errorStr, NULL);
	return TCL_ERROR;
    }

    *unloadProcPtr = &TclpUnloadFile;
    *loadHandle = (Tcl_LoadHandle) handle;
    return TCL_OK;
}
Esempio n. 11
0
int lexinput_tktext(char *buf, int max_size, int buf_size, void *index1, void *index2)
{
	int length, nbytes;
	Tcl_DString internal, temp;

	static int first = 1;
	static Tcl_DString external;
	static Tcl_Encoding encoding;

	if(first) {
		/* The lexers require ASCII encoding. */
		encoding = Tcl_GetEncoding(NULL, "ascii");
		if(encoding == NULL) {
			/* No ASCII encoding available. */
			return 0;
		}
		Tcl_DStringInit(&external);
		first = 0;
	}
	Tcl_DStringInit(&internal);

	if(Tcl_DStringLength(&external) == 0) {
		/* Translate the text to `external'. */
		if(tk_text_buffer(&internal, buf_size, index1, index2) > 0) {
			Tcl_UtfToExternalDString(encoding, Tcl_DStringValue(&internal), Tcl_DStringLength(&internal), &external);
		} else {
			return 0;
		}
	}

	/* Fill up the user-provided buffer as much as possible. */
	length = Tcl_DStringLength(&external);
	nbytes = (length > max_size) ? max_size : length;
	memcpy(buf, Tcl_DStringValue(&external), nbytes);

	/* I wish DStrings had a copy constructor. In fact, sometimes I wish
	 Tcl was written in C++. */
	if(length > nbytes) {
		Tcl_DStringInit(&temp);
		Tcl_DStringAppend(&temp, Tcl_DStringValue(&external) + nbytes, length - nbytes);
		Tcl_DStringFree(&external);
		Tcl_DStringInit(&external);
		Tcl_DStringAppend(&external, Tcl_DStringValue(&temp), Tcl_DStringLength(&temp));
		Tcl_DStringFree(&temp);
	} else {
		Tcl_DStringFree(&external);
		Tcl_DStringInit(&external);
	}

	/* Clean up. */
	Tcl_DStringFree(&internal);

	return nbytes;
}
Esempio n. 12
0
int
Ns_ConnFlush(Ns_Conn *conn, char *buf, int len, int stream)
{
    Conn *connPtr = (Conn *) conn;
    NsServer *servPtr = connPtr->servPtr;
    Tcl_Encoding encoding;
    Tcl_DString  enc, gzip;
    char *ahdr;
    int status;

    Tcl_DStringInit(&enc);
    Tcl_DStringInit(&gzip);
    if (len < 0) {
	len = strlen(buf);
    }

    /*
     * Encode content to the expected charset.
     */

    encoding = Ns_ConnGetEncoding(conn);
    if (encoding != NULL) {
	Tcl_UtfToExternalDString(encoding, buf, len, &enc);
	buf = enc.string;
	len = enc.length;
    }

    /*
     * GZIP the content when not streaming if enabled and the content
     * length is above the minimum.
     */

    if (!stream
	    && (conn->flags & NS_CONN_GZIP)
	    && (servPtr->opts.flags & SERV_GZIP)
	    && (len > (int) servPtr->opts.gzipmin)
	    && (ahdr = Ns_SetIGet(conn->headers, "Accept-Encoding")) != NULL
	    && strstr(ahdr, "gzip") != NULL
	    && Ns_Gzip(buf, len, servPtr->opts.gziplevel, &gzip) == NS_OK) {
	buf = gzip.string;
	len = gzip.length;
	Ns_ConnCondSetHeaders(conn, "Content-Encoding", "gzip");
    }

    /*
     * Flush content.
     */

    status = Ns_ConnFlushDirect(conn, buf, len, stream);
    Tcl_DStringFree(&enc);
    Tcl_DStringFree(&gzip);
    return status;
}
Esempio n. 13
0
char *
Tcl_WinUtfToTChar(
    const char *string,
    int len,
    Tcl_DString *dsPtr)
{
    if (!winTCharEncoding) {
	winTCharEncoding = Tcl_GetEncoding(0, "unicode");
    }
    return Tcl_UtfToExternalDString(winTCharEncoding,
	    string, len, dsPtr);
}
Esempio n. 14
0
ClientData
TclNativeCreateNativeRep(
    Tcl_Obj *pathPtr)
{
    char *nativePathPtr;
    const char *str;
    Tcl_DString ds;
    Tcl_Obj *validPathPtr;
    size_t len;

    if (TclFSCwdIsNative()) {
	/*
	 * The cwd is native, which means we can use the translated path
	 * without worrying about normalization (this will also usually be
	 * shorter so the utf-to-external conversion will be somewhat faster).
	 */

	validPathPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
	if (validPathPtr == NULL) {
	    return NULL;
	}
    } else {
	/*
	 * Make sure the normalized path is set.
	 */

	validPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
	if (validPathPtr == NULL) {
	    return NULL;
	}
	Tcl_IncrRefCount(validPathPtr);
    }

    str = TclGetString(validPathPtr);
    len = validPathPtr->length;
    Tcl_UtfToExternalDString(NULL, str, len, &ds);
    len = Tcl_DStringLength(&ds) + sizeof(char);
    if (strlen(Tcl_DStringValue(&ds)) < len - sizeof(char)) {
	/* See bug [3118489]: NUL in filenames */
	Tcl_DecrRefCount(validPathPtr);
	Tcl_DStringFree(&ds);
	return NULL;
    }
    Tcl_DecrRefCount(validPathPtr);
    nativePathPtr = ckalloc(len);
    memcpy(nativePathPtr, Tcl_DStringValue(&ds), (size_t) len);

    Tcl_DStringFree(&ds);
    return nativePathPtr;
}
Esempio n. 15
0
static void *
FindSymbol(
    Tcl_Interp *interp,		/* Place to put error messages. */
    Tcl_LoadHandle loadHandle,	/* Value from TcpDlopen(). */
    const char *symbol)		/* Symbol to look up. */
{
    const char *native;		/* Name of the library to be loaded, in
				 * system encoding */
    Tcl_DString newName, ds;	/* Buffers for converting the name to
				 * system encoding and prepending an
				 * underscore*/
    void *handle = (void *) loadHandle->clientData;
				/* Native handle to the loaded library */
    void *proc;			/* Address corresponding to the resolved
				 * symbol */

    /*
     * Some platforms still add an underscore to the beginning of symbol
     * names. If we can't find a name without an underscore, try again with
     * the underscore.
     */

    native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
    proc = dlsym(handle, native);	/* INTL: Native. */
    if (proc == NULL) {
	Tcl_DStringInit(&newName);
	TclDStringAppendLiteral(&newName, "_");
	native = Tcl_DStringAppend(&newName, native, -1);
	proc = dlsym(handle, native);	/* INTL: Native. */
	Tcl_DStringFree(&newName);
    }
    Tcl_DStringFree(&ds);
    if (proc == NULL) {
	const char *errorStr = dlerror();

	if (interp) {
	    if (!errorStr) {
		errorStr = "unknown";
	    }
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "cannot find symbol \"%s\": %s", symbol, errorStr));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol,
		    NULL);
	}
    }
    return proc;
}
Esempio n. 16
0
char *
Ns_EncodeUrlWithEncoding(Ns_DString *dsPtr, char *string, Tcl_Encoding encoding)
{
    register int   i, n;
    register char *p, *q;
    Tcl_DString  ds;

    Tcl_DStringInit(&ds);
    if (encoding != NULL) {
        string = Tcl_UtfToExternalDString(encoding, string, -1, &ds);
    }

    /*
     * Determine and set the required dstring length.
     */

    p = string;
    n = 0;
    while ((i = UCHAR(*p)) != 0) {
	n += enc[i].len;
	++p;
    }
    i = dsPtr->length;
    Ns_DStringSetLength(dsPtr, dsPtr->length + n);

    /*
     * Copy the result directly to the pre-sized dstring.
     */

    q = dsPtr->string + i;
    p = string;
    while ((i = UCHAR(*p)) != 0) {
	if (UCHAR(*p) == ' ') {
	    *q++ = '+';
	} else if (enc[i].str == NULL) {
	    *q++ = *p;
	} else {
	    *q++ = '%';
	    *q++ = enc[i].str[0];
	    *q++ = enc[i].str[1];
	}
	++p;
    }
    Tcl_DStringFree(&ds);
    return dsPtr->string;
}
Esempio n. 17
0
int
Ns_WriteCharConn(Ns_Conn *conn, char *buf, int len)
{
    Tcl_Encoding    encoding;
    Tcl_DString	    enc;
    int		    status;

    Tcl_DStringInit(&enc);
    encoding = Ns_ConnGetEncoding(conn);
    if (encoding != NULL) {
	Tcl_UtfToExternalDString(encoding, buf, len, &enc);
	buf = enc.string;
	len = enc.length;
    }
    status = Ns_WriteConn(conn, buf, len);
    Tcl_DStringFree(&enc);
    return status;
}
Esempio n. 18
0
File: tcltk.c Progetto: kmillar/rho
SEXP RTcl_StringFromObj(SEXP args)
{
    char *str;
    SEXP so;
    char *s;
    Tcl_DString s_ds;
    Tcl_Obj *obj;

    obj = (Tcl_Obj *) R_ExternalPtrAddr(CADR(args));
    if (!obj) error(_("invalid tclObj -- perhaps saved from another session?"));
    Tcl_DStringInit(&s_ds);
    str = Tcl_GetStringFromObj(obj, NULL);
    /* FIXME: could use UTF-8 here */
    s = Tcl_UtfToExternalDString(NULL, str, -1, &s_ds);
    so = mkString(s);
    Tcl_DStringFree(&s_ds);
    return(so);
}
Esempio n. 19
0
ClientData
TclNativeCreateNativeRep(
    Tcl_Obj *pathPtr)
{
    char *nativePathPtr;
    Tcl_DString ds;
    Tcl_Obj *validPathPtr;
    int len;
    char *str;

    if (TclFSCwdIsNative()) {
        /*
         * The cwd is native, which means we can use the translated path
         * without worrying about normalization (this will also usually be
         * shorter so the utf-to-external conversion will be somewhat faster).
         */

        validPathPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
        if (validPathPtr == NULL) {
            return NULL;
        }
    } else {
        /*
         * Make sure the normalized path is set.
         */

        validPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
        if (validPathPtr == NULL) {
            return NULL;
        }
        Tcl_IncrRefCount(validPathPtr);
    }

    str = Tcl_GetStringFromObj(validPathPtr, &len);
    Tcl_UtfToExternalDString(NULL, str, len, &ds);
    len = Tcl_DStringLength(&ds) + sizeof(char);
    Tcl_DecrRefCount(validPathPtr);
    nativePathPtr = ckalloc((unsigned) len);
    memcpy((void*)nativePathPtr, (void*)Tcl_DStringValue(&ds), (size_t) len);

    Tcl_DStringFree(&ds);
    return (ClientData)nativePathPtr;
}
Esempio n. 20
0
const char *
TclpGetUserHome(
    const char *name,		/* User name for desired home directory. */
    Tcl_DString *bufferPtr)	/* Uninitialized or free DString filled with
				 * name of user's home directory. */
{
    struct passwd *pwPtr;
    Tcl_DString ds;
    const char *native = Tcl_UtfToExternalDString(NULL, name, -1, &ds);

    pwPtr = TclpGetPwNam(native);			/* INTL: Native. */
    Tcl_DStringFree(&ds);

    if (pwPtr == NULL) {
	return NULL;
    }
    Tcl_ExternalToUtfDString(NULL, pwPtr->pw_dir, -1, bufferPtr);
    return Tcl_DStringValue(bufferPtr);
}
Esempio n. 21
0
File: tcltk.c Progetto: kmillar/rho
SEXP dotTclcallback(SEXP args)
{
    SEXP ans, callback = CADR(args), env;
    char buff[BUFFLEN];
    char *s;
    Tcl_DString s_ds;

    if (isFunction(callback))
        callback_closure(buff, BUFFLEN, callback);
    else if (isLanguage(callback)) {
        env = CADDR(args);
        callback_lang(buff, BUFFLEN, callback, env);
    }
    else
    	error(_("argument is not of correct type"));

    Tcl_DStringInit(&s_ds);
    s = Tcl_UtfToExternalDString(NULL, buff, -1, &s_ds);
    ans = mkString(s);
    Tcl_DStringFree(&s_ds);
    return ans;
}
Esempio n. 22
0
TclFile
TclpCreateTempFile(
    const char *contents)	/* String to write into temp file, or NULL. */
{
    char fileName[L_tmpnam + 9];
    const char *native;
    Tcl_DString dstring;
    int fd;

    /*
     * We should also check against making more then TMP_MAX of these.
     */

    strcpy(fileName, P_tmpdir);				/* INTL: Native. */
    if (fileName[strlen(fileName) - 1] != '/') {
	strcat(fileName, "/");				/* INTL: Native. */
    }
    strcat(fileName, "tclXXXXXX");
    fd = mkstemp(fileName);				/* INTL: Native. */
    if (fd == -1) {
	return NULL;
    }
    fcntl(fd, F_SETFD, FD_CLOEXEC);
    unlink(fileName);					/* INTL: Native. */

    if (contents != NULL) {
	native = Tcl_UtfToExternalDString(NULL, contents, -1, &dstring);
	if (write(fd, native, strlen(native)) == -1) {
	    close(fd);
	    Tcl_DStringFree(&dstring);
	    return NULL;
	}
	Tcl_DStringFree(&dstring);
	TclOSseek(fd, (Tcl_SeekOffset) 0, SEEK_SET);
    }
    return MakeFile(fd);
}
Esempio n. 23
0
void
TkSuspendClipboard()
{
    TkClipboardTarget *targetPtr;
    TkClipboardBuffer *cbPtr;
    TkDisplay *dispPtr;
    char *buffer, *p, *endPtr, *buffPtr;
    long length;

    dispPtr = TkGetDisplayList();
    if ((dispPtr == NULL) || !dispPtr->clipboardActive) {
	return;
    }

    for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;
	    targetPtr = targetPtr->nextPtr) {
	if (targetPtr->type == XA_STRING)
	    break;
    }
    if (targetPtr != NULL) {
	Tcl_DString encodedText;

	length = 0;
	for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;
		cbPtr = cbPtr->nextPtr) {
	    length += cbPtr->length;
	}

	buffer = ckalloc(length);
	buffPtr = buffer;
	for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;
		cbPtr = cbPtr->nextPtr) {
	    for (p = cbPtr->buffer, endPtr = p + cbPtr->length;
		    p < endPtr; p++) {
		if (*p == '\n') {
		    *buffPtr++ = '\r';
		} else {
		    *buffPtr++ = *p;
		}
	    }
	}

	ZeroScrap();
	Tcl_UtfToExternalDString(NULL, buffer, length, &encodedText);
	PutScrap(Tcl_DStringLength(&encodedText), 'TEXT',
		Tcl_DStringValue(&encodedText));
	Tcl_DStringFree(&encodedText);
	ckfree(buffer);
    }

    /*
     * The system now owns the scrap.  We tell Tk that it has
     * lost the selection so that it will look for it the next time
     * it needs it.  (Window list NULL if quiting.)
     */

    if (TkGetMainInfoList() != NULL) {
	Tk_ClearSelection((Tk_Window) TkGetMainInfoList()->winPtr, 
		Tk_InternAtom((Tk_Window) TkGetMainInfoList()->winPtr,
			"CLIPBOARD"));
    }

    return;
}
Esempio n. 24
0
Tcl_Obj *
TclpObjLink(
    Tcl_Obj *pathPtr,
    Tcl_Obj *toPtr,
    int linkAction)
{
    if (toPtr != NULL) {
	const char *src = Tcl_FSGetNativePath(pathPtr);
	const char *target = NULL;

	if (src == NULL) {
	    return NULL;
	}

	/*
	 * If we're making a symbolic link and the path is relative, then we
	 * must check whether it exists _relative_ to the directory in which
	 * the src is found (not relative to the current cwd which is just not
	 * relevant in this case).
	 *
	 * If we're making a hard link, then a relative path is just converted
	 * to absolute relative to the cwd.
	 */

	if ((linkAction & TCL_CREATE_SYMBOLIC_LINK)
		&& (Tcl_FSGetPathType(toPtr) == TCL_PATH_RELATIVE)) {
	    Tcl_Obj *dirPtr, *absPtr;

	    dirPtr = TclPathPart(NULL, pathPtr, TCL_PATH_DIRNAME);
	    if (dirPtr == NULL) {
		return NULL;
	    }
	    absPtr = Tcl_FSJoinToPath(dirPtr, 1, &toPtr);
	    Tcl_IncrRefCount(absPtr);
	    if (Tcl_FSAccess(absPtr, F_OK) == -1) {
		Tcl_DecrRefCount(absPtr);
		Tcl_DecrRefCount(dirPtr);

		/*
		 * Target doesn't exist.
		 */

		errno = ENOENT;
		return NULL;
	    }

	    /*
	     * Target exists; we'll construct the relative path we want below.
	     */

	    Tcl_DecrRefCount(absPtr);
	    Tcl_DecrRefCount(dirPtr);
	} else {
	    target = Tcl_FSGetNativePath(toPtr);
	    if (target == NULL) {
		return NULL;
	    }
	    if (access(target, F_OK) == -1) {
		/*
		 * Target doesn't exist.
		 */

		errno = ENOENT;
		return NULL;
	    }
	}

	if (access(src, F_OK) != -1) {
	    /*
	     * Src exists.
	     */

	    errno = EEXIST;
	    return NULL;
	}

	/*
	 * Check symbolic link flag first, since we prefer to create these.
	 */

	if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {
	    int targetLen;
	    Tcl_DString ds;
	    Tcl_Obj *transPtr;

	    /*
	     * Now we don't want to link to the absolute, normalized path.
	     * Relative links are quite acceptable (but links to ~user are not
	     * -- these must be expanded first).
	     */

	    transPtr = Tcl_FSGetTranslatedPath(NULL, toPtr);
	    if (transPtr == NULL) {
		return NULL;
	    }
	    target = TclGetStringFromObj(transPtr, &targetLen);
	    target = Tcl_UtfToExternalDString(NULL, target, targetLen, &ds);
	    Tcl_DecrRefCount(transPtr);

	    if (symlink(target, src) != 0) {
		toPtr = NULL;
	    }
	    Tcl_DStringFree(&ds);
	} else if (linkAction & TCL_CREATE_HARD_LINK) {
	    if (link(target, src) != 0) {
		return NULL;
	    }
	} else {
	    errno = ENODEV;
	    return NULL;
	}
	return toPtr;
    } else {
	Tcl_Obj *linkPtr = NULL;

	char link[MAXPATHLEN];
	int length;
	Tcl_DString ds;
	Tcl_Obj *transPtr;

	transPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
	if (transPtr == NULL) {
	    return NULL;
	}
	Tcl_DecrRefCount(transPtr);

	length = readlink(Tcl_FSGetNativePath(pathPtr), link, sizeof(link));
	if (length < 0) {
	    return NULL;
	}

	Tcl_ExternalToUtfDString(NULL, link, length, &ds);
	linkPtr = TclDStringToObj(&ds);
	Tcl_IncrRefCount(linkPtr);
	return linkPtr;
    }
}
Esempio n. 25
0
int
TclpDlopen(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Obj *pathPtr,		/* Name of the file containing the desired
				 * code (UTF-8). */
    Tcl_LoadHandle *loadHandle,	/* Filled with token for dynamically loaded
				 * file which will be passed back to
				 * (*unloadProcPtr)() to unload the file. */
    Tcl_FSUnloadFileProc **unloadProcPtr,
				/* Filled with address of Tcl_FSUnloadFileProc
				 * function which should be used for this
				 * file. */
    int flags)
{
    void *handle;
    Tcl_LoadHandle newHandle;
    const char *native;
    int dlopenflags = 0;

    /*
     * First try the full path the user gave us. This is particularly
     * important if the cwd is inside a vfs, and we are trying to load using a
     * relative path.
     */

    native = Tcl_FSGetNativePath(pathPtr);
    /*
     * Use (RTLD_NOW|RTLD_LOCAL) as default, see [Bug #3216070]
     */
    if (flags & TCL_LOAD_GLOBAL) {
    	dlopenflags |= RTLD_GLOBAL;
    } else {
    	dlopenflags |= RTLD_LOCAL;
    }
    if (flags & TCL_LOAD_LAZY) {
    	dlopenflags |= RTLD_LAZY;
    } else {
    	dlopenflags |= RTLD_NOW;
    }
    handle = dlopen(native, dlopenflags);
    if (handle == NULL) {
	/*
	 * Let the OS loader examine the binary search path for whatever
	 * string the user gave us which hopefully refers to a file on the
	 * binary path.
	 */

	Tcl_DString ds;
	const char *fileName = Tcl_GetString(pathPtr);

	native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
	/*
	 * Use (RTLD_NOW|RTLD_LOCAL) as default, see [Bug #3216070]
	 */
	handle = dlopen(native, dlopenflags);
	Tcl_DStringFree(&ds);
    }

    if (handle == NULL) {
	/*
	 * Write the string to a variable first to work around a compiler bug
	 * in the Sun Forte 6 compiler. [Bug 1503729]
	 */

	const char *errorStr = dlerror();

	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "couldn't load file \"%s\": %s",
		    Tcl_GetString(pathPtr), errorStr));
	}
	return TCL_ERROR;
    }
    newHandle = Tcl_Alloc(sizeof(*newHandle));
    newHandle->clientData = handle;
    newHandle->findSymbolProcPtr = &FindSymbol;
    newHandle->unloadFileProcPtr = &UnloadFile;
    *unloadProcPtr = &UnloadFile;
    *loadHandle = newHandle;

    return TCL_OK;
}
Esempio n. 26
0
MODULE_SCOPE int
TclpDlopen(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Obj *pathPtr,		/* Name of the file containing the desired
				 * code (UTF-8). */
    Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
				 * file which will be passed back to
				 * (*unloadProcPtr)() to unload the file. */
    Tcl_FSUnloadFileProc **unloadProcPtr)
				/* Filled with address of Tcl_FSUnloadFileProc
				 * function which should be used for this
				 * file. */
{
    Tcl_DyldLoadHandle *dyldLoadHandle;
#if TCL_DYLD_USE_DLFCN
    void *dlHandle = NULL;
#endif
#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
    const struct mach_header *dyldLibHeader = NULL;
    Tcl_DyldModuleHandle *modulePtr = NULL;
#endif
#if TCL_DYLD_USE_NSMODULE
    NSLinkEditErrors editError;
    int errorNumber;
    const char *errorName, *objFileImageErrMsg = NULL;
#endif
    const char *errMsg = NULL;
    int result;
    Tcl_DString ds;
    char *fileName = NULL;
    const char *nativePath, *nativeFileName = NULL;

    /*
     * First try the full path the user gave us. This is particularly
     * important if the cwd is inside a vfs, and we are trying to load using a
     * relative path.
     */

    nativePath = Tcl_FSGetNativePath(pathPtr);

#if TCL_DYLD_USE_DLFCN
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040
    if (tclMacOSXDarwinRelease >= 8)
#endif
    {
	dlHandle = dlopen(nativePath, RTLD_NOW | RTLD_LOCAL);
	if (!dlHandle) {
	    /*
	     * Let the OS loader examine the binary search path for whatever
	     * string the user gave us which hopefully refers to a file on the
	     * binary path.
	     */

	    fileName = Tcl_GetString(pathPtr);
	    nativeFileName = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
	    dlHandle = dlopen(nativeFileName, RTLD_NOW | RTLD_LOCAL);
	}
	if (dlHandle) {
	    TclLoadDbgMsg("dlopen() successful");
	} else {
	    errMsg = dlerror();
	    TclLoadDbgMsg("dlopen() failed: %s", errMsg);
	}
    }
    if (!dlHandle)
#endif /* TCL_DYLD_USE_DLFCN */
    {
#if TCL_DYLD_USE_NSMODULE
	dyldLibHeader = NSAddImage(nativePath,
		NSADDIMAGE_OPTION_RETURN_ON_ERROR);
	if (dyldLibHeader) {
	    TclLoadDbgMsg("NSAddImage() successful");
	} else {
	    NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg);
	    if (editError == NSLinkEditFileAccessError) {
		/*
		 * The requested file was not found. Let the OS loader examine
		 * the binary search path for whatever string the user gave us
		 * which hopefully refers to a file on the binary path.
		 */

		if (!fileName) {
		    fileName = Tcl_GetString(pathPtr);
		    nativeFileName = Tcl_UtfToExternalDString(NULL, fileName,
			    -1, &ds);
		}
		dyldLibHeader = NSAddImage(nativeFileName,
			NSADDIMAGE_OPTION_WITH_SEARCHING |
			NSADDIMAGE_OPTION_RETURN_ON_ERROR);
		if (dyldLibHeader) {
		    TclLoadDbgMsg("NSAddImage() successful");
		} else {
		    NSLinkEditError(&editError, &errorNumber, &errorName,
			    &errMsg);
		    TclLoadDbgMsg("NSAddImage() failed: %s", errMsg);
		}
	    } else if ((editError == NSLinkEditFileFormatError
		    && errorNumber == EBADMACHO)
		    || editError == NSLinkEditOtherError){
		NSObjectFileImageReturnCode err;
		NSObjectFileImage dyldObjFileImage;
		NSModule module;

		/*
		 * The requested file was found but was not of type MH_DYLIB,
		 * attempt to load it as a MH_BUNDLE.
		 */

		err = NSCreateObjectFileImageFromFile(nativePath,
			&dyldObjFileImage);
		if (err == NSObjectFileImageSuccess && dyldObjFileImage) {
		    TclLoadDbgMsg("NSCreateObjectFileImageFromFile() "
			    "successful");
		    module = NSLinkModule(dyldObjFileImage, nativePath,
			    NSLINKMODULE_OPTION_BINDNOW
			    | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
		    NSDestroyObjectFileImage(dyldObjFileImage);
		    if (module) {
			modulePtr = (Tcl_DyldModuleHandle *)
				ckalloc(sizeof(Tcl_DyldModuleHandle));
			modulePtr->module = module;
			modulePtr->nextPtr = NULL;
			TclLoadDbgMsg("NSLinkModule() successful");
		    } else {
			NSLinkEditError(&editError, &errorNumber, &errorName,
				&errMsg);
			TclLoadDbgMsg("NSLinkModule() failed: %s", errMsg);
		    }
		} else {
		    objFileImageErrMsg = DyldOFIErrorMsg(err);
		    TclLoadDbgMsg("NSCreateObjectFileImageFromFile() failed: "
			    "%s", objFileImageErrMsg);
		}
	    }
	}
#endif /* TCL_DYLD_USE_NSMODULE */
    }
    if (0
#if TCL_DYLD_USE_DLFCN
	    || dlHandle
#endif
#if TCL_DYLD_USE_NSMODULE
	    || dyldLibHeader || modulePtr
#endif
    ) {
	dyldLoadHandle = (Tcl_DyldLoadHandle *)
		ckalloc(sizeof(Tcl_DyldLoadHandle));
#if TCL_DYLD_USE_DLFCN
	dyldLoadHandle->dlHandle = dlHandle;
#endif
#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
	dyldLoadHandle->dyldLibHeader = dyldLibHeader;
	dyldLoadHandle->modulePtr = modulePtr;
#endif
	*loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
	*unloadProcPtr = &TclpUnloadFile;
	result = TCL_OK;
    } else {
	Tcl_AppendResult(interp, errMsg, NULL);
#if TCL_DYLD_USE_NSMODULE
	if (objFileImageErrMsg) {
	    Tcl_AppendResult(interp, "\nNSCreateObjectFileImageFromFile() "
		    "error: ", objFileImageErrMsg, NULL);
	}
#endif
	result = TCL_ERROR;
    }
    if(fileName) {
	Tcl_DStringFree(&ds);
    }
    return result;
}
Esempio n. 27
0
void
TclpFindExecutable(
    const char *argv0)		/* The value of the application's argv[0]
				 * (native). */
{
    Tcl_Encoding encoding;
#ifdef __CYGWIN__
    int length;
    char buf[PATH_MAX * 2];
    char name[PATH_MAX * TCL_UTF_MAX + 1];
    GetModuleFileNameW(NULL, buf, PATH_MAX);
    cygwin_conv_path(3, buf, name, PATH_MAX);
    length = strlen(name);
    if ((length > 4) && !strcasecmp(name + length - 4, ".exe")) {
	/* Strip '.exe' part. */
	length -= 4;
    }
    encoding = Tcl_GetEncoding(NULL, NULL);
    TclSetObjNameOfExecutable(
	    Tcl_NewStringObj(name, length), encoding);
#else
    const char *name, *p;
    Tcl_StatBuf statBuf;
    Tcl_DString buffer, nameString, cwd, utfName;

    if (argv0 == NULL) {
	return;
    }
    Tcl_DStringInit(&buffer);

    name = argv0;
    for (p = name; *p != '\0'; p++) {
	if (*p == '/') {
	    /*
	     * The name contains a slash, so use the name directly without
	     * doing a path search.
	     */

	    goto gotName;
	}
    }

    p = getenv("PATH");					/* INTL: Native. */
    if (p == NULL) {
	/*
	 * There's no PATH environment variable; use the default that is used
	 * by sh.
	 */

	p = ":/bin:/usr/bin";
    } else if (*p == '\0') {
	/*
	 * An empty path is equivalent to ".".
	 */

	p = "./";
    }

    /*
     * Search through all the directories named in the PATH variable to see if
     * argv[0] is in one of them. If so, use that file name.
     */

    while (1) {
	while (TclIsSpaceProc(*p)) {
	    p++;
	}
	name = p;
	while ((*p != ':') && (*p != 0)) {
	    p++;
	}
	TclDStringClear(&buffer);
	if (p != name) {
	    Tcl_DStringAppend(&buffer, name, p - name);
	    if (p[-1] != '/') {
		TclDStringAppendLiteral(&buffer, "/");
	    }
	}
	name = Tcl_DStringAppend(&buffer, argv0, -1);

	/*
	 * INTL: The following calls to access() and stat() should not be
	 * converted to Tclp routines because they need to operate on native
	 * strings directly.
	 */

	if ((access(name, X_OK) == 0)			/* INTL: Native. */
		&& (TclOSstat(name, &statBuf) == 0)	/* INTL: Native. */
		&& S_ISREG(statBuf.st_mode)) {
	    goto gotName;
	}
	if (*p == '\0') {
	    break;
	} else if (*(p+1) == 0) {
	    p = "./";
	} else {
	    p++;
	}
    }
    TclSetObjNameOfExecutable(Tcl_NewObj(), NULL);
    goto done;

    /*
     * If the name starts with "/" then just store it
     */

  gotName:
#ifdef DJGPP
    if (name[1] == ':')
#else
    if (name[0] == '/')
#endif
    {
	encoding = Tcl_GetEncoding(NULL, NULL);
	Tcl_ExternalToUtfDString(encoding, name, -1, &utfName);
	TclSetObjNameOfExecutable(
		Tcl_NewStringObj(Tcl_DStringValue(&utfName), -1), encoding);
	Tcl_DStringFree(&utfName);
	goto done;
    }

    if (TclpGetCwd(NULL, &cwd) == NULL) {
	TclSetObjNameOfExecutable(Tcl_NewObj(), NULL);
	goto done;
    }

    /*
     * The name is relative to the current working directory. First strip off
     * a leading "./", if any, then add the full path name of the current
     * working directory.
     */

    if ((name[0] == '.') && (name[1] == '/')) {
	name += 2;
    }

    Tcl_DStringInit(&nameString);
    Tcl_DStringAppend(&nameString, name, -1);

    Tcl_DStringFree(&buffer);
    Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&cwd),
	    Tcl_DStringLength(&cwd), &buffer);
    if (Tcl_DStringValue(&cwd)[Tcl_DStringLength(&cwd) -1] != '/') {
	TclDStringAppendLiteral(&buffer, "/");
    }
    Tcl_DStringFree(&cwd);
    TclDStringAppendDString(&buffer, &nameString);
    Tcl_DStringFree(&nameString);

    encoding = Tcl_GetEncoding(NULL, NULL);
    Tcl_ExternalToUtfDString(encoding, Tcl_DStringValue(&buffer), -1,
	    &utfName);
    TclSetObjNameOfExecutable(
	    Tcl_NewStringObj(Tcl_DStringValue(&utfName), -1), encoding);
    Tcl_DStringFree(&utfName);

  done:
    Tcl_DStringFree(&buffer);
#endif
}
Esempio n. 28
0
int
TclpMatchInDirectory(
    Tcl_Interp *interp,		/* Interpreter to receive errors. */
    Tcl_Obj *resultPtr,		/* List object to lappend results. */
    Tcl_Obj *pathPtr,		/* Contains path to directory to search. */
    const char *pattern,	/* Pattern to match against. */
    Tcl_GlobTypeData *types)	/* Object containing list of acceptable types.
				 * May be NULL. In particular the directory
				 * flag is very important. */
{
    const char *native;
    Tcl_Obj *fileNamePtr;
    int matchResult = 0;

    if (types != NULL && types->type == TCL_GLOB_TYPE_MOUNT) {
	/*
	 * The native filesystem never adds mounts.
	 */

	return TCL_OK;
    }

    fileNamePtr = Tcl_FSGetTranslatedPath(interp, pathPtr);
    if (fileNamePtr == NULL) {
	return TCL_ERROR;
    }

    if (pattern == NULL || (*pattern == '\0')) {
	/*
	 * Match a file directly.
	 */

	Tcl_Obj *tailPtr;
	const char *nativeTail;

	native = Tcl_FSGetNativePath(pathPtr);
	tailPtr = TclPathPart(interp, pathPtr, TCL_PATH_TAIL);
	nativeTail = Tcl_FSGetNativePath(tailPtr);
	matchResult = NativeMatchType(interp, native, nativeTail, types);
	if (matchResult == 1) {
	    Tcl_ListObjAppendElement(interp, resultPtr, pathPtr);
	}
	Tcl_DecrRefCount(tailPtr);
	Tcl_DecrRefCount(fileNamePtr);
    } else {
	DIR *d;
	Tcl_DirEntry *entryPtr;
	const char *dirName;
	int dirLength, nativeDirLen;
	int matchHidden, matchHiddenPat;
	Tcl_StatBuf statBuf;
	Tcl_DString ds;		/* native encoding of dir */
	Tcl_DString dsOrig;	/* utf-8 encoding of dir */

	Tcl_DStringInit(&dsOrig);
	dirName = TclGetStringFromObj(fileNamePtr, &dirLength);
	Tcl_DStringAppend(&dsOrig, dirName, dirLength);

	/*
	 * Make sure that the directory part of the name really is a
	 * directory. If the directory name is "", use the name "." instead,
	 * because some UNIX systems don't treat "" like "." automatically.
	 * Keep the "" for use in generating file names, otherwise "glob
	 * foo.c" would return "./foo.c".
	 */

	if (dirLength == 0) {
	    dirName = ".";
	} else {
	    dirName = Tcl_DStringValue(&dsOrig);

	    /*
	     * Make sure we have a trailing directory delimiter.
	     */

	    if (dirName[dirLength-1] != '/') {
		dirName = TclDStringAppendLiteral(&dsOrig, "/");
		dirLength++;
	    }
	}

	/*
	 * Now open the directory for reading and iterate over the contents.
	 */

	native = Tcl_UtfToExternalDString(NULL, dirName, -1, &ds);

	if ((TclOSstat(native, &statBuf) != 0)		/* INTL: Native. */
		|| !S_ISDIR(statBuf.st_mode)) {
	    Tcl_DStringFree(&dsOrig);
	    Tcl_DStringFree(&ds);
	    Tcl_DecrRefCount(fileNamePtr);
	    return TCL_OK;
	}

	d = opendir(native);				/* INTL: Native. */
	if (d == NULL) {
	    Tcl_DStringFree(&ds);
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't read directory \"%s\": %s",
			Tcl_DStringValue(&dsOrig), Tcl_PosixError(interp)));
	    }
	    Tcl_DStringFree(&dsOrig);
	    Tcl_DecrRefCount(fileNamePtr);
	    return TCL_ERROR;
	}

	nativeDirLen = Tcl_DStringLength(&ds);

	/*
	 * Check to see if -type or the pattern requests hidden files.
	 */

	matchHiddenPat = (pattern[0] == '.')
		|| ((pattern[0] == '\\') && (pattern[1] == '.'));
	matchHidden = matchHiddenPat
		|| (types && (types->perm & TCL_GLOB_PERM_HIDDEN));
	while ((entryPtr = TclOSreaddir(d)) != NULL) {	/* INTL: Native. */
	    Tcl_DString utfDs;
	    const char *utfname;

	    /*
	     * Skip this file if it doesn't agree with the hidden parameters
	     * requested by the user (via -type or pattern).
	     */

	    if (*entryPtr->d_name == '.') {
		if (!matchHidden) {
		    continue;
		}
	    } else {
#ifdef MAC_OSX_TCL
		if (matchHiddenPat) {
		    continue;
		}
		/* Also need to check HFS hidden flag in TclMacOSXMatchType. */
#else
		if (matchHidden) {
		    continue;
		}
#endif
	    }

	    /*
	     * Now check to see if the file matches, according to both type
	     * and pattern. If so, add the file to the result.
	     */

	    utfname = Tcl_ExternalToUtfDString(NULL, entryPtr->d_name, -1,
		    &utfDs);
	    if (Tcl_StringCaseMatch(utfname, pattern, 0)) {
		int typeOk = 1;

		if (types != NULL) {
		    Tcl_DStringSetLength(&ds, nativeDirLen);
		    native = Tcl_DStringAppend(&ds, entryPtr->d_name, -1);
		    matchResult = NativeMatchType(interp, native,
			    entryPtr->d_name, types);
		    typeOk = (matchResult == 1);
		}
		if (typeOk) {
		    Tcl_ListObjAppendElement(interp, resultPtr,
			    TclNewFSPathObj(pathPtr, utfname,
			    Tcl_DStringLength(&utfDs)));
		}
	    }
	    Tcl_DStringFree(&utfDs);
	    if (matchResult < 0) {
		break;
	    }
	}

	closedir(d);
	Tcl_DStringFree(&ds);
	Tcl_DStringFree(&dsOrig);
	Tcl_DecrRefCount(fileNamePtr);
    }
    if (matchResult < 0) {
	return TCL_ERROR;
    }
    return TCL_OK;
}
Esempio n. 29
0
    /* ARGSUSED */
int
TclpCreateProcess(
    Tcl_Interp *interp,		/* Interpreter in which to leave errors that
				 * occurred when creating the child process.
				 * Error messages from the child process
				 * itself are sent to errorFile. */
    int argc,			/* Number of arguments in following array. */
    const char **argv,		/* Array of argument strings in UTF-8.
				 * argv[0] contains the name of the executable
				 * translated using Tcl_TranslateFileName
				 * call). Additional arguments have not been
				 * converted. */
    TclFile inputFile,		/* If non-NULL, gives the file to use as input
				 * for the child process. If inputFile file is
				 * not readable or is NULL, the child will
				 * receive no standard input. */
    TclFile outputFile,		/* If non-NULL, gives the file that receives
				 * output from the child process. If
				 * outputFile file is not writeable or is
				 * NULL, output from the child will be
				 * discarded. */
    TclFile errorFile,		/* If non-NULL, gives the file that receives
				 * errors from the child process. If errorFile
				 * file is not writeable or is NULL, errors
				 * from the child will be discarded. errorFile
				 * may be the same as outputFile. */
    Tcl_Pid *pidPtr)		/* If this function is successful, pidPtr is
				 * filled with the process id of the child
				 * process. */
{
    TclFile errPipeIn, errPipeOut;
    int count, status, fd;
    char errSpace[200 + TCL_INTEGER_SPACE];
    Tcl_DString *dsArray;
    char **newArgv;
    int pid, i;

    errPipeIn = NULL;
    errPipeOut = NULL;
    pid = -1;

    /*
     * Create a pipe that the child can use to return error information if
     * anything goes wrong.
     */

    if (TclpCreatePipe(&errPipeIn, &errPipeOut) == 0) {
	Tcl_AppendResult(interp, "couldn't create pipe: ",
		Tcl_PosixError(interp), NULL);
	goto error;
    }

    /*
     * We need to allocate and convert this before the fork so it is properly
     * deallocated later
     */

    dsArray = (Tcl_DString *)
	    TclStackAlloc(interp, argc * sizeof(Tcl_DString));
    newArgv = (char **) TclStackAlloc(interp, (argc+1) * sizeof(char *));
    newArgv[argc] = NULL;
    for (i = 0; i < argc; i++) {
	newArgv[i] = Tcl_UtfToExternalDString(NULL, argv[i], -1, &dsArray[i]);
    }

#ifdef USE_VFORK
    /*
     * After vfork(), do not call code in the child that changes global state,
     * because it is using the parent's memory space at that point and writes
     * might corrupt the parent: so ensure standard channels are initialized in
     * the parent, otherwise SetupStdFile() might initialize them in the child.
     */
    if (!inputFile) {
	Tcl_GetStdChannel(TCL_STDIN);
    }
    if (!outputFile) {
        Tcl_GetStdChannel(TCL_STDOUT);
    }
    if (!errorFile) {
        Tcl_GetStdChannel(TCL_STDERR);
    }
#endif
    pid = fork();
    if (pid == 0) {
	int joinThisError = errorFile && (errorFile == outputFile);

	fd = GetFd(errPipeOut);

	/*
	 * Set up stdio file handles for the child process.
	 */

	if (!SetupStdFile(inputFile, TCL_STDIN)
		|| !SetupStdFile(outputFile, TCL_STDOUT)
		|| (!joinThisError && !SetupStdFile(errorFile, TCL_STDERR))
		|| (joinThisError &&
			((dup2(1,2) == -1) || (fcntl(2, F_SETFD, 0) != 0)))) {
	    sprintf(errSpace,
		    "%dforked process couldn't set up input/output: ", errno);
	    (void)write(fd, errSpace, (size_t) strlen(errSpace));
	    _exit(1);
	}

	/*
	 * Close the input side of the error pipe.
	 */

	RestoreSignals();
	execvp(newArgv[0], newArgv);			/* INTL: Native. */
	sprintf(errSpace, "%dcouldn't execute \"%.150s\": ", errno, argv[0]);
	(void)write(fd, errSpace, (size_t) strlen(errSpace));
	_exit(1);
    }

    /*
     * Free the mem we used for the fork
     */

    for (i = 0; i < argc; i++) {
	Tcl_DStringFree(&dsArray[i]);
    }
    TclStackFree(interp, newArgv);
    TclStackFree(interp, dsArray);

    if (pid == -1) {
	Tcl_AppendResult(interp, "couldn't fork child process: ",
		Tcl_PosixError(interp), NULL);
	goto error;
    }

    /*
     * Read back from the error pipe to see if the child started up OK. The
     * info in the pipe (if any) consists of a decimal errno value followed by
     * an error message.
     */

    TclpCloseFile(errPipeOut);
    errPipeOut = NULL;

    fd = GetFd(errPipeIn);
    count = read(fd, errSpace, (size_t) (sizeof(errSpace) - 1));
    if (count > 0) {
	char *end;
	errSpace[count] = 0;
	errno = strtol(errSpace, &end, 10);
	Tcl_AppendResult(interp, end, Tcl_PosixError(interp), NULL);
	goto error;
    }

    TclpCloseFile(errPipeIn);
    *pidPtr = (Tcl_Pid) INT2PTR(pid);
    return TCL_OK;

  error:
    if (pid != -1) {
	/*
	 * Reap the child process now if an error occurred during its startup.
	 * We don't call this with WNOHANG because that can lead to defunct
	 * processes on an MP system. We shouldn't have to worry about hanging
	 * here, since this is the error case. [Bug: 6148]
	 */

	Tcl_WaitPid((Tcl_Pid) INT2PTR(pid), &status, 0);
    }

    if (errPipeIn) {
	TclpCloseFile(errPipeIn);
    }
    if (errPipeOut) {
	TclpCloseFile(errPipeOut);
    }
    return TCL_ERROR;
}
Esempio n. 30
0
MODULE_SCOPE Tcl_PackageInitProc *
TclpFindSymbol(
    Tcl_Interp *interp,		/* For error reporting. */
    Tcl_LoadHandle loadHandle,	/* Handle from TclpDlopen. */
    CONST char *symbol)		/* Symbol name to look up. */
{
    Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *) loadHandle;
    Tcl_PackageInitProc *proc = NULL;
    const char *errMsg = NULL;
    Tcl_DString ds;
    const char *native;

    native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
#if TCL_DYLD_USE_DLFCN
    if (dyldLoadHandle->dlHandle) {
	proc = dlsym(dyldLoadHandle->dlHandle, native);
	if (proc) {
	    TclLoadDbgMsg("dlsym() successful");
	} else {
	    errMsg = dlerror();
	    TclLoadDbgMsg("dlsym() failed: %s", errMsg);
	}
    } else
#endif /* TCL_DYLD_USE_DLFCN */
    {
#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
	NSSymbol nsSymbol = NULL;
	Tcl_DString newName;

	/*
	 * dyld adds an underscore to the beginning of symbol names.
	 */

	Tcl_DStringInit(&newName);
	Tcl_DStringAppend(&newName, "_", 1);
	native = Tcl_DStringAppend(&newName, native, -1);
	if (dyldLoadHandle->dyldLibHeader) {
	    nsSymbol = NSLookupSymbolInImage(dyldLoadHandle->dyldLibHeader,
		    native, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW |
		    NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
	    if (nsSymbol) {
		TclLoadDbgMsg("NSLookupSymbolInImage() successful");
#ifdef DYLD_SUPPORTS_DYLIB_UNLOADING
		/*
		 * Until dyld supports unloading of MY_DYLIB binaries, the
		 * following is not needed.
		 */

		NSModule module = NSModuleForSymbol(nsSymbol);
		Tcl_DyldModuleHandle *modulePtr = dyldLoadHandle->modulePtr;

		while (modulePtr != NULL) {
		    if (module == modulePtr->module) {
			break;
		    }
		    modulePtr = modulePtr->nextPtr;
		}
		if (modulePtr == NULL) {
		    modulePtr = (Tcl_DyldModuleHandle *)
			    ckalloc(sizeof(Tcl_DyldModuleHandle));
		    modulePtr->module = module;
		    modulePtr->nextPtr = dyldLoadHandle->modulePtr;
		    dyldLoadHandle->modulePtr = modulePtr;
		}
#endif /* DYLD_SUPPORTS_DYLIB_UNLOADING */
	    } else {
		NSLinkEditErrors editError;
		int errorNumber;
		const char *errorName;

		NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg);
		TclLoadDbgMsg("NSLookupSymbolInImage() failed: %s", errMsg);
	    }
	} else if (dyldLoadHandle->modulePtr) {
	    nsSymbol = NSLookupSymbolInModule(
		    dyldLoadHandle->modulePtr->module, native);
	    if (nsSymbol) {
		TclLoadDbgMsg("NSLookupSymbolInModule() successful");
	    } else {
		TclLoadDbgMsg("NSLookupSymbolInModule() failed");
	    }
	}
	if (nsSymbol) {
	    proc = NSAddressOfSymbol(nsSymbol);
	    if (proc) {
		TclLoadDbgMsg("NSAddressOfSymbol() successful");
	    } else {
		TclLoadDbgMsg("NSAddressOfSymbol() failed");
	    }
	}
	Tcl_DStringFree(&newName);
#endif /* TCL_DYLD_USE_NSMODULE */
    }
    Tcl_DStringFree(&ds);
    if (errMsg) {
	Tcl_AppendResult(interp, errMsg, NULL);
    }
    return proc;
}