1 /* source: xioclose.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Published under the GNU General Public License V.2, see file COPYING */
4 
5 /* this is the source of the extended close function */
6 
7 
8 #include "xiosysincludes.h"
9 #include "xioopen.h"
10 #include "xiolockfile.h"
11 
12 #include "xio-termios.h"
13 
14 
15 /* close the xio fd; must be valid and "simple" (not dual) */
16 int xioclose1(struct single *pipe) {
17 
18    if (pipe->tag == XIO_TAG_INVALID) {
19       Notice("xioclose1(): invalid file descriptor");
20       errno = EINVAL;
21       return -1;
22    }
23 
24 #if WITH_READLINE
25    if ((pipe->dtype & XIODATA_MASK) == XIODATA_READLINE) {
26       Write_history(pipe->para.readline.history_file);
27       /*xiotermios_setflag(pipe->fd, 3, ECHO|ICANON);*/	/* error when pty closed */
28    }
29 #endif /* WITH_READLINE */
30 #if WITH_OPENSSL
31    if ((pipe->dtype & XIODATA_MASK) == XIODATA_OPENSSL) {
32       if (pipe->para.openssl.ssl) {
33 	 /* e.g. on TCP connection refused, we do not yet have this set */
34 	 sycSSL_shutdown(pipe->para.openssl.ssl);
35 	 sycSSL_free(pipe->para.openssl.ssl);
36 	 pipe->para.openssl.ssl = NULL;
37       }
38       Close(pipe->fd);  pipe->fd = -1;
39       if (pipe->para.openssl.ctx) {
40 	 sycSSL_CTX_free(pipe->para.openssl.ctx);
41 	 pipe->para.openssl.ctx = NULL;
42       }
43    } else
44 #endif /* WITH_OPENSSL */
45 #if WITH_TERMIOS
46    if (pipe->ttyvalid) {
47       if (Tcsetattr(pipe->fd, 0, &pipe->savetty) < 0) {
48 	 Warn2("cannot restore terminal settings on fd %d: %s",
49 	       pipe->fd, strerror(errno));
50       }
51    }
52 #endif /* WITH_TERMIOS */
53    if (pipe->fd >= 0) {
54       switch (pipe->howtoend) {
55       case END_KILL: case END_SHUTDOWN_KILL: case END_CLOSE_KILL:
56 	 if (pipe->para.exec.pid > 0) {
57 	    pid_t pid;
58 
59 	    /* first unregister child pid, so our sigchld handler will not throw an error */
60 	    pid = pipe->para.exec.pid;
61 	    pipe->para.exec.pid = 0;
62 	    if (Kill(pid, SIGTERM) < 0) {
63 	       Msg2(errno==ESRCH?E_INFO:E_WARN, "kill(%d, SIGTERM): %s",
64 		    pid, strerror(errno));
65 	    }
66 	 }
67       default:
68 	 break;
69       }
70       switch (pipe->howtoend) {
71       case END_CLOSE: case END_CLOSE_KILL:
72 	 if (Close(pipe->fd) < 0) {
73 	 Info2("close(%d): %s", pipe->fd, strerror(errno)); } break;
74 #if _WITH_SOCKET
75       case END_SHUTDOWN: case END_SHUTDOWN_KILL:
76 	 if (Shutdown(pipe->fd, 2) < 0) {
77 	     Info3("shutdown(%d, %d): %s", pipe->fd, 2, strerror(errno)); }
78          break;
79 #endif /* _WITH_SOCKET */
80       case END_NONE: default: break;
81       }
82    }
83 
84    /* unlock */
85    if (pipe->havelock) {
86       xiounlock(pipe->lock.lockfile);
87       pipe->havelock = false;
88    }
89    if (pipe->opt_unlink_close && pipe->unlink_close) {
90       if (Unlink(pipe->unlink_close) < 0) {
91 	 Info2("unlink(\"%s\"): %s", pipe->unlink_close, strerror(errno));
92       }
93       free(pipe->unlink_close);
94    }
95 
96    pipe->tag = XIO_TAG_INVALID;
97    return 0;	/*! */
98 }
99 
100 
101 /* close the xio fd */
102 int xioclose(xiofile_t *file) {
103    int result;
104 
105    if (file->tag == XIO_TAG_INVALID) {
106       Error("xioclose(): invalid file descriptor");
107       errno = EINVAL;
108       return -1;
109    }
110 
111    if (file->tag == XIO_TAG_DUAL) {
112       result  = xioclose1(file->dual.stream[0]);
113       result |= xioclose1(file->dual.stream[1]);
114       file->tag = XIO_TAG_INVALID;
115    } else {
116       result = xioclose1(&file->stream);
117    }
118    return result;
119 }
120 
121