Beispiel #1
0
/*
 * Return error message and code for owtcl internal and syntax errors.
 */
void owtcl_Error(Tcl_Interp * interp, char *error_family, char *error_code, char *format, ...)
{
#ifdef HAVE_VASPRINTF
	char *buf;
#else
#define ErrBufSize 500
	char buf[ErrBufSize];
#endif
	va_list argsPtr;

	va_start(argsPtr, format);

#ifdef HAVE_VASPRINTF
	if (vasprintf(&buf, format, argsPtr) < 0)
#else
	if (vsnprintf(buf, ErrBufSize, format, argsPtr) < 0)
#endif
	{
		/* Error within vasprintf/vsnprintf */
		Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_ErrnoMsg(Tcl_GetErrno()),-1)); // -1 means a C-style string
		Tcl_PosixError(interp);
	} else {
		/* Generate a posix like error message and code. */
		Tcl_SetResult(interp, buf, TCL_VOLATILE);
		Tcl_SetErrorCode(interp, error_family, error_code, NULL);
	}

	va_end(argsPtr);
#ifdef HAVE_VASPRINTF
	if (buf) {
		free(buf);
	}
#endif
}
Beispiel #2
0
int SshPosixError(Tcl_Interp* interp, int status) {
    int result = TCL_OK;

    if (status) {
        Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_ErrnoMsg(status), -1));
        result = TCL_ERROR;
    }

    return result;
}
Beispiel #3
0
char *
dlerror(
) {
    TclWinConvertError(GetLastError());
    return (char *) Tcl_ErrnoMsg(Tcl_GetErrno());
}
Beispiel #4
0
static int
TcpGetOptionProc(
    ClientData instanceData,	/* Socket state. */
    Tcl_Interp *interp,		/* For error reporting - can be NULL. */
    const char *optionName,	/* Name of the option to retrieve the value
				 * for, or NULL to get all options and their
				 * values. */
    Tcl_DString *dsPtr)		/* Where to store the computed value;
				 * initialized by caller. */
{
    TcpState *statePtr = instanceData;
    size_t len = 0;

    WaitForConnect(statePtr, NULL);

    if (optionName != NULL) {
	len = strlen(optionName);
    }

    if ((len > 1) && (optionName[1] == 'e') &&
	    (strncmp(optionName, "-error", len) == 0)) {
	socklen_t optlen = sizeof(int);

        if (statePtr->flags & TCP_ASYNC_CONNECT) {
            /* Suppress errors as long as we are not done */
            errno = 0;
        } else if (statePtr->connectError != 0) {
            errno = statePtr->connectError;
            statePtr->connectError = 0;
        } else {
            int err;
            getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR,
                    (char *) &err, &optlen);
            errno = err;
        }
        if (errno != 0) {
	    Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(errno), -1);
        }
	return TCL_OK;
    }

    if ((len > 1) && (optionName[1] == 'c') &&
	    (strncmp(optionName, "-connecting", len) == 0)) {

        Tcl_DStringAppend(dsPtr,
                        (statePtr->flags & TCP_ASYNC_CONNECT) ? "1" : "0", -1);
        return TCL_OK;
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 'p') &&
	    (strncmp(optionName, "-peername", len) == 0))) {
        address peername;
        socklen_t size = sizeof(peername);

	if ( (statePtr->flags & TCP_ASYNC_CONNECT) ) {
	    /*
	     * In async connect output an empty string
	     */
	    if (len == 0) {
		Tcl_DStringAppendElement(dsPtr, "-peername");
		Tcl_DStringAppendElement(dsPtr, "");
	    } else {
		return TCL_OK;
	    }
	} else if (getpeername(statePtr->fds.fd, &peername.sa, &size) >= 0) {
	    /*
	     * Peername fetch succeeded - output list
	     */
	    if (len == 0) {
		Tcl_DStringAppendElement(dsPtr, "-peername");
		Tcl_DStringStartSublist(dsPtr);
	    }
            TcpHostPortList(interp, dsPtr, peername, size);
	    if (len) {
                return TCL_OK;
            }
            Tcl_DStringEndSublist(dsPtr);
	} else {
	    /*
	     * getpeername failed - but if we were asked for all the options
	     * (len==0), don't flag an error at that point because it could be
	     * an fconfigure request on a server socket (which have no peer).
	     * Same must be done on win&mac.
	     */

	    if (len) {
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                            "can't get peername: %s",
			    Tcl_PosixError(interp)));
		}
		return TCL_ERROR;
	    }
	}
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 's') &&
	    (strncmp(optionName, "-sockname", len) == 0))) {
	TcpFdList *fds;
        address sockname;
        socklen_t size;
	int found = 0;

	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-sockname");
	    Tcl_DStringStartSublist(dsPtr);
	}
	if ( (statePtr->flags & TCP_ASYNC_CONNECT) ) {
	    /*
	     * In async connect output an empty string
	     */
	     found = 1;
	} else {
	    for (fds = &statePtr->fds; fds != NULL; fds = fds->next) {
		size = sizeof(sockname);
		if (getsockname(fds->fd, &(sockname.sa), &size) >= 0) {
		    found = 1;
		    TcpHostPortList(interp, dsPtr, sockname, size);
		}
	    }
	}
        if (found) {
            if (len) {
                return TCL_OK;
            }
            Tcl_DStringEndSublist(dsPtr);
        } else {
            if (interp) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "can't get sockname: %s", Tcl_PosixError(interp)));
            }
	    return TCL_ERROR;
	}
    }

    if (len > 0) {
	return Tcl_BadChannelOption(interp, optionName, "connecting peername sockname");
    }

    return TCL_OK;
}
Beispiel #5
0
/*
 * Return error message and code for OWlib errors.
 */
void owtcl_ErrorOWlib(Tcl_Interp * interp)
{
	/* Generate a posix like error message and code. */
	Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_ErrnoMsg(Tcl_GetErrno()),-1)); // -1 means a C-style string
	Tcl_SetErrorCode(interp, "OWTCL", Tcl_ErrnoId(), Tcl_ErrnoMsg(Tcl_GetErrno()), NULL);
}
Beispiel #6
0
void TclTextInterp::doEvent() {
  if (!done_waiting())
    return;

  // no recursive calls to TclEvalObj; this prevents  
  // display update ui from messing up Tcl. 
  if (callLevel) 
    return;

  Tcl_Channel inChannel = Tcl_GetStdChannel(TCL_STDIN);
  Tcl_Channel outChannel = Tcl_GetStdChannel(TCL_STDOUT);

  if (needPrompt && consoleisatty) {
#if TCL_MINOR_VERSION >= 4
    if (gotPartial) {
      Tcl_WriteChars(outChannel, "? ", -1);
    } else { 
      Tcl_WriteChars(outChannel, VMD_CMD_PROMPT, -1);
    }
#else
    if (gotPartial) {
      Tcl_Write(outChannel, "? ", -1);
    } else { 
      Tcl_Write(outChannel, VMD_CMD_PROMPT, -1);
    }
#endif
#if defined(VMDTKCON)
    vmdcon_purge();
#endif
    Tcl_Flush(outChannel);
    needPrompt = 0;
  }

#if defined(VMD_NANOHUB)  
  return;
#endif

  //
  // MPI builds of VMD cannot try to read any command input from the 
  // console because it creates shutdown problems, at least with MPICH.
  // File-based command input is fine however.
  //
  // For the time being, the Android builds won't attempt to get any
  // console input.  Any input we're going to get is going to come via
  // some means other than stdin, such as a network socket, text box, etc.
  //
  if (ignorestdin)
    return;
 
  if (!vmd_check_stdin())
    return;

  //
  // event loop based on tclMain.c
  //
  // According to the Tcl docs, GetsObj returns -1 on error or EOF.
    
  int length = Tcl_GetsObj(inChannel, commandPtr);
  if (length < 0) {
    if (Tcl_Eof(inChannel)) {
      // exit if we're not a tty, or if eofexit is set
      if ((!consoleisatty) || app->get_eofexit())
        app->VMDexit("", 0, 0);
    } else {
      msgErr << "Error reading Tcl input: " << Tcl_ErrnoMsg(Tcl_GetErrno()) 
             << sendmsg;
    }
    return;
  }
  
  needPrompt = 1;
  // add the newline removed by Tcl_GetsObj
  Tcl_AppendToObj(commandPtr, "\n", 1);

  char *stringrep = Tcl_GetStringFromObj(commandPtr, NULL);
  if (!Tcl_CommandComplete(stringrep)) {
    gotPartial = 1;
    return;
  }
  gotPartial = 0;

  callLevel++;
#if defined(VMD_NANOHUB)
  Tcl_EvalObjEx(interp, commandPtr, 0);
#else
  Tcl_RecordAndEvalObj(interp, commandPtr, 0);
#endif
  callLevel--;

#if TCL_MINOR_VERSION >= 4
  Tcl_DecrRefCount(commandPtr);
  commandPtr = Tcl_NewObj();
  Tcl_IncrRefCount(commandPtr);
#else
  // XXX this crashes Tcl 8.5.[46] with an internal panic
  Tcl_SetObjLength(commandPtr, 0);
#endif
    
  // if ok, send to stdout; if not, send to stderr
  Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
  char *bytes = Tcl_GetStringFromObj(resultPtr, &length);
#if defined(VMDTKCON)
  if (length > 0) {
    vmdcon_append(VMDCON_ALWAYS, bytes,length);
    vmdcon_append(VMDCON_ALWAYS, "\n", 1);
  }
  vmdcon_purge();
#else
  if (length > 0) {
#if TCL_MINOR_VERSION >= 4
    Tcl_WriteChars(outChannel, bytes, length);
    Tcl_WriteChars(outChannel, "\n", 1);
#else
    Tcl_Write(outChannel, bytes, length);
    Tcl_Write(outChannel, "\n", 1);
#endif
  }
  Tcl_Flush(outChannel);
#endif
}
Beispiel #7
0
int main(int argc, char **argv)
{
    char buffer[1024];
    size_t objSize = sizeof(char);
    int objCount = 100;
    int opRet;

    FILE *sp = NULL;
    char *str = NULL;
    int count;
    int i;
 
    if (argc != 2)
    {
        printf("Usage: \n1. testSlicerIO path/fileName\n2. testSlicerIO \"command pipe\" (e.g. \"| date\")\n");
        return 1; 
    }



    /* ------------------------------------------------------ */
    /* Testing fgets                                          */
    /* ------------------------------------------------------ */
    printf("\n......... Testing fgets .........\n\n");
    printf("Case 1: Get a line from a file stream or command pipe\n");

    sp = fopen(argv[1], "r");
    if (sp == NULL)
    {
        printf("\n\nfopen failed\n\n");
        return 1;
    }

    memset(buffer, 0, 1024);
    fgets(buffer, 1024, sp);
    if (strlen(buffer) > 0)
    {
        printf(".........passed\n\n");
        printf("Output: %s \n\n", buffer);
    }
    else
    {
        printf(".........failed\n\n");
    }
    fclose(sp);

    printf("Case 2: Get a line from stdin (please type and hit return)\n");
    str = fgets(buffer, 1024, stdin);
    if (str != NULL)
    {
        printf(".........passed\n\n");
        printf("Output: %s \n\n", str);
    }
    else
    {
        printf(".........failed\n\n");
    }



    /* ------------------------------------------------------ */
    /* Testing fread                                          */
    /* ------------------------------------------------------ */
    printf("\n......... Testing fread .........\n\n");
    printf("Case 1: Read from a file stream or command pipe\n");

    sp = fopen(argv[1], "r");
    if (sp == NULL)
    {
        printf("\n\nfopen failed\n\n");
        return 1;
    }

    memset(buffer, 0, 1024);
    opRet = fread(buffer, objSize, objCount, sp);

    if (opRet > 0)
    {
        printf(".........passed\n\n");
    }
    else
    {
        printf(".........failed\n\n");
    }
    printf("Output: %s \n\n", buffer);

    printf("Case 2: Read from stdin (please type (> 20 chars) and hit return)\n");
    memset(buffer, 0, 1024);
    objCount = 20;
    opRet = fread(buffer, objSize, objCount, stdin);
    if (opRet > 0)
    {
        printf(".........passed\n\n");
    }
    else
    {
        printf(".........failed\n\n");
    }
    printf("Output: %s \n\n", buffer);

    fclose(sp);



    /* ------------------------------------------------------ */
    /* Test fwrite                                            */
    /* ------------------------------------------------------ */
    printf("\n......... Testing fwrite .........\n\n");
    printf("Case 1: Write to a file\n");

    sp = fopen("testFwrite.txt", "w");
    if (sp == NULL)
    {
        printf("\n\nfopen failed\n\n");
        return 1;
    }

    memset(buffer, 0, 1024);
    objCount = 200;
    opRet = fwrite(buffer, objSize, objCount, sp);
    fclose(sp);
    if (opRet != objCount)
    {
        printf(".........failed\n\n");
        return 1;
    }
    else
    {
        printf(".........passed\n\n");
    }

    printf("Case 2: Write to stdout\n");
    opRet = fwrite(buffer, objSize, objCount, stdout);
    if (opRet != objCount)
    {
        printf(".........failed\n\n");
        return 1;
    }
    else
    {
        printf(".........passed\n\n");
    }


    printf("Case 3: Write to stderr\n");
    opRet = fwrite(buffer, objSize, objCount, stderr);
    if (opRet != objCount)
    {
        printf(".........failed\n\n");
        return 1;
    }
    else
    {
        printf(".........passed\n\n");
    }

    printf("Case 4: Write to a command pipe\n");

    sp = fopen("| cal", "w");
    if (sp == NULL)
    {
        printf("\n\nfopen failed\n\n");
        return 1;
    }

    strcpy(buffer, "Hello, I'm here in Boston Ma.");
    /* memset(buffer, 38, 1024); */
    opRet = fwrite(buffer, objSize, objCount, sp);
    fclose(sp);
    if (opRet != objCount)
    {
        printf(".........failed\n\n");
        return 1;
    }
    else
    {
        printf(".........passed\n\n");
    }



    /* ------------------------------------------------------ */
    /* Testing fprintf                                           */
    /* ------------------------------------------------------ */
    printf("\n......... Testing fprintf .........\n\n");
 
    printf("Case 1: Write to stdout\n");
    opRet = fprintf(stdout, "%s\n", "Boston MA");
    if (opRet <= 0)
    {
        printf(".........failed\n\n");
        return 1;
    }
    else
    {
        printf(".........passed\n\n");
    }

    printf("Case 2: Write to stderr\n");
    opRet = fprintf(stderr, "%s %d\n", "Boston Ma", 2006);
    if (opRet <= 0)
    {
        printf(".........failed\n\n");
        return 1;
    }
    else
    {
        printf(".........passed\n\n");
    }

    printf("Case 3: Write to a file\n");
    sp = fopen("testFprintf.txt", "w");
    if (sp == NULL)
    {
        printf("\n\nfopen failed\n\n");
        return 1;
    }

    strcpy(buffer, "Hello, I'm here in Boston Ma.");
    /* memset(buffer, 38, 1024); */
    opRet = fprintf(sp, "%s %d\n", buffer, 2006);
    fclose(sp);

    if (opRet <= 0)
    {
        printf(".........failed\n\n");
        return 1;
    }
    else
    {
        printf(".........passed\n\n");
    }

    printf("Case 4: Write to command pipe\n");
    sp = fopen("| cal", "w");
    if (sp == NULL)
    {
        printf("\n\nfopen failed\n\n");
        return 1;
    }

    strcpy(buffer, "Hello, I'm here in Boston Ma.");
    /* memset(buffer, 38, 1024); */
    opRet = fprintf(sp, "%s %d\n", buffer, 2006);
    fclose(sp);

    if (opRet <= 0)
    {
        printf(".........failed\n\n");
        return 1;
    }
    else
    {
        printf(".........passed\n\n");
    }


    /* ------------------------------------------------------ */
    /* Testing fflush                                           */
    /* ------------------------------------------------------ */
    printf("\n......... Testing fflush .........\n\n");
 
    printf("Case 1: Flush stdout\n");
    opRet = fflush(stdout);
    if (opRet != 0)
    {
        printf(".........failed\n\n");
        return 1;
    }
    else
    {
        printf(".........passed\n\n");
    }

    printf("Case 2: Flush stderr\n");
    opRet = fflush(stderr);
    if (opRet != 0)
    {
        printf(".........failed\n\n");
        return 1;
    }
    else
    {
        printf(".........passed\n\n");
    }

    printf("Case 3: Flush a file stream or command pipe\n");

    sp = fopen("testFflush.txt", "w");
    if (sp == NULL)
    {
        printf("\n\nfopen failed\n\n");
        return 1;
    }

    opRet = fflush(sp);
    if (opRet != 0)
    {
        printf(".........failed\n\n");
        if (sp->interp != NULL)
        {
            int errno = Tcl_GetErrno();
            printf("%s", Tcl_ErrnoMsg(errno));
        }
        return 1;
    }
    else
    {
        printf(".........passed\n\n");
    }

    fclose(sp);



    /* ------------------------------------------------------ */
    /* Testing fgetc                                          */
    /* ------------------------------------------------------ */
    printf("\n......... Testing fgetc .........\n\n");
 
    printf("Case 1: fgetc from stdin (type > 10 chars)\n");
    i = 0;
    while (i++ < 10) {
        printf("%c", fgetc(stdin));
    }
    printf("\n");
    printf(".........passed\n\n");


    printf("Case 2: fgetc from a file or command pipe\n");
    sp = fopen(argv[1], "r");
    if (sp == NULL)
    {
        printf("\n\nfopen failed\n\n");
        return 1;
    }

    count = 1; 
    while ((i = fgetc(sp)) != EOF && count < 30)
    {
        printf("%c", i);
        count++;
    }
    fclose(sp);
    printf("\n");
    printf(".........passed\n\n");



    /* ------------------------------------------------------ */
    /* Testing fputc                                          */
    /* ------------------------------------------------------ */
    printf("\n......... Testing fputc .........\n\n");
 
    printf("Case 1: fputc to stdout\n");
    strcpy(buffer, "Hello, I'm here in Boston Ma.");
    count = 0; 
    fflush(stdout);
    while (count < 30) {
        fputc(buffer[count], stdout);
        count++;
    }
    printf("\n");
    printf(".........passed\n\n");


    printf("Case 2: fputc to stderr\n");
    count = 0; 
    fflush(stderr);
    while (count < 30) {
        fputc(buffer[count], stderr);
        count++;
    }
    printf("\n");
    printf(".........passed\n\n");


    printf("Case 3: fputc to a file\n");
    sp = fopen("testFputc.txt", "w");
    if (sp == NULL)
    {
        printf("\n\nfopen failed\n\n");
        return 1;
    }

    count = 0; 
    while (count < 30)
    {
        printf("%c", fputc(buffer[count], sp));
        count++;
    }
    fclose(sp);
    printf("\n");
    printf(".........passed\n\n");


    printf("Case 4: fputc to a command pipe\n");
    sp = fopen("| cal", "w");
    if (sp == NULL)
    {
        printf("\n\nfopen failed\n\n");
        return 1;
    }

    count = 0; 
    while (count < 30)
    {
        printf("%c", fputc(buffer[count], sp));
        count++;
    }
    fclose(sp);
    printf("\n");
    printf(".........passed\n\n");



    /* ------------------------------------------------------ */
    /* Testing feof                                           */
    /* ------------------------------------------------------ */
    printf("\n......... Testing feof .........\n\n");
 
    printf("Case 1: feof to a file or command pipe\n");
    sp = fopen(argv[1], "r");
    if (sp == NULL)
    {
        printf("\n\nfopen failed\n\n");
        return 1;
    }

    while (!feof(sp))
    {
        fgets(buffer, 1024, sp);
        printf("%s\n", buffer);
    } 
    fclose(sp);
    printf("\n");
    printf(".........passed\n\n");


    printf("Case 2: feof to stdin (use control-d to finish input)\n");
    while (!feof(stdin))
    {
        fgets(buffer, 1024, stdin);
        printf("%s\n", buffer);
    }
    printf("\n");
    printf(".........passed\n\n");



    /* ------------------------------------------------------ */
    /* Testing fseek                                          */
    /* ------------------------------------------------------ */
    printf("\n......... Testing fseek .........\n\n");
 
    printf("Case 1: fseek a file or command pipe\n");
    sp = fopen(argv[1], "r");
    if (sp == NULL)
    {
        printf("\n\nfopen failed\n\n");
        return 1;
    }

    fgets(buffer, 1024, sp);
    printf("%s\n", buffer);

    opRet = fseek(sp, 5, SEEK_SET);

    fgets(buffer, 1024, sp);
    printf("%s\n", buffer);

    fclose(sp);
    
    // Return non-zero if it fails
    // See http://www.cplusplus.com/reference/clibrary/cstdio/fseek/
    if (opRet != 0)
    {
        printf(".........failed (Tcl_Seek on pipes: Not supported\n\n");
        /* return 1; */
    }
    else
    {
        printf(".........passed\n\n");
    }



    /* ------------------------------------------------------ */
    /* Testing ftell                                          */
    /* ------------------------------------------------------ */
    printf("\n......... Testing ftell .........\n\n");
 
    printf("Case 1: ftell a file or command pipe\n");
    sp = fopen(argv[1], "r");
    if (sp == NULL)
    {
        printf("\n\nfopen failed\n\n");
        return 1;
    }

    fseek(sp, 5, SEEK_SET);
    opRet = ftell(sp);

    fclose(sp);
    if (opRet == -1)
    {
        printf(".........failed (Tcl_Tell on pipes: Not supported)\n\n");
        /* return 1; */
    }
    else
    {
        printf("Current access point = %d\n", opRet);
        printf(".........passed\n\n");
    }



    /* ------------------------------------------------------ */
    /* Testing ungetc                                          */
    /* ------------------------------------------------------ */
    printf("\n......... Testing ungetc .........\n\n");
 
    printf("Case 1: ungetc onto a file stream or command pipe\n");
    sp = fopen(argv[1], "r");
    if (sp == NULL)
    {
        printf("\n\nfopen failed\n\n");
        return 1;
    }

    count = 1; 
    while ((i = fgetc(sp)) != EOF && count < 5)
    {
        printf("%c", i);
        count++;
    }
 
    ungetc(i, sp);
    opRet = fgetc(sp);

    fclose(sp);

    if (opRet != i)
    {
        printf(".........failed");
        return 1;
    }
    else
    {
        printf("\nchar = %c\n", i);
        printf(".........passed\n\n");
    }



    printf("\nAll testing cases passed\n\n");
 
    return 0;
}
Beispiel #8
0
static int
elTclSignal(ClientData data, Tcl_Interp *interp, int objc,
	    Tcl_Obj *const objv[])
{
   ElTclInterpInfo *iinfo = data;
   ElTclSignalContext *ctx;
   sigset_t set, oset;
   int i, signum;
   char *action;

   if (objc < 2 || objc > 3) {
      Tcl_WrongNumArgs(interp, 1, objv,
		       "signal ?script|-ignore|-default|-block|-unblock?");
      return TCL_ERROR;
   }

   if (objc == 2 &&
       !strcmp(Tcl_GetStringFromObj(objv[1], NULL), "names")) {
      /* [signal names] */
      Tcl_DString dstring;

      Tcl_DStringInit(&dstring);
      for(i=0; i<ELTCL_MAXSIG; i++) if (signalNames[i] != NULL) {
	 Tcl_DStringAppendElement(&dstring, signalNames[i]);
      }
      Tcl_DStringResult(interp, &dstring);
      return TCL_OK;
   }

   /* objv[1] must be a signal name */
   signum = -1;
   for(i=0; i<ELTCL_MAXSIG; i++) if (signalNames[i] != NULL)
      if (!strcmp(Tcl_GetStringFromObj(objv[1], NULL), signalNames[i])) {
	 signum = i;
	 break;
      }

   if (signum < 0) {
      /* or an integer */
      if (Tcl_GetIntFromObj(interp, objv[1], &signum) == TCL_ERROR)
	 return TCL_ERROR;
   }

   /* prepare the interpreter result so that this command returns the
    * previous action for that signal */
   ctx = getSignalContext(signum, iinfo);
   if (ctx == NULL || ctx->script == ELTCL_SIGDFL) {
      Tcl_SetResult(interp, "-default", TCL_STATIC);
   } else if (ctx->script == ELTCL_SIGIGN) {
      Tcl_SetResult(interp, "-ignore", TCL_STATIC);
   } else {
      Tcl_SetObjResult(interp, ctx->script);
   }

   /* if no action given, return current script associated with
    * signal */
   if (objc == 2) { return TCL_OK; }

   /* get the given action */
   action = Tcl_GetStringFromObj(objv[2], NULL);

   /* check if signal should be reset to default */
   if (!strcmp(action, "-default")) {
      /* special case of SIGWINCH, which we must keep processing */
#ifdef SIGWINCH
      if (signum != SIGWINCH)
#endif
	 if (signal(signum, SIG_DFL) == (void *)-1) goto error;

      if (ctx == NULL) return TCL_OK;

      if (ctx->script != ELTCL_SIGDFL && ctx->script != ELTCL_SIGIGN) {
	 Tcl_DecrRefCount(ctx->script);
	 Tcl_AsyncDelete(ctx->asyncH);
      }
      ctx->script = ELTCL_SIGDFL;
      return TCL_OK;
   }

   /* check if signal should be ignored */
   if (!strcmp(action, "-ignore")) {
      if (ctx == NULL) {
	 ctx = createSignalContext(signum, iinfo);
	 if (ctx == NULL) goto error;
      }
      /* special case of SIGWINCH, which we must keep processing */
#ifdef SIGWINCH
      if (signum != SIGWINCH)
#endif
	 if (signal(signum, SIG_IGN) == (void *)-1) goto error;

      if (ctx->script != ELTCL_SIGDFL && ctx->script != ELTCL_SIGIGN) {
	 Tcl_DecrRefCount(ctx->script);
	 Tcl_AsyncDelete(ctx->asyncH);
      }
      ctx->script = ELTCL_SIGIGN;
      return TCL_OK;
   }

   /* check if signal should be (un)blocked */
   if (!strcmp(action, "-block") || !strcmp(action, "-unblock")) {
      Tcl_DString dstring;
      int code;

      sigemptyset(&set);
      sigemptyset(&oset);
      sigaddset(&set, signum);

      if (!strcmp(action, "-block"))
	 code = sigprocmask(SIG_BLOCK, &set, &oset);
      else
	 code = sigprocmask(SIG_UNBLOCK, &set, &oset);

      if (code) goto error;

      /* return the previous mask */
      Tcl_DStringInit(&dstring);
      for(i=0; i<ELTCL_MAXSIG; i++) if (signalNames[i] != NULL) {
	 if (sigismember(&oset, i))
	    Tcl_DStringAppendElement(&dstring, signalNames[i]);
      }
      Tcl_DStringResult(interp, &dstring);
      return TCL_OK;
   }

   /* a script was given: create async handler and register signal */

   if (ctx == NULL) {
      ctx = createSignalContext(signum, iinfo);
      if (ctx == NULL) goto error;
   }

   /* block signal while installing handler */
   sigemptyset(&set);
   sigaddset(&set, signum);
   if (sigprocmask(SIG_BLOCK, &set, &oset)) goto error;

#ifdef SIGWINCH
   if (signum != SIGWINCH)
#endif
      if (signal(signum, signalHandler) == (void *)-1) {
	 sigprocmask(SIG_SETMASK, &oset, NULL);
	 goto error;
      }

   if (ctx->script != ELTCL_SIGDFL && ctx->script != ELTCL_SIGIGN) {
      Tcl_DecrRefCount(ctx->script);
      Tcl_AsyncDelete(ctx->asyncH);
   }

   ctx->script = objv[2];
   Tcl_IncrRefCount(ctx->script);
   ctx->asyncH = Tcl_AsyncCreate(asyncSignalHandler, ctx);

   sigprocmask(SIG_SETMASK, &oset, NULL);
   return TCL_OK;

  error:
   Tcl_SetResult(interp, (char *)Tcl_ErrnoMsg(errno), TCL_VOLATILE);
   Tcl_SetErrno(errno);
   Tcl_PosixError(interp);
   return TCL_ERROR;
}