/* source: xioclose.c */ /* Copyright Gerhard Rieger and contributors (see file CHANGES) */ /* 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" #include "xio-interface.h" #include "xio-posixmq.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; } if (pipe->tag == XIO_TAG_CLOSED) { return 0; } pipe->tag |= XIO_TAG_CLOSED; if (pipe->dtype & XIOREAD_RECV_ONESHOT) { if (pipe->triggerfd >= 0) { char r[1]; Info("consuming packet to prevent loop in parent"); Read(pipe->fd, r, sizeof(r)); Close(pipe->triggerfd); pipe->triggerfd = -1; } } #if WITH_READLINE if ((pipe->dtype & XIODATA_MASK) == XIODATA_READLINE) { Write_history(pipe->para.readline.history_file); /*xiotermios_setflag(pipe->fd, 3, ECHO|ICANON);*/ /* error when pty closed */ } #endif /* WITH_READLINE */ #if WITH_OPENSSL if ((pipe->dtype & XIODATA_MASK) == XIODATA_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->fd); pipe->fd = -1; if (pipe->para.openssl.ctx) { sycSSL_CTX_free(pipe->para.openssl.ctx); pipe->para.openssl.ctx = NULL; } } else #endif /* WITH_OPENSSL */ #if WITH_TERMIOS if (pipe->ttyvalid) { if (Tcsetattr(pipe->fd, TCSANOW, &pipe->savetty) < 0) { Warn2("cannot restore terminal settings on fd %d: %s", pipe->fd, strerror(errno)); } } #endif /* WITH_TERMIOS */ #if WITH_POSIXMQ if ((pipe->dtype & XIODATA_MASK) == XIODATA_POSIXMQ) { xioclose_posixmq(pipe); } #endif /* WITH_POSIXMQ */ if (pipe->fd >= 0) { switch (pipe->howtoend) { case END_KILL: case END_SHUTDOWN_KILL: case END_CLOSE_KILL: if (pipe->para.exec.pid > 0) { pid_t pid; /* first unregister child pid, so our sigchld handler will not throw an error */ pid = pipe->para.exec.pid; pipe->para.exec.pid = 0; if (Kill(pid, SIGTERM) < 0) { Msg2(errno==ESRCH?E_INFO:E_WARN, "kill(%d, SIGTERM): %s", pid, strerror(errno)); } } default: break; } switch (pipe->howtoend) { case END_CLOSE: case END_CLOSE_KILL: if (Close(pipe->fd) < 0) { Info2("close(%d): %s", pipe->fd, strerror(errno)); } break; #if _WITH_SOCKET case END_SHUTDOWN: case END_SHUTDOWN_KILL: if (Shutdown(pipe->fd, 2) < 0) { Info3("shutdown(%d, %d): %s", pipe->fd, 2, strerror(errno)); } break; #endif /* _WITH_SOCKET */ #if WITH_INTERFACE case END_INTERFACE: { if (pipe->para.interface.name[0] != '\0') { _xiointerface_set_iff(pipe->fd, pipe->para.interface.name, pipe->para.interface.save_iff); } if (Close(pipe->fd) < 0) { Info2("close(%d): %s", pipe->fd, strerror(errno)); } break; } break; #endif /* WITH_INTERFACE */ case END_NONE: default: break; } } /* 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) { Warn2("unlink(\"%s\"): %s", pipe->unlink_close, strerror(errno)); } free(pipe->unlink_close); } return 0; /*! */ } /* close the xio fd */ int xioclose(xiofile_t *file) { int result; if (file->tag == XIO_TAG_INVALID) { Error("xioclose(): invalid file descriptor"); errno = EINVAL; return -1; } if (file->tag == XIO_TAG_CLOSED) { return 0; } if (file->tag == XIO_TAG_DUAL) { file->tag |= XIO_TAG_CLOSED; result = xioclose1(file->dual.stream[0]); result |= xioclose1(file->dual.stream[1]); } else { result = xioclose1(&file->stream); } return result; }