lts->screenSize = lts->nRows * lts->nCols;
int lterm_open(int lterm, char *const argv[], const char* cookie,               const UNICHAR* prompt_regexp, int options, int process_type,               lterm_callback_func_t callback_func, void *callback_data){  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 screen parameters (VT100) */  lts->nRows = 24;  lts->nCols = 80;  lts->screenSize = lts->nRows * lts->nCols;  /* 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, errfd,                   noblock, lts->noTTYEcho, noexport, debugPTY) == -1) {      LTERM_OPEN_ERROR_RETURN(lterm,lts,            "lterm_open: Error - PTY creation failed\n")    }    /* Resize TTY */    if (pty_resize(&ptyStruc, lts->nRows, lts->nCols, 0, 0) != 0) {      LTERM_OPEN_ERROR_RETURN(lterm,lts,            "lterm_open: Error - PTY resizing 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 = POLLIN;  if (lts->ptyMode) {#ifndef USE_NSPR_IO    lto->pollFD[POLL_STDOUT].fd = lts->pty.ptyFD;    lto->pollFD[POLL_STDOUT].POLL_EVENTS = POLLIN;    if (VALID_FILEDESC(lts->pty.errpipeFD)) {      lto->pollFD[POLL_STDERR].fd = lts->pty.errpipeFD;      lto->pollFD[POLL_STDERR].POLL_EVENTS = POLLIN;      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 = POLLIN;    if (VALID_FILEDESC(ltp->processERR)) {      lto->pollFD[POLL_STDERR].fd = ltp->processERR;      lto->pollFD[POLL_STDERR].POLL_EVENTS = POLLIN;      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=%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 string */  if (lts->processType == LTERM_UNKNOWN_PROCESS) {    lts->shellInitStr[0] = '\0';  } else {    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";    }    if (strlen(shellInitFormat)+strlen(lts->cookie) <= MAXSHELLINITSTR+1) {      sprintf(lts->shellInitStr, shellInitFormat, lts->cookie);    } else {      LTERM_WARNING("lterm_open: Warning - shell initialization string too long\n");      lts->shellInitStr[0] = '\0';    }  }  LTERM_LOG(lterm_open,11,("shellInitStr='%s'\n",lts->shellInitStr));  /* Shell initialization commands have not been sent yet */  lts->shellInitFlag = 0;  /* 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;}