/* analyse a file system entry, referred by file name */ int filan_file(const char *filename, FILE *outfile) { int fd = -1; int result; #if HAVE_STAT64 struct stat64 buf = {0}; #else struct stat buf = {0}; #endif /* !HAVE_STAT64 */ if (filan_followsymlinks) { #if HAVE_STAT64 result = Stat64(filename, &buf); #else result = Stat(filename, &buf); #endif /* !HAVE_STAT64 */ if (result < 0) { Warn3("stat(\"%s\", %p): %s", filename, &buf, strerror(errno)); } } else { #if HAVE_STAT64 result = Lstat64(filename, &buf); #else result = Lstat(filename, &buf); #endif /* !HAVE_STAT64 */ if (result < 0) { Warn3("lstat(\"%s\", %p): %s", filename, &buf, strerror(errno)); } } switch (buf.st_mode&S_IFMT) { #ifdef S_IFSOCK case S_IFSOCK: /* probably, it's useless to make a socket and describe it */ break; #endif /* S_IFSOCK */ default: if ((fd = Open(filename, O_RDONLY|O_NOCTTY|O_NONBLOCK #ifdef O_LARGEFILE |O_LARGEFILE #endif , 0700)) < 0) { Warn2("open(\"%s\", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE, 0700): %s", filename, strerror(errno)); } } result = filan_stat(&buf, fd, -1, outfile); fputc('\n', outfile); return result; }
/* register the sub process pid for passing of signals of type signum. Only for SIGHUP, SIGINT, and SIGQUIT! returns 0 on success or <0 if an error occurred */ int xio_opt_signal(pid_t pid, int signum) { struct socat_sig_desc *sigdesc; if ((sigdesc = socat_get_sig_desc(signum)) == NULL) { Error("sub process registered for unsupported signal"); return -1; } if (sigdesc->sig_use >= SOCAT_MAXPIDS) { Error1("too many sub processes registered for signal %d", signum); return -1; } if (sigdesc->sig_use == 0) { /* the special signal handler has not been registered yet - do it now */ #if HAVE_SIGACTION struct sigaction act; memset(&act, 0, sizeof(struct sigaction)); act.sa_flags = 0/*|SA_RESTART*/; act.sa_handler = socatsignalpass; sigfillset(&act.sa_mask); if (Sigaction(signum, &act, NULL) < 0) { /*! man does not say that errno is defined */ Warn3("sigaction(%d, %p, NULL): %s", signum, &act, strerror(errno)); } #else Signal(signum, socatsignalpass); #endif /* !HAVE_SIGACTION */ } sigdesc->sig_pids[sigdesc->sig_use++] = pid; return 0; }
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((xiofile_t *)sock->dual.stream[0], 0); } if ((how+1)&2) { result |= xioshutdown((xiofile_t *)sock->dual.stream[1], 1); } return result; } switch (sock->stream.howtoshut) { char writenull; case XIOSHUT_NONE: return 0; case XIOSHUT_CLOSE: if (Close(sock->stream.fd) < 0) { Info2("close(%d): %s", sock->stream.fd, strerror(errno)); } return 0; case XIOSHUT_DOWN: if ((result = Shutdown(sock->stream.fd, how)) < 0) { Info3("shutdown(%d, %d): %s", sock->stream.fd, how, strerror(errno)); } return 0; #if _WITH_SOCKET case XIOSHUT_NULL: /* send an empty packet; only useful on datagram sockets? */ xiowrite(sock, &writenull, 0); return 0; #endif /* _WITH_SOCKET */ default: ; } if (false) { ; #if WITH_OPENSSL } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_OPENSSL) { sycSSL_shutdown (sock->stream.para.openssl.ssl); /*! what about half/full close? */ #endif /* WITH_OPENSSL */ } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_PIPE) { if ((how+1)&1) { if (Close(sock->stream.fd) < 0) { Info2("close(%d): %s", sock->stream.fd, strerror(errno)); } } if ((how+1)&2) { if (Close(sock->stream.para.bipipe.fdout) < 0) { Info2("close(%d): %s", sock->stream.para.bipipe.fdout, strerror(errno)); } } } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_2PIPE) { if ((how+1)&1) { if (Close(sock->stream.fd) < 0) { Info2("close(%d): %s", sock->stream.fd, strerror(errno)); } } if ((how+1)&2) { if (Close(sock->stream.para.exec.fdout) < 0) { Info2("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) { Info3("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) { Info3("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 */ { struct sigaction act; sigfillset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = signal_kill_pid; Sigaction(SIGALRM, &act, NULL); } 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 & XIODATA_MASK) == (XIODATA_RECVFROM & XIODATA_MASK)) { if (how >= 1) { if (Close(sock->stream.fd) < 0) { Info2("close(%d): %s", sock->stream.fd, strerror(errno)); } sock->stream.eof = 2; 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 &&