📄 serv_p4.c
字号:
#ifdef _AIX { int reader_pipe[2]; int reader_pid; if (pipe(reader_pipe) < 0) failure2("reader pipe failed: %s", strerror(errno)); if ((reader_pid = fork()) < 0) failure2("reader fork failed: %s", strerror(errno)); notice2("got reader pid %d", reader_pid); if (reader_pid == 0) { int fd; close(reader_pipe[0]);#if defined(SUN_SOLARIS) if (setuid(pw->pw_uid) != 0) failure2("cannot setuid: %s", strerror(errno)); if (seteuid(pw->pw_uid) != 0) failure2("cannot seteuid: %s", strerror(errno));#else /* We can only call setreuid if we are root; otherwise we get EPERM */ if (this_uid == 0 && setreuid(pw->pw_uid, pw->pw_uid) != 0) exit(1);#endif if ((fd = open(filename, O_RDONLY)) >= 0) { char buf[1024]; int n; while ((n = read(fd, buf, sizeof(buf))) > 0) { if (n != write(reader_pipe[1], buf, n)) notice("Short write"); } if (n < 0) { close(reader_pipe[1]); exit(1); } close(fd); } else { close(reader_pipe[1]); exit(1); } close(reader_pipe[1]); exit(0); } else { close(reader_pipe[1]); fp = fdopen(reader_pipe[0], "r"); if (!fp) { fprintf( logfile_fp, "Could not get FILE for reader_pipe fd\n" ); } } }#else fp = fopen(filename,"r");#endif /* _AIX */ if (fp != (FILE *) NULL) { char *s1, *s2; if (fstat( fileno(fp), &statbuf) != 0) failure2("cannot stat %s", filename); if (statbuf.st_mode & 077) failure(".p4apps readable by others"); /* fprintf( logfile_fp, "Trying to find program %s\n", pgm ); */ restart_read: errno = 0; /* ensure that it isn't EINTR from some previous event */ while (fgets(progline, sizeof(progline), fp) != NULL) { s1 = progline; while (*s1 && isspace(*s1)) s1++; if (*s1 == '\0' || *s1 == '#') continue; s2 = s1; while (*s2 && !isspace(*s2)) s2++; *s2 = 0; /* fprintf( logfile_fp, "Checking %s\n", s1 ); */ if (strcmp(pgm, s1) == 0) { valid = 1; break; } else { if (stat(pgm, &statbuf_pgm) != 0) continue; if (stat(s1, &statbuf_apps_entry) != 0) continue; if (statbuf_pgm.st_ino == statbuf_apps_entry.st_ino) valid = 1; } } /* Fix for fgets fails because of interrupted system call */ if ((errno == EINTR) || (errno == EAGAIN)) goto restart_read; fclose(fp);#ifdef _AIX { int status; pid_t pid; pid = wait(&status); notice2("got wait return %d", status); if (WEXITSTATUS(status) == 1) failure("reader child failed"); }#endif } if (!valid) failure2("Invalid program %s", pgm); if (stat(pgm, &statbuf) != 0) failure2("Cannot stat %s", pgm); if (!(statbuf.st_mode & 0111)) failure2("Cannot execute %s", pgm);#endif /*********/ if (!getline(stdout_port_str, sizeof(stdout_port_str))) failure("No stdout"); else stdout_port = atoi(stdout_port_str); notice2("got stdout_port %d", stdout_port); /*********/ notice3("executing %s %s", pgm, pgm_args); execute(pgm, pgm_args, pw->pw_uid, stdout_port, hp); }void execute(pgm, pgm_args, uid, stdout_port, hp)char *pgm, *pgm_args;int uid, stdout_port;struct hostent *hp;{ int p[2]; int rd, wr; int pid, n; char *args[MAXARGS]; int nargs; char *s, *end; char buf[1024]; int stdout_fd; s = pgm_args; while (*s && isspace(*s)) s++; args[0] = pgm; nargs = 1; while (*s) { args[nargs] = s; while (*s && !isspace(*s)) s++; end = s; while (*s && isspace(*s)) s++; *end = 0; nargs++; if (nargs + 1>= MAXARGS) failure("Too many arguments to pgm"); } args[nargs] = NULL; if (pipe(p) != 0) failure2("Cannot create pipe: %s", strerror(errno)); rd = p[0]; wr = p[1]; if (fcntl(wr, F_SETFD, 1) != 0) failure2("fcntl F_SETFD failed: %s", strerror(errno)); if (this_uid == 0) {#if defined(HP) && !defined(SUN_SOLARIS) if (setresuid(uid, uid, -1) != 0) failure2("cannot setresuid: %s", strerror(errno));#else if (seteuid(0) != 0) failure2("cannot seteuid: %s", strerror(errno));#if defined(SUN_SOLARIS) if (setuid(uid) != 0) failure2("cannot setuid: %s", strerror(errno));#else if (setreuid(uid, uid) != 0) failure2("cannot setreuid: %s", strerror(errno));#endif#endif } pid = fork(); if (pid < 0) failure2("fork failed: %s", strerror(errno)); if (pid == 0) { close(rd); close(0); open("/dev/null", O_RDONLY); stdout_fd = connect_to_listener(hp,stdout_port); notice2("stdout_fd=%d", stdout_fd); close(1); dup(stdout_fd); /* open("/dev/null", O_WRONLY); */ close(2); dup(stdout_fd); /* open("/dev/null", O_WRONLY); */ /***** {char tempbuf[100]; strcpy(tempbuf,"writing this to stdout_fd"); write(stdout_fd,tempbuf,strlen(tempbuf)+1); strcpy(tempbuf,"writing this to real stdout"); write(stdout_fd,tempbuf,strlen(tempbuf)+1); } *****/ if (execv(pgm, args) != 0) { sprintf(tmpbuf, "Exec failed: %s\n", strerror(errno)); write(wr, tmpbuf, strlen(tmpbuf)); exit(0); } } close(wr); if ((n = read(rd, buf, sizeof(buf))) > 0) { buf[n] = 0; s = index(buf, '\n'); if (s) *s = 0; failure2("child failed: %s", buf); } fprintf( stdout_fp, "Success: Child %d started\n", pid); notice2("Child %d started", pid);}int getline(str, len)char *str;int len;{ char *s; if (fgets(str, len, stdin_fp) == NULL) return 0; if ((s = index(str, '\n')) != NULL) *s = 0; if ((s = index(str, '\r')) != NULL) *s = 0; return 1;} void failure(s)char *s;{ fprintf( stdout_fp, "Failure <%s>: %s\n", fromhost, s); fprintf( logfile_fp, "Failure <%s>: %s\n", fromhost, s); fflush(logfile_fp); exit(1);}void notice(s)char *s;{ fprintf( logfile_fp, "Notice <%s>: %s\n", fromhost, s); fflush(logfile_fp);}/* Accept a connection on socket skt and return fd of new connection. */int net_accept(skt)int skt;{struct sockaddr_in from;int fromlen;int skt2;int gotit; fromlen = sizeof(from); gotit = 0; while (!gotit) { skt2 = accept(skt, (struct sockaddr *) &from, &fromlen); if (skt2 == -1) { if (errno == EINTR) continue; else error_check(skt2, "net_accept accept"); } else gotit = 1; } return(skt2);}void net_setup_listener(backlog, port, skt)int backlog, port, *skt;{int sinlen;struct sockaddr_in sin; *skt = socket(AF_INET, SOCK_STREAM, 0); error_check(*skt,"net_setup_anon_listener socket"); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(port); sinlen = sizeof(sin); error_check(bind(*skt,(struct sockaddr *) &sin,sizeof(sin)), "net_setup_listener bind"); error_check(listen(*skt, backlog), "net_setup_listener listen");}void net_setup_anon_listener(backlog, port, skt)int backlog, *port, *skt;{int sinlen;struct sockaddr_in sin; *skt = socket(AF_INET, SOCK_STREAM, 0); error_check(*skt,"net_setup_anon_listener socket"); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(0); sinlen = sizeof(sin); error_check(bind(*skt,(struct sockaddr *) &sin,sizeof(sin)), "net_setup_anon_listener bind"); error_check(listen(*skt, backlog), "net_setup_anon_listener listen"); getsockname(*skt, (struct sockaddr *) &sin, &sinlen); *port = ntohs(sin.sin_port);}void error_check(val, str)int val;char *str;{ if (val < 0) { fprintf(logfile_fp, "%s: %s\n", str, strerror(errno)); exit(1); }}#include <time.h>char *timestamp(){ long clock; struct tm *tmp; clock = time(0L); tmp = localtime(&clock); return asctime(tmp);}char *save_string(s)char *s;{ char *rc = (char *) malloc(strlen(s) + 1); strcpy(rc, s); return rc;}#ifdef NEED_GETOPT/* This is from the released BSD sources lib/libc/getopt.c *//* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#define BADCH (int)'?'#define EMSG ""intgetopt(nargc, nargv, ostr) int nargc; char **nargv; char *ostr;{ static char *place = EMSG; /* option letter processing */ register char *oli; /* option letter list index */ char *p; if (!*place) { /* update scanning pointer */ if (optind >= nargc || *(place = nargv[optind]) != '-') { place = EMSG; return(EOF); } if (place[1] && *++place == '-') { /* found "--" */ ++optind; place = EMSG; return(EOF); } } /* option letter okay? */ if ((optopt = (int)*place++) == (int)':' || !(oli = index(ostr, optopt))) { /* * if the user didn't specify '-' as an option, * assume it means EOF. */ if (optopt == (int)'-') return(EOF); if (!*place) ++optind; if (opterr) { if (!(p = rindex(*nargv, '/'))) p = *nargv; else ++p; (void)fprintf(stderr, "%s: illegal option -- %c\n", p, optopt); } return(BADCH); } if (*++oli != ':') { /* don't need argument */ optarg = NULL; if (!*place) ++optind; } else { /* need an argument */ if (*place) /* no white space */ optarg = place; else if (nargc <= ++optind) { /* no arg */ place = EMSG; if (!(p = rindex(*nargv, '/'))) p = *nargv; else ++p; if (opterr) (void)fprintf(stderr, "%s: option requires an argument -- %c\n", p, optopt); return(BADCH); } else /* white space */ optarg = nargv[optind]; place = EMSG; ++optind; } return(optopt); /* dump back option letter */}#endifstatic int connect_to_listener(hp,stdout_port)struct hostent *hp;int stdout_port;{ int conn; int rc; struct sockaddr_in addr; conn = socket(AF_INET, SOCK_STREAM, 0); if (conn < 0) { failure("connect_to_listener: socket failed"); } addr.sin_family = hp->h_addrtype; addr.sin_port = htons(stdout_port); bcopy(hp->h_addr, &addr.sin_addr, hp->h_length); rc = connect(conn, (struct sockaddr *) & addr, sizeof(addr)); if (rc < 0) { failure("connect_to_listener: connect failed"); } return conn;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -