int do_daemonize(void) { pid_t child; unsigned int i; if ((child = fork()) == (pid_t) -1) { logger_error(NULL, "Unable to fork() in order to daemonize"); return -1; } else if (child != (pid_t) 0) { _exit(0); } if (setsid() == (pid_t) -1) { logger_error(NULL, "Unable to setsid()"); } i = open_max(); do { if (isatty((int) i)) { (void) close((int) i); } i--; } while (i > 2U); if (closedesc_all(1) != 0) { logger_error(NULL, _PATH_DEVNULL " duplication"); return -1; } return 0; }
void hmsg_monitor(void) { int i, maxi, listenfd, clifd, nread; char buf[MAXLINE]; uid_t uid; struct pollfd *pollfd; if ((pollfd = malloc(open_max() * sizeof(struct pollfd))) == NULL) dlog(L_ERR, "malloc error"); /* obtain fd to listen for client requests on */ if ((listenfd = msg_listen(MSG_PATH)) < 0) dlog(L_ERR, "msg_listen error"); client_add(listenfd, 0); /* we use [0] for listenfd */ pollfd[0].fd = listenfd; pollfd[0].events = POLLIN; maxi = 0; for ( ; ; ) { if (poll(pollfd, maxi + 1, -1) < 0) dlog(L_ERR, "poll error"); if (pollfd[0].revents & POLLIN) { /* accept new client request */ if ((clifd = serv_accept(listenfd, &uid)) < 0) dlog(L_ERR, "serv_accept error: %d", clifd); i = client_add(clifd, uid); pollfd[i].fd = clifd; pollfd[i].events = POLLIN; if (i > maxi) maxi = i; dlog(L_INFO, "new connection: uid %d, fd %d\n", uid, clifd); } for (i = 1; i <= maxi; i++) { if ((clifd = client[i].fd) < 0) continue; if (pollfd[i].revents & POLLHUP) { goto hungup; } else if (pollfd[i].revents & POLLIN) { /* read argument buffer from client */ if ((nread = read(clifd, buf, MAXLINE)) < 0) { dlog(L_ERR, "read error on fd %d\n", clifd); } else if (nread == 0) { hungup: dlog(L_INFO, "closed: uid %d, fd %d\n", client[i].uid, clifd); client_del(clifd); /* client has closed conn */ pollfd[i].fd = -1; close(clifd); } else { /* process client's request */ msg_parse_arg(buf, nread, clifd, client[i].uid); } } } } }
FILE * popen(const char *cmdstring, const char *type) { int i; int pfd[2]; pid_t pid; FILE *fp; if ((type[0] != 'r' && type[0] != 'w') || type[1] != 0) { errno = EINVAL; return (NULL); } if (childpid == NULL) { maxfd = open_max(); if ((childpid = calloc(maxfd, sizeof(pid_t))) == NULL) return NULL; } if (pipe(pfd) < 0){ return (NULL); } else if (pid == 0) { if (*type == 'r') { close(pfd[0]); if (pfd[1] != STDOUT_FILENO) { dup2(pfd[1], STDOUT_FILENO); close(pfd[1]); } } else { close(pfd[1]); if (pfd[0] != STDIN_FILENO) { dup2(pfd[0], STDIN_FILENO); close(pfd[0]); } } for (i = 0; i < maxfd; i++) if (childpid[i] > 0) close(i); execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); _exit(127); } if (*type == 'r') { close(pfd[1]); if ((fp = fdopen(pfd[0], type)) == NULL) return (NULL); } else { close(pfd[0]); if ((fp = fopen(pfd[1], type)) == NULL) return (NULL); } childpid[fileno(fp)] = pid; return (fp); }
int main(int argc, char **argv) { struct rlimit rlp; if (getrlimit(RLIMIT_NOFILE, &rlp) != 0) { fprintf(stderr, "Unable to get per process rlimit: %s\n", strerror(errno)); exit(EXIT_FAILURE); } printf("This user could open %d file descriptors.\n", open_max()); printf("This process could open %d file descriptors.\n", (int)rlp.rlim_cur); return EXIT_SUCCESS; }
static int fdwalk(int (*func)(void *data, int fd), void *data){ int rv = 0; int fd; #ifdef PROC_SELF_FD_DIR DIR *dir = opendir(PROC_SELF_FD_DIR); if(dir){ /* procfs may not be mounted... */ struct dirent *ent; int saved_errno; int dir_fd = dirfd(dir); while((ent = readdir(dir))){ char *err = NULL; if(ent->d_name[0] == '.') continue; errno = 0; fd = (int)strtol(ent->d_name, &err, 10); if (errno || ! err || *err || fd == dir_fd) continue; if ((rv = func(data, fd))) break; } saved_errno = errno; closedir(dir); errno = saved_errno; } else #endif /* PROC_SELF_FD_DIR */ { int maxfd = open_max(); for(fd = 0; fd < maxfd; fd++){ /* use fcntl to detect whether fd is a valid file descriptor */ errno = 0; if(fcntl(fd, F_GETFD) < 0) continue; errno = 0; if ((rv = func(data, fd))) break; } } return rv; }
/* * call-seq: * IO.closefrom(lowfd) * * Close all open file descriptors (associated with the current process) that * are greater than or equal to +lowfd+. * * This method uses your system's builtin closefrom() function, if supported. * Otherwise, it uses a manual, and (probably) less efficient approach. * *-- * The manual approach was copied from the closefrom() man page on Solaris 9. */ static VALUE io_closefrom(VALUE klass, VALUE v_low_fd){ #if defined(HAVE_CLOSEFROM) && !defined(HAVE_RB_RESERVED_FD_P) /* we can't safely use closefrom() if the RubyVM reserves FDs */ closefrom(NUM2INT(v_low_fd)); #else int i, lowfd; int maxfd = open_max(); lowfd = NUM2INT(v_low_fd); for(i = lowfd; i < maxfd; i++) { if(!RB_RESERVED_FD_P(i)) close(i); } #endif return klass; }
FILE * popen(const char *cmdstring, const char *type) { int i; int pfd[2]; pid_t pid; FILE *fp; /* only allow "r" or "w" */ if ((type[0] != 'r' && type[0] != 'w') || type[1] != 0) { errno = EINVAL; return(NULL); } if (childpid == NULL) { /* first time throught */ /* allocate zeroed out array for child pids */ maxfd = open_max(); if ((childpid = calloc(maxfd, sizeof(pid_t))) == NULL) return(NULL); } if (pipe(pfd) < 0) return(NULL); /* errno set by pipe() */ if (pfd[0] >= maxfd || pfd[1] >= maxfd) { close(pfd[0]); close(pfd[1]); errno = EMFILE; return(NULL); } if ((pid = fork()) < 0) { return(NULL); /* errno set by fork() */ } else if (pid == 0) { /* child */ if (*type == 'r') { close(pfd[0]); if (pfd[1] != STDOUT_FILENO) { dup2(pfd[1], STDOUT_FILENO); close(pfd[1]); } } else if (*type == 'w') { close(pfd[1]); if (pfd[0] != STDIN_FILENO) { dup2(pfd[0], STDIN_FILENO); close(pfd[0]); } } /* close all descriptors in childpid[] */ for (i = 0; i < maxfd; i++) if (childpid[i] > 0) close(i); execl("/bin/sh", "sh", "-c", cmdstring, (char*)0); _exit(127); } /* parent continues... */ if (*type == 'r') { close(pfd[1]); if ((fp = fdopen(pfd[0], type)) == NULL) return(NULL); } else { close(pfds[0]); if ((fp = fdopen(pfd[1], type)) == NULL) return(NULL); } childpid[fileno(fp)] = pid; /* remeber child pid for this fd */ return(fp); }
int main() { int size = open_max(); printf("size: %d\n", size); return 0; }
int main() { long ans = open_max(); printf("%ld\n", ans); return 0; }
#include <poll.h> #include <limits.h> /* for open_max() */ #include <netdb.h> /* POSIX requires that an #include of <poll.h> DefinE INFTIM, but many systems still DefinE it in <sys/stropts.h>. We don't want to include all the STREAMS stuff if it's not needed, so we just DefinE INFTIM here. This is the standard value, but there's no guarantee it is -1. */ #define INFTIM (-1) /* infinite poll timeout */ #define HAVE_POLL #ifdef OPEN_MAX static long openmax = open_max(); #else static long openmax = 0; #endif /* * If open_max() is indeterminate, we're not * guaranteed that this is adequate. */ #define OPEN_MAX_GUESS 256 void err_sys(const char *fmt, ...); long open_max(void)
FILE *popen(const char *cmdstring, const char *type) { int i; int pfd[2]; pid_t pid; FILE *fp; /* only allow "r" or "w" */ if ((type[0] != 'r' && type[0] != 'w') || type[1] != '\0') { errno = EINVAL; return (NULL); } if (childpid == NULL) { maxfd = open_max(); if ((childpid = calloc(maxfd, sizeof(pid_t))) == NULL) return (NULL); } if (pipe(pfd) < 0) return (NULL); if (pfd[0] >= maxfd || pfd[1] >= maxfd) { close(pfd[0]); close(pfd[1]); errno = EMFILE; return (NULL); } if ((pid = fork()) < 0) { return (NULL); } else if (pid == 0) { if (*type == 'r') { close(pfd[0]); if (pfd[1] != STDOUT_FILENO) { dup2(pfd[1], STDOUT_FILENO); close(pfd[0]); } } else { close(pfd[1]); if (pfd[0] != STDOUT_FILENO) { dup2(pfd[0], STDOUT_FILENO); close(pfd[0]); } } /* close all descriptors in childpid */ for (i = 0; i < maxfd; i++) close(i); execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); _exit(127); /* if it executes, that would be a error */ } /* parent continue */ if (*type == 'r') { close(pfd[1]); if ((fp = fdopen(pfd[0], type)) == NULL) return (NULL); } else { close(pfd[0]); if ((fp = fdopen(pfd[1], type)) == NULL) return (NULL); } childpid[fileno(fp)] = pid; return (fp); }
FILE * spopen (const char *cmdstring) { char *env[2]; char *cmd = NULL; char **argv = NULL; char *str, *tmp; int argc; int i = 0, pfd[2], pfderr[2]; pid_t pid; #ifdef RLIMIT_CORE /* do not leave core files */ struct rlimit limit; getrlimit (RLIMIT_CORE, &limit); limit.rlim_cur = 0; setrlimit (RLIMIT_CORE, &limit); #endif env[0] = strdup("LC_ALL=C"); env[1] = '\0'; /* if no command was passed, return with no error */ if (cmdstring == NULL) return (NULL); /* make copy of command string so strtok() doesn't silently modify it */ /* (the calling program may want to access it later) */ cmd = malloc (strlen (cmdstring) + 1); if (cmd == NULL) return NULL; strcpy (cmd, cmdstring); /* This is not a shell, so we don't handle "???" */ if (strstr (cmdstring, "\"")) return NULL; /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */ if (strstr (cmdstring, " ' ") || strstr (cmdstring, "'''")) return NULL; /* there cannot be more args than characters */ argc = strlen (cmdstring) + 1; /* add 1 for NULL termination */ argv = malloc (sizeof(char*)*argc); if (argv == NULL) { printf ("%s\n", _("Could not malloc argv array in popen()")); return NULL; } /* loop to get arguments to command */ while (cmd) { str = cmd; str += strspn (str, " \t\r\n"); /* trim any leading whitespace */ if (i >= argc - 2) { printf ("%s\n",_("CRITICAL - You need more args!!!")); return (NULL); } if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */ str++; if (!strstr (str, "'")) return NULL; /* balanced? */ cmd = 1 + strstr (str, "'"); str[strcspn (str, "'")] = 0; } else if (strcspn(str,"'") < strcspn (str, " \t\r\n")) { /* handle --option='foo bar' strings */ tmp = str + strcspn(str, "'") + 1; if (!strstr (tmp, "'")) return NULL; /* balanced? */ tmp += strcspn(tmp,"'") + 1; *tmp = 0; cmd = tmp + 1; } else { if (strpbrk (str, " \t\r\n")) { cmd = 1 + strpbrk (str, " \t\r\n"); str[strcspn (str, " \t\r\n")] = 0; } else { cmd = NULL; } } if (cmd && strlen (cmd) == strspn (cmd, " \t\r\n")) cmd = NULL; argv[i++] = str; } argv[i] = NULL; if (childpid == NULL) { /* first time through */ maxfd = open_max (); /* allocate zeroed out array for child pids */ if ((childpid = calloc ((size_t)maxfd, sizeof (pid_t))) == NULL) return (NULL); } if (child_stderr_array == NULL) { /* first time through */ maxfd = open_max (); /* allocate zeroed out array for child pids */ if ((child_stderr_array = calloc ((size_t)maxfd, sizeof (int))) == NULL) return (NULL); } if (pipe (pfd) < 0) return (NULL); /* errno set by pipe() */ if (pipe (pfderr) < 0) return (NULL); /* errno set by pipe() */ #ifdef REDHAT_SPOPEN_ERROR if (signal (SIGCHLD, popen_sigchld_handler) == SIG_ERR) { usage4 (_("Cannot catch SIGCHLD")); } #endif if ((pid = fork ()) < 0) return (NULL); /* errno set by fork() */ else if (pid == 0) { /* child */ close (pfd[0]); if (pfd[1] != STDOUT_FILENO) { dup2 (pfd[1], STDOUT_FILENO); close (pfd[1]); } close (pfderr[0]); if (pfderr[1] != STDERR_FILENO) { dup2 (pfderr[1], STDERR_FILENO); close (pfderr[1]); } /* close all descriptors in childpid[] */ for (i = 0; i < maxfd; i++) if (childpid[i] > 0) close (i); execve (argv[0], argv, env); _exit (0); } close (pfd[1]); /* parent */ if ((child_process = fdopen (pfd[0], "r")) == NULL) return (NULL); close (pfderr[1]); childpid[fileno (child_process)] = pid; /* remember child pid for this fd */ child_stderr_array[fileno (child_process)] = pfderr[0]; /* remember STDERR */ return (child_process); }
int main() { printf("openmax = %ld\n", open_max()); return 0; }
FILE* mypopen(const char *cmdstring, const char *type){ int i; int pfd[2]; pid_t pid; FILE *fp; /*only allow "r" or "w"*/ if((type[0] != 'r' && type[0] != 'w') || type[1] != 0){ errno = EINVAL;/*required by POSIX*/ return(NULL); } if(childpid == NULL){/*first time through*/ /*allocate zeroed out array for child pids*/ maxfd = open_max(); if((childpid = calloc(maxfd, sizeof(pid_t))) == NULL) return(NULL); } if(pipe(pfd) < 0) return(NULL);/*errno set by pipe()*/ if((pid = fork()) < 0){ return(NULL);/*errno set by fork()*/ }else if(pid == 0){/*child*/ if(*type == 'r'){ close(pfd[0]);/*close the read end.*/ if(pfd[1] != STDOUT_FILENO){ dup2(pfd[1], STDOUT_FILENO); close(pfd[1]); } }else{ close(pfd[1]);/*close the read end.*/ if(pfd[0] != STDIN_FILENO){ dup2(pfd[0], STDIN_FILENO); close(pfd[0]); } } /*close all descriptors in childpid[]*/ for(i = 0; i < maxfd; i++){ if(childpid[i] > 0) close(i); } execl("/bin/sh", "sh", "-c", cmdstring, (char *) 0); _exit(127);/*when execl run normal, this will not run.*/ } /*parent continues...*/ if(*type == 'r'){ close(pfd[1]); /*change fd to FILE pointer.*/ if((fp = fdopen(pfd[0], type)) == NULL) return NULL; }else{ close(pfd[0]); if((fp = fdopen(pfd[1], type)) == NULL) return NULL; } childpid[fileno(fp)] = pid;/*remember child pid for this fd*/ return fp; }
int main(int argc, char *argv[]) { printf("max file descriptors number is %ld\n", open_max()); return 0; }
int main( int argc, char *argv[] ) { printf( "openmax = %ld\n", open_max() ); exit(0); }
FILE *popen_l(const char *cmd, const char *type) { int i, pfd[2]; FILE *fp; pid_t pid; /* only allow "r" or "w" */ if ((type[0] != 'r' && type[0] != 'w') || type[1] != '\0') { errno = EINVAL; /* required by POSIX */ return NULL; } if (childpid == NULL) { /* first time through */ /* allocate zeroed out array for child pids */ maxfd = open_max(); if ((childpid = calloc(maxfd, sizeof(childpid))) == NULL) { return NULL; } } if (pipe(pfd) < 0) return NULL; /* errno set by pipe() */ if ((pid = fork()) < 0) { return NULL; /* errno set by fork() */ } else if (pid == 0) { /* child */ if (type[0] == 'r') { close(pfd[0]); if (pfd[1] != STDOUT_FILENO) { dup2(pfd[1], STDOUT_FILENO); close(pfd[1]); } } else { close(pfd[1]); if (pfd[0] != STDIN_FILENO) { dup2(pfd[0], STDIN_FILENO); close(pfd[0]); } } /* close all descriptors in childpid[]. * 书中提到, POSIX.1 requires that popen() close any streams that * are still open in the child from previous call to popen(). To * do this, we go through the childpid array in the child, closing * any descriptors that are still open. * POSIX.1标准中,对这个要求的原始描述是: The popen() function shall * ensure that any streams from previous popen() calls that remain * open in the parent process are closed in the new child process. * 即,假设已经调用过一次popen(),父进程得到一个FILE *类型的fp指针,然 * 后父进程再调用popen()时,popen()创建的子进程也拥有一个fp指针,但是 * 子进程不需要该fp指针,所以子进程要关闭它. */ for (i = 0; i < maxfd; ++i) if (childpid[i] > 0) close(i); /* sh 命令的 -c 选项表示: Read commands from the command_string * operand nsteand of from the standard input. */ execl("/bin/sh", "sh", "-c", cmd, (char *)0); _exit(127); } /* parent continues... */ if (type[0] == 'r') { close(pfd[1]); if ((fp = fdopen(pfd[0], type)) == NULL) return NULL; } else { close(pfd[0]); if ((fp = fdopen(pfd[1], type)) == NULL) return NULL; } childpid[fileno(fp)] = pid; /* remember child pid for this fd */ return fp; }
int geekhttpd_daemon(void) { int fd0, fd1, fd2; /* stdin, stdout, stderr */ long openmax, i; pid_t pid; char cwd[256]; struct sigaction sa; /*信号处理 */ /*由于子进程继承了父进程的file mode creation mask, * 所以子进程要创建文件时也会用这个mask值进行与之后的结 * 果来创建文件, 所以为了不影响文件的创建,把它清零 */ umask(0); if ((pid = fork()) < 0){ printf("cann't fork!\n"); return -1; } else if( pid != 0) /* parent */ exit(0); /* 父进程退出*/ /* 把子进程变以一个session leader, process * group leader, 并且没有控制终端 */ setsid(); /* 确保子进程没有分配终端*/ sa.sa_handler = SIG_IGN; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (sigaction(SIGHUP, &sa, NULL) < 0) { printf("sigaction error, SIGHUP"); return(-1); } /* TODO: 处理SIGTERM */ /* 把工作目录切换到服务器所在的工作目录, 防止目前工作目前可能被umount而受影响 */ if((access(g_geekhttpd_doc_path, F_OK|R_OK|X_OK)) == -1) { perror("Cannot access GEEKHTTP_DOC_PATH"); return(-1); } if (chdir(g_geekhttpd_doc_path) < 0) { printf("cannot change work directory to GEEKHTTP_DOC_PATH\n"); return(-1); } if (getcwd(cwd, 256) == NULL) printf("getcwd error\n"); printf("[cwd]: %s\n", cwd); /* Close all open file descriptors. */ openmax = open_max(); for (i = 0; i< openmax; i++) close(i); /* 把标准输入输出和出错文件描述符重定位到/dev/null */ fd0 = open("/dev/null", O_RDWR); fd1 = dup(0); fd2 = dup(0); /* 到目前为止就不能使用printf来输出信息了, * 只有通过syslog */ openlog("geekhttpd", LOG_CONS, LOG_DAEMON); if (fd0 != 0 || fd1 != 1 || fd2 != 2) { syslog(LOG_ERR, "unexpected file descriptors %d %d %d", \ fd0, fd1, fd2); return(-1); } }