Back to index

lightning-sunbird  0.9+nobinonly
Defines | Functions | Variables
ltermManager.c File Reference
#include "lineterm.h"
#include "ltermPrivate.h"

Go to the source code of this file.

Defines

#define CHECK_IF_VALID_LTERM_NUMBER(procname, lterm)
#define GLOBAL_LOCK   MUTEX_LOCK(ltermGlobal.listMutex)
#define GLOBAL_UNLOCK   MUTEX_UNLOCK(ltermGlobal.listMutex)
#define SWITCH_GLOBAL_TO_UNILOCK(procname, mutex, mutex_flag)
#define RELEASE_UNILOCK(mutex, mutex_flag)
#define LTERM_OPEN_ERROR_RETURN(lterm, lts, errmsg)

Functions

int ltermClose (struct lterms *lts)
 Closes an LTERM described by structure pointed to by LTS.
static int ltermShellInit (struct lterms *lts, int all)
 Sends shell initialization commands, if any (WORKS UNDER GLOBAL_LOCK)
static int ltermCreatePipe (FILEDESC *writePIPE, FILEDESC *readPIPE)
 Creates unidirectional pipe which can be written to and read from using the file descriptors writePIPE and readPIPE.
static int ltermCreateProcess (struct LtermProcess *ltp, char *const argv[], int nostderr, int noexport)
 Creates a new process to execute the command line contained in array ARGV and redirects its standard I/O and standard error through pipes.
static void ltermDestroyProcess (struct LtermProcess *ltp)
 Destroys process pointed by LTP.
int lterm_init (int messageLevel)
 Initializes all LTERM operations (documented in the LTERM interface)
int lterm_new ()
 Creates a new LTERM object and returns its descriptor index but does not open it for I/O (documented in the LTERM interface)
int lterm_open (int lterm, char *const argv[], const char *cookie, const char *init_command, const UNICHAR *prompt_regexp, int options, int process_type, int rows, int cols, int x_pixels, int y_pixels, lterm_callback_func_t callback_func, void *callback_data)
 Opens an LTERM for I/O (documented in the LTERM interface)
int lterm_close (int lterm)
 Closes an LTERM (documented in the LTERM interface)
int lterm_delete (int lterm)
 Deletes an LTERM object, closing it if necessary (documented in the LTERM interface)
void lterm_close_all ()
 Closes all LTERMs, but does not delete them.
int lterm_setecho (int lterm, int echo_flag)
 Sets input echo flag for LTERM (documented in the LTERM interface)
int lterm_resize (int lterm, int rows, int cols)
 Resizes the line terminal indexed by LTERM to new row/column count.
int lterm_setcursor (int lterm, int row, int col)
 Sets cursor position in line terminal indexed by LTERM.
int lterm_write (int lterm, const UNICHAR *buf, int count, int dataType)
 Writes a string to LTERM (documented in the LTERM interface)
int lterm_read (int lterm, int timeout, UNICHAR *buf, int count, UNISTYLE *style, int *opcodes, int *opvals, int *buf_row, int *buf_col, int *cursor_row, int *cursor_col)
 Reads a (possibly incomplete) line from LTERM (documented in the LTERM interface)

Variables

LtermGlobal ltermGlobal

Define Documentation

#define CHECK_IF_VALID_LTERM_NUMBER (   procname,
  lterm 
)
Value:
if ((lterm < 0) || (lterm >= MAXTERM)) {           \
    LTERM_ERROR("procname: Error - LTERM index %d out of range\n", \
                lterm);                              \
    return -1;                                       \
  }

Definition at line 49 of file ltermManager.c.

#define GLOBAL_LOCK   MUTEX_LOCK(ltermGlobal.listMutex)

Definition at line 57 of file ltermManager.c.

#define GLOBAL_UNLOCK   MUTEX_UNLOCK(ltermGlobal.listMutex)

Definition at line 58 of file ltermManager.c.

#define LTERM_OPEN_ERROR_RETURN (   lterm,
  lts,
  errmsg 
)
Value:
LTERM_ERROR(errmsg);  \
  ltermClose(lts);      \
  RELEASE_UNILOCK(adminMutex,adminMutexLocked) \
  lterm_delete(lterm);  \
  return -1;

Definition at line 228 of file ltermManager.c.

#define RELEASE_UNILOCK (   mutex,
  mutex_flag 
)
Value:
lts->mutex_flag = 0;      \
  MUTEX_UNLOCK(lts->mutex);

Definition at line 78 of file ltermManager.c.

#define SWITCH_GLOBAL_TO_UNILOCK (   procname,
  mutex,
  mutex_flag 
)
Value:
if (lts->mutex_flag) {                 \
    LTERM_ERROR("procname: Error - MUTEX mutex already locked\n", \
                lts->mutex);   \
    MUTEX_UNLOCK(ltermGlobal.listMutex); \
    return -1;                           \
  }                                      \
  MUTEX_LOCK(lts->mutex);                \
  lts->mutex_flag = 1;                   \
  MUTEX_UNLOCK(ltermGlobal.listMutex);

Definition at line 67 of file ltermManager.c.


Function Documentation

int lterm_close ( int  lterm)

Closes an LTERM (documented in the LTERM interface)

Closes line terminal indexed by LTERM.

Returns:
0 on success, or -1 on error.

Definition at line 749 of file ltermManager.c.

{
  struct lterms *lts;
  int returnCode;

  CHECK_IF_VALID_LTERM_NUMBER(lterm_close,lterm)

  LTERM_LOG(lterm_close,10,("Closing LTERM %d\n", lterm));

  GLOBAL_LOCK;

  lts = ltermGlobal.termList[lterm];

  if (lts == NULL) {
    /* Forgiving return for non-existent LTERM */
    GLOBAL_UNLOCK;
    return 0;
  }

  if (!lts->opened) {
    LTERM_WARNING("lterm_close: Error - LTERM %d not opened\n", lterm);
    GLOBAL_UNLOCK;
    return -1;
  }

  SWITCH_GLOBAL_TO_UNILOCK(lterm_close,adminMutex,adminMutexLocked)

  returnCode = ltermClose(lts);

  RELEASE_UNILOCK(adminMutex,adminMutexLocked)

  return returnCode;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Closes all LTERMs, but does not delete them.

This may be used to free any resources associated with LTERMs for clean up. The closed LTERMs should still be deleted, if possible.

Definition at line 832 of file ltermManager.c.

{
  int lterm;
  struct lterms *lts;

  LTERM_LOG(lterm_close_all,10,("\n"));

  GLOBAL_LOCK;

  for (lterm=0; lterm < MAXTERM; lterm++) {
    lts = ltermGlobal.termList[lterm];

    if ((lts != NULL) && lts->opened) {
      /* Opened LTERM; close it, disregarding return code */
      lts->adminMutexLocked = 1;
      MUTEX_LOCK(lts->adminMutex);

      /* NOTE,10, ("lterm_close_all:\n"******** This call is being made from within a global lock;
       *                POTENTIAL FOR DEADLOCK?
       */
      ltermClose(lts);

      lts->adminMutexLocked = 0;
      MUTEX_UNLOCK(lts->adminMutex);
    }
  }

  GLOBAL_UNLOCK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int lterm_delete ( int  lterm)

Deletes an LTERM object, closing it if necessary (documented in the LTERM interface)

Deletes an LTERM object, closing it if necessary.

Returns:
0 on success, or -1 on error.

Definition at line 788 of file ltermManager.c.

{
  struct lterms *lts;
  int returnCode;

  CHECK_IF_VALID_LTERM_NUMBER(lterm_delete,lterm)

  LTERM_LOG(lterm_delete,10,("Closing LTERM %d\n", lterm));

  GLOBAL_LOCK;

  lts = ltermGlobal.termList[lterm];

  if (lts == NULL) {
    /* Forgiving return for non-existent LTERM */
    GLOBAL_UNLOCK;
    return 0;
  }

  /* Remove LTERM structure from list */
  ltermGlobal.termList[lterm] = NULL;

  SWITCH_GLOBAL_TO_UNILOCK(lterm_open,adminMutex,adminMutexLocked)

  returnCode = 0;
  if (lts->opened) {
    /* Opened LTERM; close it */
    returnCode = ltermClose(lts);
  }

  RELEASE_UNILOCK(adminMutex,adminMutexLocked)

  MUTEX_DESTROY(lts->adminMutex);

  /* Free memory for LTERMS structure */
  FREE(lts);

  LTERM_LOG(lterm_delete,11,("LTERM deleted\n"));

  return returnCode;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int lterm_init ( int  messageLevel)

Initializes all LTERM operations (documented in the LTERM interface)

Initializes all LTERM operations; needs to be called before any calls to lterm_new.

Returns:
0 on success, or -1 on error.

Definition at line 95 of file ltermManager.c.

{
  if (!ltermGlobal.initialized) {
    int result, j;
    /* Assert that INTs have at least 32-bit precision.
     * This assumption underlies the choice of various bit codes.
     */
    assert(sizeof(int) >= 4);

    if (sizeof(UNICHAR) == 2) {
      /* Assert that the maximum column count fits into an UNICHAR.
       * This assumption is used for input buffer pipe I/O by lterm_write
       * and ltermWrite, but could be relaxed by using different buffer record
       * structure.
       */
      assert(MAXCOL <= 0x7FFF);
    }

    /* Initialize lock for accessing LTERMs array */
    if (MUTEX_INITIALIZE(ltermGlobal.listMutex) != 0)
      return -1;

    /* Initialize trace/log module for STDERR;
     * this could perhaps be eliminated, if TLOG_PRINT is redefined to PR_LOG
     * and so on, with the USE_NSPR_IO option enabled.
     */
    tlog_init(stderr);
    result = tlog_set_level(LTERM_TLOG_MODULE, messageLevel, NULL);

    /* Meta input delimiter */
    ltermGlobal.metaDelimiter = U_COLON;

    /* String of five ASCII characters escaped in XML;
     * only the first four characters are escaped in HTML;
     * it is sufficient to escape just the first three characters, "&<>"
     * when inserting plain text (outside markup) in XML/HTML fragments
     */
    ltermGlobal.escapeChars[LTERM_AMP_ESCAPE]  = '&';
    ltermGlobal.escapeChars[LTERM_LT_ESCAPE]   = '<';
    ltermGlobal.escapeChars[LTERM_GT_ESCAPE]   = '>';
    ltermGlobal.escapeChars[LTERM_QUOT_ESCAPE] = '\"';
    ltermGlobal.escapeChars[LTERM_APOS_ESCAPE] = '\'';
    ltermGlobal.escapeChars[LTERM_XML_ESCAPES] = 0;

    /* List of XML character escape sequences (Unicode) */
    ucscopy(ltermGlobal.escapeSeq[LTERM_AMP_ESCAPE],  "&amp;",
              LTERM_MAXCHAR_ESCAPE+1);
    ucscopy(ltermGlobal.escapeSeq[LTERM_LT_ESCAPE],   "&lt;",
              LTERM_MAXCHAR_ESCAPE+1);
    ucscopy(ltermGlobal.escapeSeq[LTERM_GT_ESCAPE],   "&gt;",
              LTERM_MAXCHAR_ESCAPE+1);
    ucscopy(ltermGlobal.escapeSeq[LTERM_QUOT_ESCAPE], "&quot;",
              LTERM_MAXCHAR_ESCAPE+1);
    ucscopy(ltermGlobal.escapeSeq[LTERM_APOS_ESCAPE], "&apos;",
              LTERM_MAXCHAR_ESCAPE+1);

    /* Escape sequence lengths (including delimiters) */
    for (j=0; j<LTERM_XML_ESCAPES; j++) {
      ltermGlobal.escapeLen[j] = ucslen(ltermGlobal.escapeSeq[j]);
      assert(ltermGlobal.escapeLen[j] <= LTERM_MAXCHAR_ESCAPE);
    }

    /* LTERM global initialization flag */
    ltermGlobal.initialized = 1;

  } else {
    LTERM_WARNING("lterm_init: Warning - already initialized\n");
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Creates a new LTERM object and returns its descriptor index but does not open it for I/O (documented in the LTERM interface)

Returns:
lterm descriptor index (>= 0) on success, or -1 on error

Definition at line 174 of file ltermManager.c.

{
  int lterm;
  struct lterms *lts;

  if (!ltermGlobal.initialized) {
    LTERM_ERROR("lterm_new: Error - call lterm_init() to initialize LTERM library\n");
    return -1;
  }

  LTERM_LOG(lterm_new,10,("Creating LTERM ...\n"));

  /* Allocate memory for new LTERMS structure: needs clean-up */
  lts = (struct lterms *) MALLOC(sizeof(struct lterms));

  if (lts == NULL) {
    LTERM_ERROR("lterm_new: Error - failed to allocate memory for LTERM\n");
    return -1;
  }

  GLOBAL_LOCK;

  for (lterm=0; lterm < MAXTERM; lterm++) {
    if (ltermGlobal.termList[lterm] == NULL)
      break;
  }

  if (lterm == MAXTERM) {
    LTERM_ERROR( "lterm_new: Error - too many LTERMS; recompile with increased MAXTERM\n");
    FREE(lts);  /* Clean up memory allocation for LTERMS structure */
    GLOBAL_UNLOCK;
    return -1;
  }
  
  /* Insert LTERM pointer in list of LTERMs */
  ltermGlobal.termList[lterm] = lts;

  MUTEX_INITIALIZE(lts->adminMutex);

  /* Administrative thread inactive */
  lts->adminMutexLocked = 0;

  /* LTERM not yet opened for I/O */
  lts->opened = 0;

  GLOBAL_UNLOCK;

  LTERM_LOG(lterm_new,11,("created lterm = %d\n", lterm));

  return lterm;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int lterm_open ( int  lterm,
char *const  argv[],
const char *  cookie,
const char *  init_command,
const UNICHAR prompt_regexp,
int  options,
int  process_type,
int  rows,
int  cols,
int  x_pixels,
int  y_pixels,
lterm_callback_func_t  callback_func,
void callback_data 
)

Opens an LTERM for I/O (documented in the LTERM interface)

Opens line terminal indexed by LTERM for input/output and creates a process attached to it to execute the command line contained in string array ARGV.

Returns:
0 on success, or -1 on error

Definition at line 239 of file ltermManager.c.

{
  int nostderr, noPTY, j;
  struct ptys ptyStruc;
  struct lterms *lts;
  struct LtermInput *lti;
  struct LtermOutput *lto;
  struct LtermProcess *ltp;
  char *const *cargv;
  char *defaultArgs[3];

  if (!ltermGlobal.initialized) {
    LTERM_ERROR("lterm_open: Error - call lterm_init() to initialize LTERM library\n");
    return -1;
  }

  CHECK_IF_VALID_LTERM_NUMBER(lterm_open,lterm)

  LTERM_LOG(lterm_open,10,("Opening LTERM %d\n", lterm));

  GLOBAL_LOCK;

  lts = ltermGlobal.termList[lterm];

  if (lts == NULL) {
    LTERM_ERROR("lterm_open: Error - LTERM %d not created using lterm_new\n",
                lterm);
    GLOBAL_UNLOCK;
    return -1;
  }

  if (lts->opened) {
    LTERM_ERROR("lterm_open: Error - LTERM %d is already open\n",
                lterm);
    GLOBAL_UNLOCK;
    return -1;
  }

  SWITCH_GLOBAL_TO_UNILOCK(lterm_open,adminMutex,adminMutexLocked)

  /* Pointers to LTERM process/input/output structures */
  ltp = &(lts->ltermProcess);
  lti = &(lts->ltermInput);
  lto = &(lts->ltermOutput);

  /* Initialize flags/pointers/file descriptors that need to be cleaned up */
  lts->suspended = 0;
  lts->ptyMode   = 0;

  /* Initialize TTY control characters */
  assert(TTYWERASE < MAXTTYCONTROL);
  lts->control[TTYINTERRUPT] = U_CTL_C;
  lts->control[TTYERASE]     = U_DEL;
  lts->control[TTYKILL]      = U_CTL_U;
  lts->control[TTYEOF]       = U_CTL_D;
  lts->control[TTYSUSPEND]   = U_CTL_Z;
  lts->control[TTYREPRINT]   = U_CTL_R;
  lts->control[TTYDISCARD]   = U_CTL_O;
  lts->control[TTYWERASE]    = U_CTL_W;

  lts->writeBUFFER =  NULL_FILEDESC;
  lts->readBUFFER =   NULL_FILEDESC;

  /* Clear input line break flag */
  lts->inputLineBreak = 0;

  /* Clear input buffer */
  lti->inputBufBytes = 0;
  lts->inputBufRecord = 0;

  /* Clear styleMask */
  lto->styleMask = 0;

  /* Clear incomplete raw output buffers */
  lto->rawOUTBytes = 0;
  lto->rawERRBytes = 0;

  /* Clear decoded output buffer */
  lto->decodedChars = 0;
  lto->incompleteEscapeSequence = 0;

  /* Set initial screen size */
  lts->nRows = rows;
  lts->nCols = cols;
  lts->xPixels = y_pixels;
  lts->yPixels = x_pixels;

  /* Clear screen buffer */
  lto->screenChar  = NULL;
  lto->screenStyle = NULL;

  lts->outputMutexLocked = 0;

  MUTEX_INITIALIZE(lts->outputMutex);

  /* AT THIS POINT, LTERMCLOSE MAY BE CALLED FOR CLEAN-UP */

  /* Create input buffer pipe; needs clean-up */
  if (ltermCreatePipe(&(lts->writeBUFFER), &(lts->readBUFFER)) != 0) {
    LTERM_OPEN_ERROR_RETURN(lterm,lts,
                "lterm_open: Error - input buffer pipe creation failed\n")
  }

  LTERM_LOG(lterm_open,11,("Created input buffer pipe\n", lterm));

  defaultArgs[0] = NULL;
  defaultArgs[1] = "-i";
  defaultArgs[2] = NULL;

  if (argv != NULL) {
    /* Use supplied command arguments */
    cargv= argv;

  } else {
    /* Default command arguments */
    defaultArgs[0] = (char *) getenv("SHELL");
    if (defaultArgs[0] == NULL)
      defaultArgs[0] = "/bin/sh";
    cargv= defaultArgs;
  }

  if (process_type >= 0) {
    /* Specified process type code */
    lts->processType = process_type;

  } else {
    /* Determine process type code from path name */
    char *lastSlash;
    char *tailStr;

    /* Find the last occurrence of slash */
    lastSlash = (char *) strrchr(cargv[0], '/');
    if (lastSlash == NULL) {
      tailStr = cargv[0];
    } else {
      tailStr = lastSlash + 1;
    }

    if (strcmp(tailStr,"sh") == 0) {
      lts->processType = LTERM_SH_PROCESS;

    } else if (strcmp(tailStr,"ksh") == 0) {
      lts->processType = LTERM_KSH_PROCESS;

    } else if (strcmp(tailStr,"bash") == 0) {
      lts->processType = LTERM_BASH_PROCESS;

    } else if (strcmp(tailStr,"csh") == 0) {
      lts->processType = LTERM_CSH_PROCESS;

    } else if (strcmp(tailStr,"tcsh") == 0) {
      lts->processType = LTERM_TCSH_PROCESS;

    } else {
      lts->processType = LTERM_UNKNOWN_PROCESS;
    }
  }

  LTERM_LOG(lterm_open,11,("process type code = %d\n", lts->processType));

  /* TTY options */
  lts->options = options;
  lts->noTTYEcho = (options & LTERM_NOECHO_FLAG) != 0;
  lts->disabledInputEcho = 1;
  lts->restoreInputEcho = 1;

  nostderr = (options & LTERM_STDERR_FLAG) == 0;

#if defined(NO_PTY) || defined(USE_NSPR_IO)
  /* Current implementation of pseudo-TTY is incompatible with the NSPR I/O
     option; set the USE_NSPR_IO option only on platforms where
     PTYSTREAM is not implemented.
     Reason for incompatibility: cannot combine the UNIX-style integral
     PTY file descriptor and NSPR's PRFileDesc in the same poll function
     call.
  */
  noPTY = 1;
#else
  noPTY = (options & LTERM_NOPTY_FLAG);
#endif

  if (noPTY) {
    /* Create pipe process: needs clean-up */
    if (ltermCreateProcess(ltp, cargv, nostderr, 0) == -1) {

      LTERM_OPEN_ERROR_RETURN(lterm,lts,
            "lterm_open: Pipe process creation failed\n")
    }

  } else {
    /* Create pseudo-TTY with blocking I/O: needs clean-up */
    int noblock = 1;
    int noexport = 0;
    int debugPTY = (tlogGlobal.messageLevel[LTERM_TLOG_MODULE] > 1);
    int errfd = nostderr?-1:-2;

    LTERM_LOG(lterm_open,11,
              ("errfd=%d, noecho=%d, noblock=%d, noexport=%d, debugPTY=%d\n",
               errfd, lts->noTTYEcho, noblock, noexport, debugPTY));
#ifndef NO_PTY
    if (pty_create(&ptyStruc, cargv,
                   lts->nRows, lts->nCols, lts->xPixels, lts->yPixels,
                   errfd, noblock, lts->noTTYEcho, noexport, debugPTY) == -1) {
      LTERM_OPEN_ERROR_RETURN(lterm,lts,
            "lterm_open: Error - PTY creation failed\n")
    }
#endif  /* !NO_PTY */

    /* Copy PTY structure */
    lts->pty = ptyStruc;
    lts->ptyMode = 1;
  }

  /* Set up LtermOutput polling structure */
  lto->pollFD[POLL_INPUTBUF].fd = lts->readBUFFER;
  lto->pollFD[POLL_INPUTBUF].POLL_EVENTS = POLL_READ;

  if (lts->ptyMode) {
#ifndef USE_NSPR_IO
    lto->pollFD[POLL_STDOUT].fd = lts->pty.ptyFD;
    lto->pollFD[POLL_STDOUT].POLL_EVENTS = POLL_READ;

    if (VALID_FILEDESC(lts->pty.errpipeFD)) {
      lto->pollFD[POLL_STDERR].fd = lts->pty.errpipeFD;
      lto->pollFD[POLL_STDERR].POLL_EVENTS = POLL_READ;
      lto->nfds = POLL_COUNT;
    } else {
        lto->nfds = POLL_COUNT-1;
    }
#else
    /* Current implementation of pseudo-TTY incompatible with USE_NSPR_IO */
    LTERM_OPEN_ERROR_RETURN(lterm,lts,
           "lterm_open: Error - pseudo-TTY incompatible with USE_NSPR_IO\n")
#endif

  } else {
    lto->pollFD[POLL_STDOUT].fd = ltp->processOUT;
    lto->pollFD[POLL_STDOUT].POLL_EVENTS = POLL_READ;

    if (VALID_FILEDESC(ltp->processERR)) {
      lto->pollFD[POLL_STDERR].fd = ltp->processERR;
      lto->pollFD[POLL_STDERR].POLL_EVENTS = POLL_READ;
      lto->nfds = POLL_COUNT;
    } else {
      lto->nfds = POLL_COUNT-1;
    }
  }

  /* No callbacks initially associated with this LTERM */
  for (j=0; j<lto->nfds; j++)
    lto->callbackTag[j] = 0;

  /* Determine whether STDERR should be read before STDOUT */
  if (lts->processType == LTERM_TCSH_PROCESS) {
    lts->readERRfirst = 0;
  } else {
    lts->readERRfirst = 1;
  }

  /* Determine whether STDERR and STDOUT should be interleaved */
  lts->interleave = 1;

  /* Determine maximum value for input mode */
  if (options & LTERM_NOCANONICAL_FLAG)
    lts->maxInputMode = LTERM0_RAW_MODE;

  else if (options & LTERM_NOEDIT_FLAG)
    lts->maxInputMode = LTERM1_CANONICAL_MODE;

  else if ((options & LTERM_NOCOMPLETION_FLAG) ||
           lts->noTTYEcho)
    lts->maxInputMode = LTERM2_EDIT_MODE;

  else {
    if ((lts->processType == LTERM_BASH_PROCESS) ||
        (lts->processType == LTERM_TCSH_PROCESS))
      lts->maxInputMode = LTERM3_COMPLETION_MODE;
    else
      lts->maxInputMode = LTERM2_EDIT_MODE;
  }

  LTERM_LOG(lterm_open,11,("options=0x%x, processType=%d, readERRfirst=%d, maxInputMode=%d\n",
                lts->options, lts->processType, lts->readERRfirst, lts->maxInputMode));
  LTERM_LOGUNICODE(lterm_open,11,(prompt_regexp, (int) ucslen(prompt_regexp) ));

  if (cookie != NULL) {
    /* Copy cookie string (no more than MAXCOOKIESTR-1 characters) */
    if (strlen(cookie) > MAXCOOKIESTR-1) {
      LTERM_WARNING("lterm_open: Warning - cookie string truncated\n");
    }
    strncpy(lts->cookie, cookie, MAXCOOKIESTR-1);
    lts->cookie[MAXCOOKIESTR-1] = '\0';
  } else {
    /* No cookie */
    lts->cookie[0] = '\0';
  }

  LTERM_LOG(lterm_open,11,("cookie='%s'\n",lts->cookie));

  /* Shell initialization commands have not been sent yet */
  lts->shellInitCommands = 0;

  /* NOTE: Shell init commands are stored in reverse order of execution */

  if (init_command != NULL) {
    /* User supplied shell init command */

    if (strlen(init_command) <= MAXSHELLINITSTR-1) {
      int cmd = lts->shellInitCommands++;
      assert(cmd < MAXSHELLINITCMD);

      (void) strncpy(lts->shellInitStr[cmd], init_command, MAXSHELLINITSTR-1);
      lts->shellInitStr[cmd][MAXSHELLINITSTR-1] = '\0';

    } else {
      LTERM_WARNING("lterm_open: Warning - user init command too long\n");
    }
  }

  if (lts->processType != LTERM_UNKNOWN_PROCESS) {
    /* Process dependent shell init command */
    int result;
    char* shellInitFormat;

    if ((lts->processType == LTERM_CSH_PROCESS) ||
      (lts->processType == LTERM_TCSH_PROCESS)) {
      /* C-shell family */
      shellInitFormat = "setenv LTERM_COOKIE '%s'\n";

    } else {
      /* Bourne-shell family */
      shellInitFormat = "LTERM_COOKIE='%s'; export LTERM_COOKIE\n";
    }

    /* **** WATCH OUT FOR BUFFER OVERFLOW!!! *** */
    if (strlen(shellInitFormat)-4+strlen(lts->cookie) <= MAXSHELLINITSTR-1) {

      int cmd = lts->shellInitCommands++;
      assert(cmd < MAXSHELLINITCMD);

      sprintf(lts->shellInitStr[cmd], shellInitFormat, lts->cookie);
      lts->shellInitStr[cmd][MAXSHELLINITSTR-1] = '\0';

    } else {
      LTERM_WARNING("lterm_open: Warning - process init command too long\n");
    }
  }

  for (j=lts->shellInitCommands-1; j>0; j--) {
    LTERM_LOG(lterm_open,11,("shellInitStr%d='%s'\n",j,lts->shellInitStr[j]));
  }

  /* Initialize regular expression string matching command prompt */
  if ((ucslen(prompt_regexp) == 0) ||
      (ucslen(prompt_regexp) > MAXPROMPT-1)) {
    LTERM_OPEN_ERROR_RETURN(lterm,lts,
         "lterm_open: Error - prompt_regexp string too short/long\n")
  }

  ucsncpy( lts->promptRegexp, prompt_regexp, MAXPROMPT);

  /* Command number counter */
  lts->lastCommandNum = 0;

  /* Command completion request code */
  lts->completionRequest = LTERM_NO_COMPLETION;

  /* Clear output line buffer and switch to line output mode */
  ltermClearOutputLine(lts);
  lto->outputMode = LTERM2_LINE_MODE;
  lto->styleMask = 0;

  /* Reset terminal modes */
  lto->insertMode = 0;
  lto->automaticNewline = 0;

  /* Clear input line buffer */
  ltermClearInputLine(lts);

  /* Clear input line flag not yet set */
  lti->clearInputLine = 0;

  /* Reset input opcodes */
  lti->inputOpcodes = 0;

  /* Open LTERM */
  lts->opened = 1;

  /* Initialize any callbacks associated with this LTERM */
  if (callback_func != NULL) {
#if !defined(USE_NSPR_IO) && defined(USE_GTK_WIDGETS)
    LTERM_LOG(lterm_open,11,("Initializing %d callbacks for LTERM %d\n",
                               lto->nfds, lterm));

    for (j=0; j<lto->nfds; j++) {
      lto->callbackTag[j] = gdk_input_add(lto->pollFD[j].fd,
                                          GDK_INPUT_READ,
                                          callback_func,
                                          (gpointer) callback_data);
      if (lto->callbackTag[j] == 0) {
        LTERM_OPEN_ERROR_RETURN(lterm,lts,
                    "lterm_open: Error - unable to add callback\n")
      }
    }
#else
    LTERM_OPEN_ERROR_RETURN(lterm,lts,
      "lterm_open: Error - callbacks not implemented for this configuration\n")
#endif
  }


  RELEASE_UNILOCK(adminMutex,adminMutexLocked)

  LTERM_LOG(lterm_open,11,
      ("outputMode=%d, inputMode=%d, maxInputMode=%d\n",
      lto->outputMode, lti->inputMode,lts->maxInputMode ));

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int lterm_read ( int  lterm,
int  timeout,
UNICHAR buf,
int  count,
UNISTYLE style,
int opcodes,
int opvals,
int buf_row,
int buf_col,
int cursor_row,
int cursor_col 
)

Reads a (possibly incomplete) line from LTERM (documented in the LTERM interface)

reads upto COUNT Unicode characters from a single line of output from line terminal indexed by LTERM into BUF.

Definition at line 1126 of file ltermManager.c.

{
  struct lterms *lts;
  int returnCode, temCode;
  struct LtermRead ltrStruc;

  CHECK_IF_VALID_LTERM_NUMBER(lterm_read,lterm)

  LTERM_LOG(lterm_read,10,("Reading from LTERM %d\n", lterm));

  GLOBAL_LOCK;

  lts = ltermGlobal.termList[lterm];

  if (lts == NULL || !lts->opened || lts->suspended) {
    /* LTERM is deleted/closed/suspended */
    if (lts == NULL)
      LTERM_WARNING("lterm_read: Warning - LTERM %d not active\n", lterm);

    *opcodes = 0;
    *opvals = 0;
    *buf_row = 0;
    *buf_col = 0;
    *cursor_row = 0;
    *cursor_col = 0;

    GLOBAL_UNLOCK;
    return -2;
  }

  SWITCH_GLOBAL_TO_UNILOCK(lterm_read,outputMutex,outputMutexLocked)

  /* Copy "input" parameters to LtermRead structure */
  ltrStruc.buf = buf;
  ltrStruc.style = style;
  ltrStruc.max_count = count;

  /* Call auxiliary function to read data */
  temCode = ltermRead(lts, &ltrStruc, timeout);

  if (temCode == 0) {
    /* Return count of characters read */
    returnCode = ltrStruc.read_count;
  } else {
    /* Error return */
    returnCode = temCode;
  }

  /* Copy "output" parameters from LtermRead structure */
  *opcodes = ltrStruc.opcodes;
  *opvals = ltrStruc.opvals;
  *buf_row = ltrStruc.buf_row;
  *buf_col = ltrStruc.buf_col;
  *cursor_row = ltrStruc.cursor_row;
  *cursor_col = ltrStruc.cursor_col;

  if (returnCode == -1) {
    /* Error return code; suspend TTY */
    LTERM_WARNING("lterm_read: Warning - LTERM %d suspended due to error\n", lterm);
    lts->suspended = 1;
  }

  RELEASE_UNILOCK(outputMutex,outputMutexLocked)

  GLOBAL_LOCK;
  if ((*opcodes != 0) && (lts->shellInitCommands > 0)) {
    /* send shell initialization string */
    if (ltermShellInit(lts,0) != 0) {
      GLOBAL_UNLOCK;
      return -1;
    }
  }
  GLOBAL_UNLOCK;

  LTERM_LOG(lterm_read,11,("return code = %d, opcodes=0x%x, opvals=%d\n",
                           returnCode, *opcodes, *opvals));

  return returnCode;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int lterm_resize ( int  lterm,
int  rows,
int  cols 
)

Resizes the line terminal indexed by LTERM to new row/column count.

Called from the output thread of LTERM.

Returns:
0 on success, or -1 on error.

Definition at line 906 of file ltermManager.c.

{
  struct lterms *lts;
  struct LtermOutput *lto;

  CHECK_IF_VALID_LTERM_NUMBER(lterm_resize,lterm)

  LTERM_LOG(lterm_resize,10,("Resizing LTERM=%d, rows=%d, cols=%d\n",
                             lterm, rows, cols));

  if ((rows <= 0)  || (cols <= 0))
    return -1;

  GLOBAL_LOCK;

  lts = ltermGlobal.termList[lterm];

  if (lts == NULL || !lts->opened || lts->suspended) {
    /* LTERM is deleted/closed/suspended */
    if (lts == NULL)
      LTERM_WARNING("lterm_resize: Warning - LTERM %d not active\n", lterm);
    GLOBAL_UNLOCK;
    return -2;
  }

  if ((rows == lts->nRows) && (cols == lts->nCols)) {
    /* Nothing to do */
    GLOBAL_UNLOCK;
    return 0;
  }

  lto = &(lts->ltermOutput);

  LTERM_LOG(lterm_resize,12,("lto->outputMode=%d\n",
                             lto->outputMode));

  /* Free full screen buffers */
  if (lto->screenChar != NULL)
    FREE(lto->screenChar);

  if (lto->screenStyle != NULL)
    FREE(lto->screenStyle);

  lto->screenChar  = NULL;
  lto->screenStyle = NULL;

  /* Resize screen */
  lts->nRows = rows;
  lts->nCols = cols;

  if (lto->outputMode == LTERM1_SCREEN_MODE) {
    /* Clear screen */
    if (ltermClearOutputScreen(lts) != 0)
      return -1;
  }

  if (lts->ptyMode) {
    /* Resize PTY */
#ifndef NO_PTY
    if (pty_resize(&(lts->pty), lts->nRows, lts->nCols, 0, 0) != 0) {
      GLOBAL_UNLOCK;
      return -1;
    }
#endif  /* !NO_PTY */
  }

  GLOBAL_UNLOCK;

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int lterm_setcursor ( int  lterm,
int  row,
int  col 
)

Sets cursor position in line terminal indexed by LTERM.

NOT YET IMPLEMENTED Row numbers increase upward, starting from 0. Column numbers increase rightward, starting from 0. Called from the output thread of LTERM.

Returns:
0 on success, or -1 on error.

Definition at line 986 of file ltermManager.c.

{
  struct lterms *lts;

  CHECK_IF_VALID_LTERM_NUMBER(lterm_setcursor,lterm)

  LTERM_LOG(lterm_setcursor,10,
            ("Setting cursor, LTERM=%d row=%d, col=%d (NOT YET IMPLEMENTED)\n",
             lterm, row, col));

  GLOBAL_LOCK;

  lts = ltermGlobal.termList[lterm];

  if (lts == NULL || !lts->opened || lts->suspended) {
    /* LTERM is deleted/closed/suspended */
    if (lts == NULL)
      LTERM_WARNING("lterm_setcursor: Warning - LTERM %d not active\n", lterm);
    GLOBAL_UNLOCK;
    return -2;
  }

  GLOBAL_UNLOCK;

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int lterm_setecho ( int  lterm,
int  echo_flag 
)

Sets input echo flag for LTERM (documented in the LTERM interface)

Set input echo flag for line terminal indexed by LTERM.

Definition at line 864 of file ltermManager.c.

{
  struct lterms *lts;

  CHECK_IF_VALID_LTERM_NUMBER(lterm_setecho,lterm)

  LTERM_LOG(lterm_setecho,10,("LTERM=%d, echo_flag=%d\n", lterm, echo_flag));

  GLOBAL_LOCK;

  lts = ltermGlobal.termList[lterm];

  if (lts == NULL || !lts->opened || lts->suspended) {
    /* LTERM is deleted/closed/suspended */
    if (lts == NULL)
      LTERM_WARNING("lterm_setecho: Warning - LTERM %d not active\n", lterm);
    GLOBAL_UNLOCK;
    return -2;
  }

  if (lts->shellInitCommands > 0) {
    /* send shell initialization string */
    if (ltermShellInit(lts,1) != 0) {
      GLOBAL_UNLOCK;
      return -1;
    }
  }

  lts->disabledInputEcho = !echo_flag;
  lts->restoreInputEcho = 0;

  GLOBAL_UNLOCK;

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int lterm_write ( int  lterm,
const UNICHAR buf,
int  count,
int  dataType 
)

Writes a string to LTERM (documented in the LTERM interface)

Writes supplied to Unicode string in BUF of length COUNT to line terminal indexed by LTERM.

Definition at line 1015 of file ltermManager.c.

{
  struct lterms *lts;
  FILEDESC writeBUFFER;
  int byteCount, sentCount, packetCount, j;
  UNICHAR temLine[PIPEHEADER+MAXCOL], uch;

  CHECK_IF_VALID_LTERM_NUMBER(lterm_write,lterm)

  LTERM_LOG(lterm_write,10,("Writing to LTERM %d\n", lterm));

  GLOBAL_LOCK;

  lts = ltermGlobal.termList[lterm];

  if (lts == NULL || !lts->opened || lts->suspended) {
    /* LTERM is deleted/closed/suspended */
    if (lts == NULL)
      LTERM_WARNING("lterm_write: Warning - LTERM %d not active\n", lterm);
    GLOBAL_UNLOCK;
    return -2;
  }

  assert(VALID_FILEDESC(lts->writeBUFFER));

  /* Save copy of input buffer file descriptor */
  writeBUFFER = lts->writeBUFFER;

  if (lts->restoreInputEcho == 1) {
    /* Restore TTY echo on input */
    lts->restoreInputEcho = 0;
    lts->disabledInputEcho = 0;
  }

  if (lts->shellInitCommands > 0) {
    /* send shell initialization string */
    if (ltermShellInit(lts,1) != 0) {
      GLOBAL_UNLOCK;
      return -1;
    }
  }

  GLOBAL_UNLOCK;

  assert(count >= 0);

  sentCount = 0;
  while (sentCount < count) {
    packetCount = count - sentCount;  /* always > 0 */

    if (packetCount > MAXCOLM1)
      packetCount = MAXCOLM1;

    if ( (dataType == LTERM_WRITE_PLAIN_INPUT) ||
         (dataType == LTERM_WRITE_PLAIN_OUTPUT) ) {
      /* Plain text data; break at control characters,
       * but break at ESCape character only if not the first character;
       * this ensures that escape sequences fit into one record
       */

      for (j=0; j<packetCount; j++) {
        uch = buf[j+sentCount];
        temLine[j+PIPEHEADER] = uch;

        if ((uch < (UNICHAR)U_SPACE) &&
            ((uch != (UNICHAR)U_ESCAPE) || (j > 0)))
          break;
      }

      if (j<packetCount)
        packetCount = j+1;

      if ( (packetCount > 1) &&
           (temLine[PIPEHEADER+packetCount-1] == U_ESCAPE) ) {
        /* Save any terminal ESCape character for next packet, unless alone */
        packetCount--;
      }

    } else {
      /* XML element data (must represent complete element) */
      for (j=0; j<packetCount; j++)
        temLine[j+PIPEHEADER] = buf[j+sentCount];
    }

    byteCount = (PIPEHEADER+packetCount)*sizeof(UNICHAR);

    /* Header contains packet character count and data type */
    temLine[0]         = (UNICHAR) packetCount;
    temLine[PHDR_TYPE] = (UNICHAR) dataType;

    LTERM_LOGUNICODE(lterm_write,12,(&temLine[PIPEHEADER], packetCount));

    if (WRITE(lts->writeBUFFER,temLine,(SIZE_T)byteCount) != byteCount) {
      LTERM_ERROR("lterm_write: Error in writing to input pipe buffer\n");
      return -1;
    }

    LTERM_LOG(lterm_write,11,
              ("wrote %d characters of type %d data to input buffer pipe\n",
               packetCount, dataType));

    sentCount += packetCount;
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ltermClose ( struct lterms lts)

Closes an LTERM described by structure pointed to by LTS.

(Auxiliary routine for lterm_close, lterm_delete, and lterm_close_all) NOTE: This routine should not attempt to acquire the global lock, since it is called from LTERM_CLOSE_ALL under a global lock.

Returns:
0 on success, or -1 on error.

Definition at line 670 of file ltermManager.c.

{
  struct LtermInput *lti;
  struct LtermOutput *lto;
  UNICHAR closeMessage[2] = {0, LTERM_WRITE_CLOSE_MESSAGE};
  int j;

  LTERM_LOG(ltermClose,10,("Closing LTERM\n"));

  assert(lts != NULL);

  /* Admin thread must be active */
  assert(lts->adminMutexLocked);

  /* Suspend LTERM to prevent any further I/O operations */
  lts->suspended = 1;

  /* Pointers to LTERM input/output structures */
  lti = &(lts->ltermInput);
  lto = &(lts->ltermOutput);

  /* Send close signal to any terminate blocked read operation */
  WRITE(lts->writeBUFFER, closeMessage, (SIZE_T)(2*sizeof(UNICHAR)) );

  /* Wait for read operations to complete */
  MUTEX_LOCK(lts->outputMutex);
  MUTEX_UNLOCK(lts->outputMutex);

  /* Destroy output mutex */
  MUTEX_DESTROY(lts->outputMutex);

  /* Close input buffer pipe */
  if (VALID_FILEDESC(lts->writeBUFFER))
    CLOSE(lts->writeBUFFER);

  if (VALID_FILEDESC(lts->readBUFFER))
    CLOSE(lts->readBUFFER);

#ifdef USE_GTK_WIDGETS
  /* Remove any callbacks associated with this LTERM */
  for (j=0; j<lto->nfds; j++) {
    if (lto->callbackTag[j] != 0) {
      gdk_input_remove((gint) lto->callbackTag[j]);
      lto->callbackTag[j] = 0;
    }
  }
#endif

  if (lts->ptyMode) {
    /* Close PTY */
#ifndef NO_PTY
    pty_close(&(lts->pty));
#endif  /* !NO_PTY */

  } else {
    /* Destroy process */
    ltermDestroyProcess(&(lts->ltermProcess));
  }

  /* Free full screen buffers */
  if (lto->screenChar != NULL)
    FREE(lto->screenChar);

  if (lto->screenStyle != NULL)
    FREE(lto->screenStyle);

  /* Close LTERM */
  lts->opened = 0;

  LTERM_LOG(ltermClose,11,("LTERM closed\n"));

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ltermCreatePipe ( FILEDESC writePIPE,
FILEDESC readPIPE 
) [static]

Creates unidirectional pipe which can be written to and read from using the file descriptors writePIPE and readPIPE.

Returns:
0 on success and -1 on error.

Definition at line 1270 of file ltermManager.c.

{
  FILEDESC pipeFD[2];

  LTERM_LOG(ltermCreatePipe,20,("Creating pipe\n"));

  /* Assume that pipe is unidirectional, although in some UNIX
     systems pipes are actually bidirectional */

  if (PIPE(pipeFD) == -1) {
    LTERM_ERROR("ltermCreatePipe: Error - pipe creation failed\n");
    return -1;
  }

  /* Copy pipe file descriptor */
  *readPIPE  = pipeFD[0];
  *writePIPE = pipeFD[1];

  return 0;
}

Here is the caller graph for this function:

static int ltermCreateProcess ( struct LtermProcess ltp,
char *const  argv[],
int  nostderr,
int  noexport 
) [static]

Creates a new process to execute the command line contained in array ARGV and redirects its standard I/O and standard error through pipes.

The process details are stored in the structure pointed to by LTP. If NOSTDERR is true, STDERR is redirected to STDOUT. If NOEXPORT is true, then the current environment is not exported to the new process.

Returns:
0 on success and -1 on error.

Definition at line 1300 of file ltermManager.c.

{
  FILEDESC stdIN, stdOUT, stdERR;
#ifdef USE_NSPR_IO
  PRProcessAttr *processAttr;
#else
  long child_pid;
#endif

  LTERM_LOG(ltermCreateProcess,20,("Creating process %s, nostderr=%d, noexport=%d\n", argv[0], nostderr, noexport));

  if (nostderr) {
    /* No STDERR pipe */
    ltp->processERR = NULL_FILEDESC;
    stdERR=           NULL_FILEDESC;
  } else {
    /* Create STDERR pipe: needs clean-up */
    FILEDESC pipeFD[2];

    if (PIPE(pipeFD) == -1) {
      LTERM_ERROR("ltermCreateProcess: Error - STDERR pipe creation failed\n");
      return -1;
    }

    /* Copy pipe file descriptor */
    ltp->processERR = pipeFD[0];
    stdERR = pipeFD[1];
  }

  /* Create I/O pipes: needs clean up */
  if ( (ltermCreatePipe(&(ltp->processIN), &stdIN) != 0) ||
       (ltermCreatePipe(&stdOUT, &(ltp->processOUT)) != 0) )
    return -1;

#ifdef USE_NSPR_IO
  /* Create new process attribute structure */
  processAttr = PR_NewProcessAttr();

  /* Redirect standard error for process */
  if (VALID_FILEDESC(stdERR))
    PR_ProcessAttrSetStdioRedirect(processAttr, (PRSpecialFD) 2, stdERR);
  else
    PR_ProcessAttrSetStdioRedirect(processAttr, (PRSpecialFD) 2, stdOUT);

  /* Redirect standard I/O for process */
  PR_ProcessAttrSetStdioRedirect(processAttr, (PRSpecialFD) 0, stdIN);
  PR_ProcessAttrSetStdioRedirect(processAttr, (PRSpecialFD) 1, stdOUT);

  /* Create NSPR process; do not export environment */
  ltp->processID = PR_CreateProcess(argv[0], argv,
                                    (char *const *)0, processAttr);

  if (!VALID_PROCESS(ltp->processID)) {
    LTERM_ERROR("ltermCreateProcess: Error in creating NSPR process %s\n",
                 argv[0]);
    return -1;
  }

  LTERM_LOG(ltermCreateProcess,21,("Created NSPR process\n"));

#else  /* not USE_NSPR_IO */

  /* Fork a child process (FORK) */
  child_pid = fork();
  if (child_pid < 0) {
    LTERM_ERROR("ltermCreateProcess: Error - fork failed\n");
    return -1;
  }

  LTERM_LOG(ltermCreateProcess,21,("vfork child pid = %d\n", child_pid));

  if (child_pid == 0) {
    /* Child process */
    int fdMax, fd;

    /* Redirect to specified descriptor or to PTY */
    if (VALID_FILEDESC(stdERR)) {
      /* Redirect STDERR to specified file descriptor */
      if (dup2(stdERR, 2) == -1) {
        LTERM_ERROR("ltermCreateProcess: Error - failed dup2 for specified stderr\n");
        return -1;
      }

    } else {
      /* Redirect STDERR to STDOUT pipe */
      if (dup2(stdOUT, 2) == -1) {
        LTERM_ERROR("ltermCreateProcess: Error - failed dup2 for default stderr\n");
        return -1;
      }
    }

    /* Redirect STDIN and STDOUT to pipes */
    if (dup2(stdIN, 0) == -1) {
      LTERM_ERROR("ltermCreateProcess: Error - failed dup2 for stdin\n");
      return -1;
    }

    if (dup2(stdOUT, 1) == -1) {
      LTERM_ERROR("ltermCreateProcess: Error - failed dup2 for stdout\n");
      return -1;
    }

    /* Close all other file descriptors in child process */
    fdMax = sysconf(_SC_OPEN_MAX);
    for (fd = 3; fd < fdMax; fd++)
      close(fd);

    if (argv != NULL) {
      /* Execute specified command with arguments */
      if (noexport)
        execve(argv[0], argv, NULL);
      else
        execvp(argv[0], argv);

      LTERM_ERROR("ltermCreateProcess: Error in executing command %s\n",
                  argv[0]);
      return -1;
    }
  }

  /* Parent process; copy child pid */
  ltp->processID = child_pid;

  /* Close child-side pipe end(s) */
  if (stdIN != stdOUT)
    close(stdIN);

  close(stdOUT);

  /* Close writable end of STDERR pipe in parent process */
  if (VALID_FILEDESC(stdERR))
    close(stdERR);

#endif  /* not USE_NSPR_IO */

  LTERM_LOG(ltermCreateProcess,21,("return code = 0\n"));

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ltermDestroyProcess ( struct LtermProcess ltp) [static]

Destroys process pointed by LTP.

Definition at line 1443 of file ltermManager.c.

{

  LTERM_LOG(ltermDestroyProcess,20,("Destroying process\n"));

  if (VALID_PROCESS(ltp->processID)) {
    /* Kill process */
#ifdef USE_NSPR_IO
    /* **NOTE** Possible memory leak here, because processID is not freed? */
    PR_KillProcess(ltp->processID);
#else  /* not USE_NSPR_IO */
    LTERM_LOG(ltermDestroyProcess,21,("Killing process %d\n",ltp->processID));
    kill(ltp->processID, SIGKILL);
#endif /* not USE_NSPR_IO */

    ltp->processID = NULL_PROCESS;
  }

  /* Close process pipes (assumed to be unidirectional) */
  if (VALID_FILEDESC(ltp->processERR))
    CLOSE(ltp->processERR);

  if (VALID_FILEDESC(ltp->processOUT))
    CLOSE(ltp->processOUT);

  if (VALID_FILEDESC(ltp->processIN))
    CLOSE(ltp->processIN);
}

Here is the caller graph for this function:

static int ltermShellInit ( struct lterms lts,
int  all 
) [static]

Sends shell initialization commands, if any (WORKS UNDER GLOBAL_LOCK)

Parameters:
allif true, send all init commands, else send just one command
Returns:
0 on success and -1 on error.

Definition at line 1214 of file ltermManager.c.

{
  int shellInitLen, lowCommand, j;

  if (lts->shellInitCommands <= 0)
    return 0;

  LTERM_LOG(ltermShellInit,20,("sending shell initialization string\n"));

  if (all) {
    /* Send all commands */
    lowCommand = 0;
  } else {
    /* Send single command */
    lowCommand = lts->shellInitCommands - 1;
  }

  for (j=lts->shellInitCommands-1; j>=lowCommand; j--) {
    /* Send shell init command and decrement count */
    lts->shellInitCommands--;

    shellInitLen = strlen(lts->shellInitStr[j]);

    if (shellInitLen > 0) {
      /* Send shell initialization string */
      UNICHAR temLine[PIPEHEADER+MAXCOL];
      int remaining, encoded, byteCount;

      utf8toucs(lts->shellInitStr[j], shellInitLen,
                temLine+PIPEHEADER, MAXCOL,
                1, &remaining, &encoded);
      if (remaining > 0) {
        LTERM_ERROR(
         "ltermShellInit: Shell init command %d string too long\n", j+1);
        return -1;
      }

      temLine[0]         = (UNICHAR) encoded;
      temLine[PHDR_TYPE] = (UNICHAR) LTERM_WRITE_PLAIN_INPUT;
      byteCount = (PIPEHEADER+encoded)*sizeof(UNICHAR);

      if (WRITE(lts->writeBUFFER, temLine, (SIZE_T)byteCount) != byteCount) {
        LTERM_ERROR("ltermShellInit: Error in writing to input pipe buffer\n");
        return -1;
      }
    }
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 47 of file ltermManager.c.