Dear Titi, The proper version of the file, properly compiled and tested is the one attached to this email message.
Hope it helps, Maurizio -----Original Message----- From: AOLserver Discussion [mailto:[EMAIL PROTECTED] On Behalf Of Titi Alailima Sent: 05 May 2008 19:03 To: AOLSERVER@LISTSERV.AOL.COM Subject: Re: [AOLSERVER] Fix for ns_tmpnam under Windows There is a missing variable declaration in this patch for "i", the for-loop index. Anyone want to make this fix and commit it? Titi Ala'ilima Lead Architect MedTouch LLC 1100 Massachusetts Avenue Cambridge, MA 02138 617.621.8670 x309 > -----Original Message----- > From: AOLserver Discussion [mailto:[EMAIL PROTECTED] On > Behalf Of Gustaf Neumann > Sent: Thursday, April 24, 2008 3:33 AM > To: AOLSERVER@LISTSERV.AOL.COM > Subject: [AOLSERVER] Fix for ns_tmpnam under Windows > > Dear AOLserver community > > There was a problem with "ns_tmpnam", when the aolserver was compiled > under > windows (esp. Vista). The Tcl command"ns_tmpnam" is implemented in C > using tmpnam(), which exists under WIN32, but behaves differently > as on unix counterparts and is practically unusable. The problem is > that tmnam() under Windows generates a filename for the root directory > of the > actual drive (at least under Vista, no permissions under normal > conditions) and > ignores the TMP environment variable. > > See some background info form Microsoft: > http://msdn2.microsoft.com/en-us/library/hs3e7355(VS.80).aspx > > I have commited a patch to CVS head to address this problem. > http://aolserver.cvs.sourceforge.net/aolserver/aolserver/nsd/tclfile.c? > r1=1.25&r2=1.26 > The patch is local and documents the intended behavior and background > in > detail. > Please crosscheck. > > best regards > -gustaf neumann > > > -- > AOLserver - http://www.aolserver.com/ > > To Remove yourself from this list, simply send an email to > <[EMAIL PROTECTED]> with the > body of "SIGNOFF AOLSERVER" in the email message. You can leave the > Subject: field of your email blank. -- AOLserver - http://www.aolserver.com/ To Remove yourself from this list, simply send an email to <[EMAIL PROTECTED]> with the body of "SIGNOFF AOLSERVER" in the email message. You can leave the Subject: field of your email blank. -- AOLserver - http://www.aolserver.com/ To Remove yourself from this list, simply send an email to <[EMAIL PROTECTED]> with the body of "SIGNOFF AOLSERVER" in the email message. You can leave the Subject: field of your email blank.
/* * The contents of this file are subject to the AOLserver Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://aolserver.com/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is AOLserver Code and related documentation * distributed by AOL. * * The Initial Developer of the Original Code is America Online, * Inc. Portions created by AOL are Copyright (C) 1999 America Online, * Inc. All Rights Reserved. * * Alternatively, the contents of this file may be used under the terms * of the GNU General Public License (the "GPL"), in which case the * provisions of GPL are applicable instead of those above. If you wish * to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the * License, indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by the GPL. * If you do not delete the provisions above, a recipient may use your * version of this file under either the License or the GPL. */ /* * tclfile.c -- * * Tcl commands that do stuff to the filesystem. */ static const char *RCSID = "@(#) $Header: /cvsroot/aolserver/aolserver/nsd/tclfile.c,v 1.24 2005/08/23 21:41:31 jgdavidson Exp $, compiled: " __DATE__ " " __TIME__; #include "nsd.h" #ifdef _WIN32 #include <sys/utime.h> #else #include <utime.h> #endif /* * Structure handling one registered channel for the [ns_chan] command */ typedef struct _NsRegChan { char *name; Tcl_Channel chan; } NsRegChan; static void SpliceChannel(Tcl_Interp *interp, Tcl_Channel chan); static void UnspliceChannel(Tcl_Interp *interp, Tcl_Channel chan); /* *---------------------------------------------------------------------- * * Ns_TclGetOpenChannel -- * * Return an open channel with an interface similar to the * pre-Tcl7.5 Tcl_GetOpenFile, used throughout AOLserver. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * The value at chanPtr is updated with a valid open Tcl_Channel. * *---------------------------------------------------------------------- */ static int GetOpenChannel(Tcl_Interp *interp, Tcl_Obj *obj, int write, int check, Tcl_Channel *chanPtr) { return Ns_TclGetOpenChannel(interp, Tcl_GetString(obj), write, check, chanPtr); } int Ns_TclGetOpenChannel(Tcl_Interp *interp, char *chanId, int write, int check, Tcl_Channel *chanPtr) { int mode; *chanPtr = Tcl_GetChannel(interp, chanId, &mode); if (*chanPtr == NULL) { return TCL_ERROR; } if (check && ((write && !(mode & TCL_WRITABLE)) || (!write && !(mode & TCL_READABLE)))) { Tcl_AppendResult(interp, "channel \"", chanId, "\" not open for ", write ? "write" : "read", NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Ns_TclGetOpenFd -- * * Return an open Unix file descriptor for the given channel. * This routine is used by the AOLserver * routines * to provide access to the underlying socket. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * The value at fdPtr is updated with a valid Unix file descriptor. * *---------------------------------------------------------------------- */ int Ns_TclGetOpenFd(Tcl_Interp *interp, char *chanId, int write, int *fdPtr) { Tcl_Channel chan; ClientData data; if (Ns_TclGetOpenChannel(interp, chanId, write, 1, &chan) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetChannelHandle(chan, write ? TCL_WRITABLE : TCL_READABLE, (ClientData*) &data) != TCL_OK) { Tcl_AppendResult(interp, "could not get handle for channel: ", chanId, NULL); return TCL_ERROR; } *fdPtr = (int) data; return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclCpFpObjCmd -- * * Implements ns_cpfp as obj command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclCpFpObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { Tcl_Channel in, out; char buf[2048]; char *p; int tocopy, nread, nwrote, toread, ntotal; if (objc != 3 && objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "inChan outChan ?ncopy?"); return TCL_ERROR; } if (GetOpenChannel(interp, objv[1], 0, 1, &in) != TCL_OK || GetOpenChannel(interp, objv[2], 1, 1, &out) != TCL_OK) { return TCL_ERROR; } if (objc == 3) { tocopy = -1; } else { if (Tcl_GetInt(interp, Tcl_GetString(objv[3]), &tocopy) != TCL_OK) { return TCL_ERROR; } if (tocopy < 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "invalid length \"", Tcl_GetString(objv[3]), "\": must be >= 0", NULL); return TCL_ERROR; } } ntotal = 0; while (tocopy != 0) { toread = sizeof(buf); if (tocopy > 0 && toread > tocopy) { toread = tocopy; } nread = Tcl_Read(in, buf, toread); if (nread == 0) { break; } else if (nread < 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "read failed: ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } if (tocopy > 0) { tocopy -= nread; } p = buf; while (nread > 0) { nwrote = Tcl_Write(out, p, nread); if (nwrote < 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "write failed: ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } nread -= nwrote; ntotal += nwrote; p += nwrote; } } Tcl_SetObjResult(interp, Tcl_NewIntObj(ntotal)); return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclCpObjCmd -- * * Implements ns_cp as obj command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclCpObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int nread, towrite, nwrote; char buf[4096], *src, *dst, *p, *emsg, *efile; int preserve, result, rfd, wfd; struct stat st; struct utimbuf ut; if (objc != 3 && objc != 4) { badargs: Tcl_WrongNumArgs(interp, 1, objv, "?-preserve? srcfile dstfile"); return TCL_ERROR; } emsg = "<unknown>"; efile = ""; wfd = rfd = -1; result = TCL_ERROR; if (objc == 3) { preserve = 0; src = Tcl_GetString(objv[1]); dst = Tcl_GetString(objv[2]); } else { if (!STREQ(Tcl_GetString(objv[1]), "-preserve")) { goto badargs; } preserve = 1; src = Tcl_GetString(objv[2]); dst = Tcl_GetString(objv[3]); if (stat(src, &st) != 0) { emsg = "stat"; efile = src; goto done; } } emsg = "open"; rfd = open(src, O_RDONLY|O_BINARY); if (rfd < 0) { efile = src; goto done; } wfd = open(dst, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644); if (wfd < 0) { efile = dst; goto done; } while ((nread = read(rfd, buf, sizeof(buf))) > 0) { p = buf; towrite = nread; while (towrite > 0) { nwrote = write(wfd, p, (size_t)towrite); if (nwrote <= 0) { emsg = "write"; efile = dst; goto done; } towrite -= nwrote; p += nwrote; } } if (nread < 0) { emsg = "read"; efile = src; goto done; } if (!preserve) { result = TCL_OK; } else { efile = dst; if (chmod(dst, st.st_mode) != 0) { emsg = "chmod"; goto done; } ut.actime = st.st_atime; ut.modtime = st.st_mtime; if (utime(dst, &ut) != 0) { emsg = "utime"; goto done; } result = TCL_OK; } done: if (result != TCL_OK) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "could not ", emsg, " \"", efile, "\": ", Tcl_PosixError(interp), NULL); } if (rfd >= 0) { close(rfd); } if (wfd >= 0) { close(wfd); } return result; } /* *---------------------------------------------------------------------- * * NsTclMkdirObjCmd -- * * Implements ns_mkdir as obj command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclMkdirObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "dir"); return TCL_ERROR; } if (mkdir(Tcl_GetString(objv[1]), 0755) != 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "mkdir (\"", Tcl_GetString(objv[1]), "\") failed: ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclRmdirObjCmd -- * * Implements ns_rmdir * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclRmdirObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "dir"); return TCL_ERROR; } if (rmdir(Tcl_GetString(objv[1])) != 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "rmdir (\"", Tcl_GetString(objv[1]), "\") failed: ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclRollFileObjCmd -- * * Implements ns_rollfile obj command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ static int FileObjCmd(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], char *cmd) { int max, status; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "file backupMax"); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[2], &max) != TCL_OK) { return TCL_ERROR; } if (max <= 0 || max > 1000) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "invalid max \"", Tcl_GetString(objv[2]), "\": should be > 0 and <= 1000.", NULL); return TCL_ERROR; } if (*cmd == 'p') { status = Ns_PurgeFiles(Tcl_GetString(objv[1]), max); } else { status = Ns_RollFile(Tcl_GetString(objv[1]), max); } if (status != NS_OK) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "could not ", cmd, " \"", Tcl_GetString(objv[1]), "\": ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } return TCL_OK; } int NsTclRollFileObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return FileObjCmd(interp, objc, objv, "roll"); } int NsTclPurgeFilesObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return FileObjCmd(interp, objc, objv, "purge"); } /* *---------------------------------------------------------------------- * * NsTclUnlinkObjCmd -- * * Implement ns_unlink as obj command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclUnlinkObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int fComplain = NS_TRUE; if ((objc != 2) && (objc != 3)) { Tcl_WrongNumArgs(interp, 1, objv, "?-nocomplain? filename"); return TCL_ERROR; } if (objc == 3) { if (!STREQ(Tcl_GetString(objv[1]), "-nocomplain")) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "unknown flag \"", Tcl_GetString(objv[1]), "\": should be -nocomplain", NULL); return TCL_ERROR; } else { fComplain = NS_FALSE; } } if (unlink(Tcl_GetString(objv[objc-1])) != 0) { if (fComplain || errno != ENOENT) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "unlink (\"", Tcl_GetString(objv[objc-1]), "\") failed: ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclMkTempCmd -- * * Implements ns_mktemp. * * Results: * Tcl result. * * Side effects: * Allocates memory for the filename as a TCL_VOLATILE object. * *---------------------------------------------------------------------- */ int NsTclMkTempCmd(ClientData dummy, Tcl_Interp *interp, int argc, char **argv) { char *buffer; if (argc != 2) { Tcl_AppendResult(interp, "wrong # of args: should be \"", argv[0], " template\"", NULL); return TCL_ERROR; } buffer = ns_strdup(argv[1]); Tcl_SetResult(interp, mktemp(buffer), (Tcl_FreeProc *)ns_free); return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclTmpNamObjCmd -- * * Implements ns_tmpnam as obj command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclTmpNamObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { #ifdef WIN32 /* The WIN32 implmentation of tmpnam() ignores the environment variable TMP and generates filenames for the root directory. Unfortunately, new WIN versions (Vista) don't allow this. The suggested replacement is _tempnam(). The first argument of _tempnam() is the default directory, in case the environment variable TMP is not set or points to a directory that does not exist. */ int i, str_len; char *buf = _tempnam("/tmp", "nsd"); if (buf == NULL) { Tcl_SetResult(interp, "could not generate temporary filename.", TCL_STATIC); return TCL_ERROR; } /* Change back slash characters into slash characters */ str_len = strlen(buf); for (i = 0; i < str_len; i++) { if (buf[i] == '\\') buf[i] = '/'; } /* The documentation says that _tempnam() allocates memory via malloc(); to be sure, that the "right" free() is used, we do not use TCL_DYNAMIC but the TCL_VOLATILE followed by the manual free(). */ Tcl_SetResult(interp, buf, TCL_VOLATILE); free(buf); #else char buf[L_tmpnam]; if (tmpnam(buf) == NULL) { Tcl_SetResult(interp, "could not generate temporary filename.", TCL_STATIC); return TCL_ERROR; } Tcl_SetResult(interp, buf, TCL_VOLATILE); #endif return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclNormalizePathObjCmd -- * * Implements ns_normalizepath as obj command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclNormalizePathObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { Ns_DString ds; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "path"); return TCL_ERROR; } Ns_DStringInit(&ds); Ns_NormalizePath(&ds, Tcl_GetString(objv[1])); Tcl_SetResult(interp, ds.string, TCL_VOLATILE); Ns_DStringFree(&ds); return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclUrl2FileObjCmd -- * * Implements ns_url2file as obj command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclUrl2FileObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { NsInterp *itPtr = arg; Ns_DString ds; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "url"); return TCL_ERROR; } Ns_DStringInit(&ds); NsUrlToFile(&ds, itPtr->servPtr, Tcl_GetString(objv[1])); Tcl_SetResult(interp, ds.string, TCL_VOLATILE); Ns_DStringFree(&ds); return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclKillObjCmd -- * * Implements ns_kill as obj command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclKillObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int pid, signal; if ((objc != 3) && (objc != 4)) { badargs: Tcl_WrongNumArgs(interp, 1, objv, "?-nocomplain? pid signal"); return TCL_ERROR; } if (objc == 3) { if (Tcl_GetIntFromObj(interp, objv[1], &pid) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[2], &signal) != TCL_OK) { return TCL_ERROR; } if (kill(pid, signal) != 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "kill (\"", Tcl_GetString(objv[1]), ",", Tcl_GetString(objv[2]), "\") failed: ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } } else { if (strcmp(Tcl_GetString(objv[1]), "-nocomplain") != 0) { goto badargs; } if (Tcl_GetIntFromObj(interp, objv[2], &pid) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[3], &signal) != TCL_OK) { return TCL_ERROR; } kill(pid, signal); } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclLinkObjCmd -- * * Implements ns_link as obj command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclLinkObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { if ((objc != 3) && (objc != 4)) { Tcl_WrongNumArgs(interp, 1, objv, "?-nocomplain? filename1 filename2"); return TCL_ERROR; } if (objc == 3) { if (link(Tcl_GetString(objv[1]), Tcl_GetString(objv[2])) != 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "link (\"", Tcl_GetString(objv[1]), "\", \"", Tcl_GetString(objv[2]), "\") failed: ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } } else { if (strcmp(Tcl_GetString(objv[1]), "-nocomplain") != 0) { Tcl_WrongNumArgs(interp, 1, objv, "?-nocomplain? filename1 filename2"); return TCL_ERROR; } link(Tcl_GetString(objv[2]), Tcl_GetString(objv[3])); } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclSymlinkObjCmd -- * * Implements ns_symlink as obj command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclSymlinkObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { if ((objc != 3) && (objc != 4)) { badargs: Tcl_WrongNumArgs(interp, 1, objv, "?-nocomplain? filename1 filename2"); return TCL_ERROR; } if (objc == 3) { if (symlink(Tcl_GetString(objv[1]), Tcl_GetString(objv[2])) != 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "symlink (\"", Tcl_GetString(objv[1]), "\", \"", Tcl_GetString(objv[2]), "\") failed: ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } } else { if (strcmp(Tcl_GetString(objv[1]), "-nocomplain") != 0) { goto badargs; } symlink(Tcl_GetString(objv[2]), Tcl_GetString(objv[3])); } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclRenameObjCmd -- * * Implements ns_rename as obj command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclRenameObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "filename1 filename2"); return TCL_ERROR; } if (rename(Tcl_GetString(objv[1]), Tcl_GetString(objv[2])) != 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "rename (\"", Tcl_GetString(objv[1]), "\", \"", Tcl_GetString(objv[2]), "\") failed: ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclWriteFpObjCmd -- * * Implements ns_writefp as obj command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclWriteFpObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { NsInterp *itPtr = arg; Tcl_Channel chan; int nbytes = INT_MAX; int result; if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "fileid ?nbytes?"); return TCL_ERROR; } if (GetOpenChannel(interp, objv[1], 0, 1, &chan) != TCL_OK) { return TCL_ERROR; } if (objc == 3 && Tcl_GetIntFromObj(interp, objv[2], &nbytes) != TCL_OK) { return TCL_ERROR; } if (itPtr->conn == NULL) { Tcl_SetResult(interp, "no connection", TCL_STATIC); return TCL_ERROR; } result = Ns_ConnSendChannel(itPtr->conn, chan, nbytes); if (result != NS_OK) { Tcl_SetResult(interp, "i/o failed", TCL_STATIC); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclTruncateObjCmd -- * * Implements ns_truncate as obj command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclTruncateObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int length; if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "file ?length?"); return TCL_ERROR; } if (objc == 2) { length = 0; } else if (Tcl_GetIntFromObj(interp, objv[2], &length) != TCL_OK) { return TCL_ERROR; } if (truncate(Tcl_GetString(objv[1]), length) != 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "truncate (\"", Tcl_GetString(objv[1]), "\", ", Tcl_GetString(objv[2]) ? Tcl_GetString(objv[2]) : "0", ") failed: ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclFTruncateObjCmd -- * * Implements ns_ftruncate as obj command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclFTruncateObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int length, fd; if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "fileId ?length?"); return TCL_ERROR; } if (Ns_TclGetOpenFd(interp, Tcl_GetString(objv[1]), 1, &fd) != TCL_OK) { return TCL_ERROR; } if (objc == 2) { length = 0; } else if (Tcl_GetInt(interp, Tcl_GetString(objv[2]), &length) != TCL_OK) { return TCL_ERROR; } if (ftruncate(fd, length) != 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "ftruncate (\"", Tcl_GetString(objv[1]), "\", ", Tcl_GetString(objv[2]) ? Tcl_GetString(objv[2]) : "0", ") failed: ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclChmodObjCmd -- * * NsTclChmodCmd * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclChmodObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int mode; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "filename mode"); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[2], &mode) != TCL_OK) { return TCL_ERROR; } if (chmod(Tcl_GetString(objv[1]), (mode_t)mode) != 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "chmod (\"", Tcl_GetString(objv[1]), "\", ", Tcl_GetString(objv[2]), ") failed: ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclChanObjCmd -- * * Implement the ns_chan command. * * Results: * Tcl result. * * Side effects: * See docs. * *---------------------------------------------------------------------- */ int NsTclChanObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { NsInterp *itPtr = arg; NsServer *servPtr = itPtr->servPtr; Tcl_Channel chan = NULL; char *name, *chanName; NsRegChan *regChan = NULL; int new, shared; Tcl_HashTable *tabPtr; Tcl_HashEntry *hPtr; Tcl_HashSearch search; static CONST char *opts[] = { "cleanup", "list", "create", "put", "get", NULL }; enum { CCleanupIdx, CListIdx, CCreateIdx, CPutIdx, CGetIdx } _nsmayalias opt; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "command ?args?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], opts, "option", 0, (int *) &opt) != TCL_OK) { return TCL_ERROR; } switch (opt) { case CCreateIdx: if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "create channel name"); return TCL_ERROR; } chanName = Tcl_GetString(objv[2]); chan = Tcl_GetChannel(interp, chanName, NULL); if (chan == (Tcl_Channel)NULL) { return TCL_ERROR; } if (Tcl_IsChannelShared(chan)) { Tcl_SetResult(interp, "channel is shared", TCL_STATIC); return TCL_ERROR; } name = Tcl_GetString(objv[3]); Ns_MutexLock(&servPtr->chans.lock); hPtr = Tcl_CreateHashEntry(&servPtr->chans.table, name, &new); if (new) { regChan = ns_malloc(sizeof(NsRegChan)); regChan->name = ns_malloc(strlen(chanName)+1); regChan->chan = chan; strcpy(regChan->name, chanName); Tcl_SetHashValue(hPtr, regChan); } Ns_MutexUnlock(&servPtr->chans.lock); if (!new) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "channel with name \"", Tcl_GetString(objv[3]), "\" already exists", NULL); return TCL_ERROR; } UnspliceChannel(interp, chan); break; case CGetIdx: if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "get name"); return TCL_ERROR; } name = Tcl_GetString(objv[2]); Ns_MutexLock(&servPtr->chans.lock); hPtr = Tcl_FindHashEntry(&servPtr->chans.table, name); if (hPtr != NULL) { regChan = (NsRegChan*)Tcl_GetHashValue(hPtr); Tcl_DeleteHashEntry(hPtr); } Ns_MutexUnlock(&servPtr->chans.lock); if (hPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "no such shared channel: ", name, NULL); return TCL_ERROR; } SpliceChannel(interp, regChan->chan); Tcl_SetResult(interp, regChan->name, TCL_VOLATILE); hPtr = Tcl_CreateHashEntry(&itPtr->chans, name, &new); Tcl_SetHashValue(hPtr, regChan); break; case CPutIdx: if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "put name"); return TCL_ERROR; } name = Tcl_GetString(objv[2]); hPtr = Tcl_FindHashEntry(&itPtr->chans, name); if (hPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "no such shared channel: ", name, NULL); return TCL_ERROR; } regChan = (NsRegChan*)Tcl_GetHashValue(hPtr); chan = Tcl_GetChannel(interp, regChan->name, NULL); if (chan == (Tcl_Channel)NULL || chan != regChan->chan) { Tcl_DeleteHashEntry(hPtr); if (chan != regChan->chan) { Tcl_SetResult(interp, "channel mismatch", TCL_STATIC); } return TCL_ERROR; } UnspliceChannel(interp, regChan->chan); Tcl_DeleteHashEntry(hPtr); Ns_MutexLock(&servPtr->chans.lock); hPtr = Tcl_CreateHashEntry(&servPtr->chans.table, name, &new); Tcl_SetHashValue(hPtr, regChan); Ns_MutexUnlock(&servPtr->chans.lock); break; case CListIdx: if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "list ?-shared?"); return TCL_ERROR; } shared = (objc == 3); if (shared) { Ns_MutexLock(&servPtr->chans.lock); tabPtr = &servPtr->chans.table; } else { tabPtr = &itPtr->chans; } hPtr = Tcl_FirstHashEntry(tabPtr, &search); while (hPtr != NULL) { Tcl_AppendElement(interp, Tcl_GetHashKey(tabPtr, hPtr)); hPtr = Tcl_NextHashEntry(&search); } if (shared) { Ns_MutexUnlock(&servPtr->chans.lock); } break; case CCleanupIdx: if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "cleanup ?-shared?"); return TCL_ERROR; } shared = (objc == 3); if (shared) { Ns_MutexLock(&servPtr->chans.lock); tabPtr = &servPtr->chans.table; } else { tabPtr = &itPtr->chans; } hPtr = Tcl_FirstHashEntry(tabPtr, &search); while (hPtr != NULL) { regChan = (NsRegChan*)Tcl_GetHashValue(hPtr); if (shared) { Tcl_SpliceChannel(regChan->chan); Tcl_UnregisterChannel((Tcl_Interp*)NULL, regChan->chan); } else { Tcl_UnregisterChannel(interp, regChan->chan); } ns_free(regChan->name); ns_free(regChan); Tcl_DeleteHashEntry(hPtr); hPtr = Tcl_NextHashEntry(&search); } if (shared) { Ns_MutexUnlock(&servPtr->chans.lock); } break; } return TCL_OK; } /* *---------------------------------------------------------------------- * * SpliceChannel * * Adds the shared channel in the interp/thread. * * Results: * None. * * Side effects: * New channel appears in the interp. * *---------------------------------------------------------------------- */ static void SpliceChannel(Tcl_Interp *interp, Tcl_Channel chan) { Tcl_SpliceChannel(chan); Tcl_RegisterChannel(interp, chan); Tcl_UnregisterChannel((Tcl_Interp*)NULL, chan); /* Prevent closing */ } /* *---------------------------------------------------------------------- * * UnspliceChannel * * Divorces the channel from its owning interp/thread. * * Results: * None. * * Side effects: * Channel is not accesible by Tcl scripts any more. * *---------------------------------------------------------------------- */ static void UnspliceChannel(Tcl_Interp *interp, Tcl_Channel chan) { Tcl_ClearChannelHandlers(chan); Tcl_RegisterChannel((Tcl_Interp*)NULL, chan); /* Prevent closing */ Tcl_UnregisterChannel(interp, chan); Tcl_CutChannel(chan); } -- AOLserver - http://www.aolserver.com/ To Remove yourself from this list, simply send an email to <[EMAIL PROTECTED]> with the body of "SIGNOFF AOLSERVER" in the email message. You can leave the Subject: field of your email blank.