nexmon – Rev 1

Subversion Repositories:
Rev:
/* source: xioclose.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Published under the GNU General Public License V.2, see file COPYING */

/* this is the source of the extended close function */


#include "xiosysincludes.h"
#include "xioopen.h"
#include "xiolockfile.h"

#include "xio-termios.h"


/* close the xio fd; must be valid and "simple" (not dual) */
int xioclose1(struct single *pipe) {

   if (pipe->tag == XIO_TAG_INVALID) {
      Notice("xioclose1(): invalid file descriptor");
      errno = EINVAL;
      return -1;
   }

   switch (pipe->howtoclose) {

#if WITH_READLINE
   case XIOCLOSE_READLINE:
      Write_history(pipe->para.readline.history_file);
      /*xiotermios_setflag(pipe->fd, 3, ECHO|ICANON);*/ /* error when pty closed */
      break;
#endif /* WITH_READLINE */

#if WITH_OPENSSL
   case XIOCLOSE_OPENSSL:
      if (pipe->para.openssl.ssl) {
         /* e.g. on TCP connection refused, we do not yet have this set */
         sycSSL_shutdown(pipe->para.openssl.ssl);
         sycSSL_free(pipe->para.openssl.ssl);
         pipe->para.openssl.ssl = NULL;
      }
      Close(pipe->rfd);  pipe->rfd = -1;
      Close(pipe->wfd);  pipe->wfd = -1;
      if (pipe->para.openssl.ctx) {
         sycSSL_CTX_free(pipe->para.openssl.ctx);
         pipe->para.openssl.ctx = NULL;
      }
      break;
#endif /* WITH_OPENSSL */

   case XIOCLOSE_SIGTERM:
      if (pipe->child.pid > 0) {
         if (Kill(pipe->child.pid, SIGTERM) < 0) {
            Msg2(errno==ESRCH?E_INFO:E_WARN, "kill(%d, SIGTERM): %s",
                 pipe->child.pid, strerror(errno));
         }
      }
      break;
   case XIOCLOSE_CLOSE_SIGTERM:
      if (pipe->child.pid > 0) {
            if (Kill(pipe->child.pid, SIGTERM) < 0) {
               Msg2(errno==ESRCH?E_INFO:E_WARN, "kill(%d, SIGTERM): %s",
                    pipe->child.pid, strerror(errno));
            }
      }
      /*PASSTHROUGH*/
   case XIOCLOSE_CLOSE:
      if (XIOWITHRD(pipe->flags) && pipe->rfd >= 0) {
         if (Close(pipe->rfd) < 0) {
            Info2("close(%d): %s", pipe->rfd, strerror(errno));
         }
      }
      if (XIOWITHWR(pipe->flags) && pipe->wfd >= 0) {
         if (Close(pipe->wfd) < 0) {
            Info2("close(%d): %s", pipe->wfd, strerror(errno));
         }
      }
      break;

   case XIOCLOSE_SLEEP_SIGTERM:
      Usleep(250000);
      if (pipe->child.pid > 0) {
            if (Kill(pipe->child.pid, SIGTERM) < 0) {
               Msg2(errno==ESRCH?E_INFO:E_WARN, "kill(%d, SIGTERM): %s",
                    pipe->child.pid, strerror(errno));
            }
      }
      break;

   case XIOCLOSE_NONE:
      break;

   case XIOCLOSE_UNSPEC:
      Warn1("xioclose(): no close action specified on 0x%x", pipe);
      break;

   default:
      Error2("xioclose(): bad close action 0x%x on 0x%x", pipe->howtoclose, pipe);
      break;
   }

#if WITH_TERMIOS
   if (pipe->ttyvalid) {
      if (Tcsetattr(pipe->rfd, 0, &pipe->savetty) < 0) {
         Warn2("cannot restore terminal settings on fd %d: %s",
               pipe->rfd, strerror(errno));
      }
   }
#endif /* WITH_TERMIOS */

   /* unlock */
   if (pipe->havelock) {
      xiounlock(pipe->lock.lockfile);
      pipe->havelock = false;
   }      
   if (pipe->opt_unlink_close && pipe->unlink_close) {
      if (Unlink(pipe->unlink_close) < 0) {
         Info2("unlink(\"%s\"): %s", pipe->unlink_close, strerror(errno));
      }
      free(pipe->unlink_close);
   }

   pipe->tag = XIO_TAG_INVALID;
   return 0;    /*! */
}


/* close the xio fd */
int xioclose(xiofile_t *file) {
   xiofile_t *xfd = file;
   int result;

   if (file->tag == XIO_TAG_INVALID) {
      Error("xioclose(): invalid file descriptor");
      errno = EINVAL;
      return -1;
   }

   if (file->tag == XIO_TAG_DUAL) {
      result  = xioclose1(file->dual.stream[0]);
      result |= xioclose1(file->dual.stream[1]);
      file->tag = XIO_TAG_INVALID;
   } else {
      result = xioclose1(&file->stream);
   }
   if (xfd->tag != XIO_TAG_INVALID && xfd->stream.subthread != 0) {
      Pthread_join(xfd->stream.subthread, NULL);
   }
   return result;
}