예제 #1
0
static RList *xnu_desc_list (int pid) {
#if TARGET_OS_IPHONE
	return NULL;
#else
#define xwr2rwx(x) ((x&1)<<2) | (x&2) | ((x&4)>>2)
	RDebugDesc *desc;
	RList *ret = r_list_new();
	struct vnode_fdinfowithpath vi;
	int i, nb, type = 0;
	int maxfd = getMaxFiles();

	for (i=0 ; i<maxfd; i++) {
		nb = proc_pidfdinfo (pid, i, PROC_PIDFDVNODEPATHINFO, &vi, sizeof (vi));
		if (nb<1) {
			continue;
		}
		if (nb < sizeof (vi)) {
			perror ("too few bytes");
			break;
		}
		//printf ("FD %d RWX %x ", i, vi.pfi.fi_openflags);
		//printf ("PATH %s\n", vi.pvip.vip_path);
		desc = r_debug_desc_new (i,
				vi.pvip.vip_path,
				xwr2rwx(vi.pfi.fi_openflags),
				type, 0);
		r_list_append (ret, desc);
	}
	return ret;
#endif
}
void genSocketDescriptor(int pid, int descriptor, QueryData& results) {
  struct socket_fdinfo si;
  if (proc_pidfdinfo(pid,
                     descriptor,
                     PROC_PIDFDSOCKETINFO,
                     &si,
                     PROC_PIDFDSOCKETINFO_SIZE) <= 0) {
    return;
  }

  if (si.psi.soi_family == AF_INET || si.psi.soi_family == AF_INET6) {
    Row r;

    r["pid"] = INTEGER(pid);
    r["fd"] = BIGINT(descriptor);
    r["socket"] = BIGINT(si.psi.soi_so);
    r["path"] = "";

    // Darwin/OSX SOCKINFO_TCP is not IPPROTO_TCP
    if (si.psi.soi_kind == SOCKINFO_TCP) {
      r["protocol"] = INTEGER(6);
    } else {
      r["protocol"] = INTEGER(17);
    }

    // Darwin/OSX AF_INET6 == 30
    if (si.psi.soi_family == AF_INET) {
      r["family"] = INTEGER(2);
    } else {
      r["family"] = INTEGER(10);
    }

    parseNetworkSocket(si, r);
    results.push_back(r);
  } else if (si.psi.soi_family == AF_UNIX) {
    Row r;

    r["pid"] = INTEGER(pid);
    r["socket"] = INTEGER(descriptor);
    r["family"] = "0";
    r["protocol"] = "0";
    r["local_address"] = "";
    r["local_port"] = "0";
    r["remote_address"] = "";
    r["remote_port"] = "0";
    if ((char*)si.psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path != nullptr) {
      r["path"] = si.psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path;
    } else {
      r["path"] = "";
    }
    results.push_back(r);
  } else if (si.psi.soi_family == AF_APPLETALK) {
    // AF_APPLETALK = 17
  } else if (si.psi.soi_family == AF_NATM) {
    // AF_NATM = 32
  } else {
    // Unsupported socket type.
  }
}
void genFileDescriptor(int pid, int descriptor, QueryData& results) {
  struct vnode_fdinfowithpath vi;
  if (proc_pidfdinfo(pid,
                     descriptor,
                     PROC_PIDFDVNODEPATHINFO,
                     &vi,
                     PROC_PIDFDVNODEPATHINFO_SIZE) <= 0) {
    return;
  }

  Row r;
  r["pid"] = INTEGER(pid);
  r["fd"] = INTEGER(descriptor);
  r["path"] = std::string(vi.pvip.vip_path);
  results.push_back(r);
}
예제 #4
0
char *common_get_fd_path(int fd) {
  struct stat st;
  if (fstat(fd, &st)) {
    return NULL;
  }

#if defined WIN32
  // Windows
  HANDLE hdl = (HANDLE) _get_osfhandle(fd);
  if (hdl != INVALID_HANDLE_VALUE) {
    DWORD size = GetFinalPathNameByHandle(hdl, NULL, 0, 0);
    if (size) {
      char *path = g_malloc(size);
      DWORD ret = GetFinalPathNameByHandle(hdl, path, size - 1, 0);
      if (ret > 0 && ret <= size) {
        return path;
      }
      g_free(path);
    }
  }
#elif defined HAVE_PROC_PIDFDINFO
  // Mac OS X
  // Ignore kqueues, since they can be opened behind our back for
  // Grand Central Dispatch
  struct kqueue_fdinfo kqi;
  if (proc_pidfdinfo(getpid(), fd, PROC_PIDFDKQUEUEINFO, &kqi, sizeof(kqi))) {
    return NULL;
  }
  char *path = g_malloc(MAXPATHLEN);
  if (!fcntl(fd, F_GETPATH, path)) {
    return path;
  }
  g_free(path);
#else
  // Fallback; works only on Linux
  char *link_path = g_strdup_printf("/proc/%d/fd/%d", getpid(), fd);
  char *path = g_file_read_link(link_path, NULL);
  g_free(link_path);
  if (path) {
    return path;
  }
#endif

  return g_strdup("<unknown>");
}
예제 #5
0
void tt_fs_status_dump_ntv(IN tt_u32_t flag)
{
    pid_t pid;
    int size;
    struct proc_fdinfo *fdinfo;

    pid = getpid();
    size = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
    if (size <= 0) {
        return;
    }

    fdinfo = (struct proc_fdinfo *)malloc(size);
    if (fdinfo == NULL) {
        return;
    }

    size = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdinfo, size);
    if (size > 0) {
        int n, i;

        n = size / PROC_PIDLISTFD_SIZE;
        for (i = 0; i < n; ++i) {
            if (fdinfo[i].proc_fdtype == PROX_FDTYPE_VNODE) {
                struct vnode_fdinfowithpath vi;
                int vs = proc_pidfdinfo(pid,
                                        fdinfo[i].proc_fd,
                                        PROC_PIDFDVNODEPATHINFO,
                                        &vi,
                                        PROC_PIDFDVNODEPATHINFO_SIZE);
                if (vs == PROC_PIDFDVNODEPATHINFO_SIZE) {
                    tt_printf("%s[fd: %d] [%s]\n",
                              TT_COND(flag & TT_FS_STATUS_PREFIX,
                                      "<<FS>> ",
                                      ""),
                              fdinfo[i].proc_fd,
                              vi.pvip.vip_path);
                }
            }
        }
    }

    free(fdinfo);
}
예제 #6
0
int find_fd_for_pid(pid_t pid, int *fd_list, int max_fd)
{
int count = 0;
int bufferSize = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, 0, 0);
struct stat stat_buf;

if (bufferSize < 0) {
    printf("Error :/, cannot proc_pidinfo\n");
    return 0;
}
struct proc_fdinfo *procFDInfo = (struct proc_fdinfo *)malloc(bufferSize);
proc_pidinfo(pid, PROC_PIDLISTFDS, 0, procFDInfo, bufferSize);
int numberOfProcFDs = bufferSize / PROC_PIDLISTFD_SIZE;
int i;

for(i = 0; i < numberOfProcFDs; i++) {
    if(procFDInfo[i].proc_fdtype == PROX_FDTYPE_VNODE) {
        struct vnode_fdinfowithpath vnodeInfo;
        proc_pidfdinfo(pid, procFDInfo[i].proc_fd, PROC_PIDFDVNODEPATHINFO, &vnodeInfo, PROC_PIDFDVNODEPATHINFO_SIZE);
        if (stat(vnodeInfo.pvip.vip_path, &stat_buf) < 0) {
            if (flag_debug)
                perror("sstat");
            continue;
        }
        if (!S_ISREG(stat_buf.st_mode) && !S_ISBLK(stat_buf.st_mode))
            continue;

        if (is_ignored_file(vnodeInfo.pvip.vip_path))
            continue;

        // OK, we've found a potential interesting file.

        fd_list[count++] = procFDInfo[i].proc_fd;
        //~ printf("[debug] %s\n",vnodeInfo.pvip.vip_path);
        if(count == max_fd)
            break;
    }
}
return count;
}
예제 #7
0
/*
 * Return process TCP and UDP connections as a list of tuples.
 * References:
 * - lsof source code: http://goo.gl/SYW79 and http://goo.gl/wNrC0
 * - /usr/include/sys/proc_info.h
 */
static PyObject*
get_process_connections(PyObject* self, PyObject* args)
{
    long pid;
    int pidinfo_result;
    int iterations;
    int i;
    int nb;

    struct proc_fdinfo *fds_pointer;
    struct proc_fdinfo *fdp_pointer;
    struct socket_fdinfo si;

    PyObject *retList = PyList_New(0);
    PyObject *tuple = NULL;
    PyObject *laddr = NULL;
    PyObject *raddr = NULL;
    PyObject *af_filter = NULL;
    PyObject *type_filter = NULL;

    if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter)) {
        return NULL;
    }

    if (!PySequence_Check(af_filter) || !PySequence_Check(type_filter)) {
        PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence");
        return NULL;
    }

    if (pid == 0) {
        return retList;
    }

    pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
    if (pidinfo_result <= 0) {
        goto error;
    }

    fds_pointer = malloc(pidinfo_result);
    pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer,
                                  pidinfo_result);
    free(fds_pointer);

    if (pidinfo_result <= 0) {
        goto error;
    }

    iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE);

    for (i = 0; i < iterations; i++) {
        errno = 0;
        fdp_pointer = &fds_pointer[i];

        //
        if (fdp_pointer->proc_fdtype == PROX_FDTYPE_SOCKET)
        {
            nb = proc_pidfdinfo(pid, fdp_pointer->proc_fd, PROC_PIDFDSOCKETINFO,
                                &si, sizeof(si));

            // --- errors checking
            if (nb <= 0) {
                if (errno == EBADF) {
                    // let's assume socket has been closed
                    continue;
                }
                if (errno != 0) {
                    return PyErr_SetFromErrno(PyExc_OSError);
                }
                else {
                    return PyErr_Format(PyExc_RuntimeError,
                                "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed");
                }
            }
            if (nb < sizeof(si)) {
                return PyErr_Format(PyExc_RuntimeError,
                 "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed (buffer mismatch)");
            }
            // --- /errors checking

            //
            int fd, family, type, lport, rport;
            char lip[200], rip[200];
            char *state;
            int inseq;
            PyObject* _family;
            PyObject* _type;

            fd = (int)fdp_pointer->proc_fd;
            family = si.psi.soi_family;
            type = si.psi.soi_kind;

            if (type == 2) {
                type = SOCK_STREAM;
            }

            else if (type == 1) {
                type = SOCK_DGRAM;
            }

            else {
                continue;
            }

            // apply filters
            _family = PyLong_FromLong((long)family);
            inseq = PySequence_Contains(af_filter, _family);
            Py_DECREF(_family);
            if (inseq == 0) {
                continue;
            }

            _type = PyLong_FromLong((long)type);
            inseq = PySequence_Contains(type_filter, _type);
            Py_DECREF(_type);
            if (inseq == 0) {
                continue;
            }

            if (errno != 0) {
                return PyErr_SetFromErrno(PyExc_OSError);
            }

            if (family == AF_INET) {
                inet_ntop(AF_INET,
                          &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_46.i46a_addr4,
                          lip,
                          sizeof(lip));
                inet_ntop(AF_INET,
                          &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr.ina_46.i46a_addr4,
                          rip,
                          sizeof(lip));
            }

            else {
                inet_ntop(AF_INET6,
                          &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_6,
                          lip, sizeof(lip));
                inet_ntop(AF_INET6,
                          &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr.ina_6,
                          lip, sizeof(rip));
            }

            // check for inet_ntop failures
            if (errno != 0) {
                return PyErr_SetFromErrno(PyExc_OSError);
            }

            lport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport);
            rport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_fport);
            if (type == SOCK_STREAM) {
                state = get_connection_status((int)si.psi.soi_proto.pri_tcp.tcpsi_state);
            }

            else {
                state = "";
            }

            laddr = Py_BuildValue("(si)", lip, lport);
            if (rport != 0) {
                raddr = Py_BuildValue("(si)", rip, rport);
            }

            else {
                raddr = PyTuple_New(0);
            }

            // --- construct python list
            tuple = Py_BuildValue("(iiiNNs)", fd, family, type, laddr, raddr,
                                              state);
            PyList_Append(retList, tuple);
            Py_DECREF(tuple);
            // --- /construct python list
        }
    }

    return retList;

error:
    if (errno != 0) {
        return PyErr_SetFromErrno(PyExc_OSError);
    }

    else if (! pid_exists(pid) ) {
        return NoSuchProcess();
    }

    else {
        return PyErr_Format(PyExc_RuntimeError,
                            "proc_pidinfo(PROC_PIDLISTFDS) failed");
    }
}
예제 #8
0
/*
 * Return process open files as a Python tuple.
 * References:
 * - lsof source code: http://goo.gl/SYW79 and http://goo.gl/m78fd
 * - /usr/include/sys/proc_info.h
 */
static PyObject*
get_process_open_files(PyObject* self, PyObject* args)
{
    long pid;
    int pidinfo_result;
    int iterations;
    int i;
    int nb;

    struct proc_fdinfo *fds_pointer;
    struct proc_fdinfo *fdp_pointer;
    struct vnode_fdinfowithpath vi;

    PyObject *retList = PyList_New(0);
    PyObject *tuple = NULL;

    if (! PyArg_ParseTuple(args, "l", &pid)) {
        return NULL;
    }

    pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
    if (pidinfo_result <= 0) {
        goto error;
    }

    fds_pointer = malloc(pidinfo_result);
    pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer,
                                  pidinfo_result);
    free(fds_pointer);

    if (pidinfo_result <= 0) {
        goto error;
    }

    iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE);

    for (i = 0; i < iterations; i++) {
        fdp_pointer = &fds_pointer[i];

        //
        if (fdp_pointer->proc_fdtype == PROX_FDTYPE_VNODE)
        {
            nb = proc_pidfdinfo(pid,
                                fdp_pointer->proc_fd,
                                PROC_PIDFDVNODEPATHINFO,
                                &vi,
                                sizeof(vi));

            // --- errors checking
            if (nb <= 0) {
                if ((errno == ENOENT) || (errno == EBADF)) {
                    // no such file or directory or bad file descriptor;
                    // let's assume the file has been closed or removed
                    continue;
                }
                if (errno != 0) {
                    return PyErr_SetFromErrno(PyExc_OSError);
                }
                else
                    return PyErr_Format(PyExc_RuntimeError,
                                "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed");
            }
            if (nb < sizeof(vi)) {
                return PyErr_Format(PyExc_RuntimeError,
                 "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed (buffer mismatch)");
            }
            // --- /errors checking

            // --- construct python list
            tuple = Py_BuildValue("(si)", vi.pvip.vip_path,
                                          (int)fdp_pointer->proc_fd);
            PyList_Append(retList, tuple);
            Py_DECREF(tuple);
            // --- /construct python list
        }
    }

    return retList;

error:
    if (errno != 0) {
        return PyErr_SetFromErrno(PyExc_OSError);
    }

    else if (! pid_exists(pid) ) {
        return NoSuchProcess();
    }

    else {
        return PyErr_Format(PyExc_RuntimeError,
                            "proc_pidinfo(PROC_PIDLISTFDS) failed");
    }
}
예제 #9
0
/*
 * check_process_fds
 *   check [process] open file descriptors
 *
 *   in  : pid
 *   out : -1 if error
 *          0 if no match
 *          1 if match
 */
static int
check_process_fds(fdOpenInfoRef info, int pid)
{
	int	buf_used;
	int	i;
	int	status;

	// get list of open file descriptors
	buf_used = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
	if (buf_used <= 0) {
		return -1;
	}

	while (1) {
		if (buf_used > info->fds_size) {
			// if we need to allocate [more] space
			while (buf_used > info->fds_size) {
				info->fds_size += (sizeof(struct proc_fdinfo) * 32);
			}

			if (info->fds == NULL) {
				info->fds = malloc(info->fds_size);
			} else {
				info->fds = reallocf(info->fds, info->fds_size);
			}
			if (info->fds == NULL) {
				return -1;
			}
		}

		buf_used = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, info->fds, (int)info->fds_size);
		if (buf_used <= 0) {
			return -1;
		}

		if ((buf_used + sizeof(struct proc_fdinfo)) >= info->fds_size) {
			// if not enough room in the buffer for an extra fd
			buf_used = (int)(info->fds_size + sizeof(struct proc_fdinfo));
			continue;
		}

		info->fds_count = (int)(buf_used / sizeof(struct proc_fdinfo));
		break;
	}

	// iterate through each file descriptor
	for (i = 0; i < info->fds_count; i++) {
		struct proc_fdinfo	*fdp;

		fdp = &info->fds[i];
		switch (fdp->proc_fdtype) {
			case PROX_FDTYPE_VNODE : {
				int			buf_used;
				struct vnode_fdinfo	vi;

				buf_used = proc_pidfdinfo(pid, fdp->proc_fd, PROC_PIDFDVNODEINFO, &vi, sizeof(vi));
				if (buf_used <= 0) {
					if (errno == ENOENT) {
						/*
						 * The file descriptor's vnode may have been revoked. This is a
						 * bit of a hack, since an ENOENT error might not always mean the
						 * descriptor's vnode has been revoked. As the libproc API
						 * matures, this code may need to be revisited.
						 */
						continue;
					}
					return -1;
				} else if (buf_used < sizeof(vi)) {
					// if we didn't get enough information
					return -1;
				}

				if ((info->flags & PROC_LISTPIDSPATH_EXCLUDE_EVTONLY) &&
				    (vi.pfi.fi_openflags & O_EVTONLY)) {
					// if this file should be excluded
					continue;
				}

				status = check_file(info, &vi.pvi.vi_stat);
				if (status != 0) {
					// if error or match
					return status;
				}
				break;
			}
			default :
				break;
		}
	}

	return 0;
}
예제 #10
0
파일: cv.c 프로젝트: zhangshiguang/cv
signed char get_fdinfo(pid_t pid, int fdnum, fdinfo_t *fd_info)
{
struct stat stat_buf;
#ifndef __APPLE__
char fdpath[MAXPATHLEN + 1];
char line[LINE_LEN];
FILE *fp;
#endif
struct timezone tz;

fd_info->num = fdnum;

#ifdef __APPLE__
struct vnode_fdinfowithpath vnodeInfo;
if (proc_pidfdinfo(pid, fdnum, PROC_PIDFDVNODEPATHINFO, &vnodeInfo, PROC_PIDFDVNODEPATHINFO_SIZE) <= 0)
    return 0;
strncpy(fd_info->name, vnodeInfo.pvip.vip_path, MAXPATHLEN);
#else
ssize_t len;
snprintf(fdpath, MAXPATHLEN, "%s/%d/fd/%d", PROC_PATH, pid, fdnum);

len=readlink(fdpath, fd_info->name, MAXPATHLEN);
if(len != -1)
    fd_info->name[len] = 0;
else {
    //~ perror("readlink");
    return 0;
}
#endif

if(stat(fd_info->name, &stat_buf) == -1) {
    //~ printf("[debug] %i - %s\n",pid,fd_info->name);
    if (!flag_quiet)
        perror("stat (get_fdinfo)");
    return 0;
}

if(S_ISBLK(stat_buf.st_mode)) {
    int fd;

    fd = open(fd_info->name, O_RDONLY);

    if (fd < 0) {
        if (!flag_quiet)
            perror("open (get_fdinfo)");
        return 0;
    }

#ifdef __APPLE__
    uint64_t bc;
    uint32_t bs;

    bs = 0;
    bc = 0;
    if (ioctl(fd, DKIOCGETBLOCKSIZE, &bs) < 0 ||  ioctl(fd, DKIOCGETBLOCKCOUNT, &bc) < 0) {
        if (!flag_quiet)
            perror("ioctl (get_fdinfo)");
        return 0;
    }
    fd_info->size = bc*bs;
    printf("Size: %lld\n", fd_info->size);
#else
    if (ioctl(fd, BLKGETSIZE64, &fd_info->size) < 0) {
        if (!flag_quiet)
            perror("ioctl (get_fdinfo)");
        return 0;
    }
#endif
} else {
    fd_info->size = stat_buf.st_size;
}

#ifdef __APPLE__
fd_info->pos = vnodeInfo.pfi.fi_offset;
gettimeofday(&fd_info->tv, &tz);
#else
fd_info->pos = 0;

snprintf(fdpath, MAXPATHLEN, "%s/%d/fdinfo/%d", PROC_PATH, pid, fdnum);
fp = fopen(fdpath, "rt");
gettimeofday(&fd_info->tv, &tz);

if(!fp) {
    if (!flag_quiet)
        perror("fopen (get_fdinfo)");
    return 0;
}

while(fgets(line, LINE_LEN - 1, fp) != NULL) {
    line[4]=0;
    if(!strcmp(line, "pos:")) {
        fd_info->pos = atoll(line + 5);
        break;
    }
}
#endif

return 1;
}
int
main(int argc, char **argv)
{
	int listenfd, n;
	struct sockaddr_in servaddr;
	void sig_chld(int);
	void sig_int(int);
	struct socket_fdinfo si;

	if (argc != 4)
		err_quit("Usage: %s <port> <#children> <#max>", basename(argv[0]));

	listenfd = Socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(atoi(argv[1]));

	Bind(listenfd, (SA *) & servaddr, sizeof(servaddr));

	Listen(listenfd, LISTENQ);

	maxconn = atoi(argv[3]);

	Pch = Calloc(maxconn, sizeof(struct child));
	if ((nchildren = mmap(0, sizeof(int),
			    PROT_READ | PROT_WRITE,
			    MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
		err_sys("mmap error");
	if ((Pstat = mmap(0, sizeof(long) * maxconn,
			  PROT_READ | PROT_WRITE,
			  MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
		err_sys("mmap error");
	minconn = *nchildren = atoi(argv[2]);

    if ((lock_fd = open("/tmp/lock.fd", O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0)
        err_sys("open lock_fd error");
    if (unlink("/tmp/lock.fd") < 0)
        err_sys("unlink error");

#if 0
	Signal(SIGCHLD, sig_chld);	/* must call waitpid() */
#endif
	_signal(SIGTERM, sig_term);

	int i, nsel;
	fd_set masterset, rset;
    FD_ZERO(&masterset);
    FD_SET(listenfd, &masterset);

	for (i = 0; i < *nchildren; i++) {
		/* parent prefork children */
		child_make(i, listenfd);
#if (_DEBUG)
        printf("%d status: %d\n", i, Pch[i].child_status);
#endif
	}

	_signal(SIGINT, _sig_int);
	_signal(SIGCHLD, sig_chld);

	for (;;) {
		rset = masterset;
		if ((nsel = select(listenfd+1, &rset, NULL, NULL, NULL)) < 0) {
			if (errno == EINTR)
				continue;
			else
				err_sys("select error");
		} else if (nsel == 0) {	/* _no_ need */
			err_msg("select timeout");
			continue;
		}
		if ((n = proc_pidfdinfo(getpid(), listenfd, PROC_PIDFDSOCKETINFO, &si, sizeof(si))) <= 0)
			err_sys("proc_pidfdinfo error");
        if (n < sizeof(si))
			err_quit("proc_pidfdinfo failed");
        /*
         * struct socket_info {}
         * soi_qlen: half-connction
         * soi_incqlen: incoming-connection
         * soi_rcv.sbi_cc: establish but not delivered connection
         * soi_snd.sbi_cc: send but not delivered connection
         */
        mode_lock_wait(lock_fd);
        if (si.psi.soi_qlen + si.psi.soi_incqlen > 1 &&
                *nchildren < maxconn && quitflag != 1)
#if 0
        if (si.psi.soi_rcv.sbi_cc + si.psi.soi_snd.sbi_cc > 0 &&
                *nchildren < maxconn && !quitflag)
#endif /* On BSD always 0 */
        {
            for (i = 0; i < maxconn; i++) {
                if (Pch[i].child_status == 0)
                    break;
            }
            child_make(i, listenfd);
            (*nchildren)++;
        }
        mode_lock_release(lock_fd);
	}
	exit(0);
}