File: xioshutdown.c

package info (click to toggle)
socat 1.4.2.0-1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 2,144 kB
  • ctags: 3,624
  • sloc: ansic: 18,730; sh: 3,319; makefile: 153
file content (135 lines) | stat: -rw-r--r-- 3,899 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* $Id: xioshutdown.c,v 1.18 2005/03/13 12:19:59 gerhard Exp $ */
/* Copyright Gerhard Rieger 2001-2005 */
/* Published under the GNU General Public License V.2, see file COPYING */

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


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

static pid_t socat_kill_pid;	/* here we pass the pid to be killed in sighandler */

static void signal_kill_pid(int dummy) {
   Notice("SIGALRM while waiting for w/o child process to die, killing it now");
   Kill(socat_kill_pid, SIGTERM);
}

int xioshutdown(xiofile_t *sock, int how) {
   int result = 0;

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

   if (sock->tag == XIO_TAG_DUAL) {
      if ((how+1)&1) {
	 result = xioshutdown(sock->dual.stream[0], 0);
      }
      if ((how+1)&2) {
	 result |= xioshutdown(sock->dual.stream[1], 1);
      }

#if WITH_OPENSSL
   } else if (sock->stream.dtype == DATA_OPENSSL) {
      sycSSL_shutdown (sock->stream.para.openssl.ssl);
      /*! */
#endif /* WITH_OPENSSL */

   } else if (sock->stream.dtype == DATA_PIPE) {
      if ((how+1)&1) {
	 if (Close(sock->stream.fd) < 0) {
	    Warn2("close(%d): %s",
		  sock->stream.fd, strerror(errno));
	 }
      }
      if ((how+1)&2) {
	 if (Close(sock->stream.para.bipipe.fdout) < 0) {
	    Warn2("close(%d): %s",
		  sock->stream.para.bipipe.fdout, strerror(errno));
	 } 
      }
      
   } else if (sock->stream.dtype == DATA_2PIPE) {
      if ((how+1)&1) {
	 if (Close(sock->stream.fd) < 0) {
	    Warn2("close(%d): %s",
		  sock->stream.fd, strerror(errno));
	 }
      }
      if ((how+1)&2) {
	 if (Close(sock->stream.para.exec.fdout) < 0) {
	    Warn2("close(%d): %s",
		  sock->stream.para.exec.fdout, strerror(errno));
	 } 
      }
      
#if WITH_SOCKET
   } else if (sock->stream.howtoend == END_SHUTDOWN) {
      if ((result = Shutdown(sock->stream.fd, how)) < 0) {
	 Warn3("shutdown(%d, %d): %s",
	       sock->stream.fd, how, strerror(errno));
      }
   } else if (sock->stream.howtoend == END_SHUTDOWN_KILL) {
      if ((result = Shutdown(sock->stream.fd, how)) < 0) {
	 Warn3("shutdown(%d, %d): %s",
	       sock->stream.fd, how, strerror(errno));
      }
      if ((sock->stream.flags&XIO_ACCMODE) == XIO_WRONLY) {
	 /* the child process might want to flush some data before terminating
	    */
	 int status = 0;

	 /* we wait for the child process to die, but to prevent timeout
	    we raise an alarm after some time.
	    NOTE: the alarm does not terminate waitpid() on Linux/glibc (BUG?),
	    therefore we have to do the kill in the signal handler */
	 Signal(SIGALRM, signal_kill_pid);
	 socat_kill_pid = sock->stream.para.exec.pid;
#if HAVE_SETITIMER
	 /*! with next feature release, we get usec resolution and an option */
#else
	 Alarm(1 /*! sock->stream.para.exec.waitdie */);
#endif /* !HAVE_SETITIMER */
	 if (Waitpid(sock->stream.para.exec.pid, &status, 0) < 0) {
	    Warn3("waitpid("F_pid", %p, 0): %s",
		  sock->stream.para.exec.pid, &status, strerror(errno));
	 }
	 Alarm(0);
      }
   } else if (sock->stream.dtype == DATA_RECV) {
      if (how >= 1) {
	 if (Close(sock->stream.fd) < 0) {
	    Warn2("close(%d): %s",
		  sock->stream.fd, strerror(errno));
	 }
	 sock->stream.eof = 1;
	 sock->stream.fd = -1;
      }
#endif /* WITH_SOCKET */
#if 0
   } else {
      Error1("xioshutdown(): bad data type specification %d", sock->stream.dtype);
      return -1;
#endif

   }
#if 0
   else if (sock->stream.howtoend == END_CLOSE &&
	      sock->stream.dtype == DATA_STREAM) {
      return result;
   }
#if WITH_TERMIOS
   if (sock->stream.ttyvalid) {
      if (Tcsetattr(sock->stream.fd, 0, &sock->stream.savetty) < 0) {
	 Warn2("cannot restore terminal settings on fd %d: %s",
	       sock->stream.fd, strerror(errno));
      }
   }
#endif /* WITH_TERMIOS */
#endif

   return result;
}