⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serv_p4.c

📁 MPICH是MPI的重要研究,提供了一系列的接口函数,为并行计算的实现提供了编程环境.
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "p4.h"#include "p4_sys.h"/****#include <stdio.h>#include <ctype.h>#include <pwd.h>#include <errno.h>#include <signal.h>#include <netdb.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>#include <time.h>****/#include <sys/stat.h>#include <sys/file.h>#include <sys/ioctl.h>#ifdef _AIX#include <sys/wait.h>#endifextern char *inet_ntoa ( struct in_addr );  /* from <arpa/inet.h> */#ifdef FOO/* These are in p4_sys.h, done better */#ifdef P4BSD#include <strings.h>#endif#ifdef P4SYSV#include <string.h>#endif#endif#if defined(SYMMETRY)#define NEED_GETOPT#endif#ifdef NEED_GETOPT/* This is from the released BSD sources lib/libc/getopt.c *//* * get option letter from argument vector */int	opterr = 1,		/* if error message should be printed */	optind = 1,		/* index into parent argv vector */	optopt;			/* character checked for validity */char	*optarg;		/* argument associated with option */#elseextern char *optarg;#endif#define MAXARGS 256#ifndef LOGFILE#define LOGFILE "/usr/adm/serv_p4.log"#endif#define notice2(a,b) {sprintf(tmpbuf, a, b); notice(tmpbuf);}#define notice3(a,b,c) {sprintf(tmpbuf, a, b,c); notice(tmpbuf);}#define failure2(a,b) {sprintf(tmpbuf, a, b); failure(tmpbuf);}/* extern char *crypt ( const char *, const char * ); */extern char *crypt();#ifndef HAVE_STRERRORextern char *sys_errlist[];#define strerror(n) sys_errlist[n]#endifextern int errno;char tmpbuf[1024];char *fromhost;char logfile[1024];FILE *logfile_fp;int   logfile_fd;#define DEFAULT_PORT 753int daemon_mode;int daemon_port;int daemon_pid;     /* pid of parent */int stdfd_closed = 0;int debug = 0;char *this_username;int this_uid;void doit                    (int);void execute                 ( char *, char *, int, int, struct hostent * );int getline                  ( char *, int );void failure                 ( char * );void notice                  ( char * );int net_accept               ( int );void net_setup_listener      ( int, int, int * );void net_setup_anon_listener ( int, int *, int *);void error_check             ( int, char * );char *timestamp              ( void );char *save_string            ( char * );static int connect_to_listener ( struct hostent *, int );void reaper ( int );int main ( int, char ** );/* * Notes on the use of file descriptors (fds) * * This code uses the <stdio> routines to read/write data to the * connected socket.  This simplifies much of the code.  However, * using stdin/out/err is a problem, since in various modes we may * close those units (for example, in order to start the server with * rsh but have the rsh return when the server starts, it is necessary * to close stdin/out/err).   * * Thus, instead of relying on particular  * unit numbers for stdin/out/err, we set (change) these values. */int stdin_fd	= 0;FILE *stdin_fp  = 0; /*	= stdin; */int stdout_fd	= 1;FILE *stdout_fp = 0; /*	= stdout; */int stderr_fd	= 2;FILE *stderr_fp = 0; /*	= stderr; */void reaper(sigval)int sigval;{    int i;    /* For systems where signal does not work (signals one-shot),       we need to reinstall the handler.  This isn't reliable, since there       is a race condition, but it is a small exposure               Later versions will use sigaction where available.     */    signal(SIGCHLD, reaper);    wait(&i);}int main(argc, argv)int argc;char **argv;{    int c;    struct sockaddr_in name;    int namelen;    int pid;    /* Initialize the FILE handles */    stdin_fp	= stdin;    stdout_fp	= stdout;    stderr_fp	= stderr;    daemon_pid = getpid();    if (getuid() == 0)    {	strcpy(logfile, LOGFILE);	daemon_port = DEFAULT_PORT;    }    else    {	sprintf(logfile, "P4Server.Log.%d", (int)getpid());	daemon_port = 0;	debug = 1;    }    namelen = sizeof(name);    if (getpeername(0, (struct sockaddr *) &name, &namelen) < 0)	daemon_mode = 1;    else	daemon_mode = 0;        while ((c = getopt(argc, argv, "Ddop:l:")) != EOF)    {	switch (c)	{	case 'D':	    debug++;	    break;	    	case 'd':	    daemon_mode++;	    break;	    	case 'o':	    /* Orphan mode; I'd use -detach, but old-fashioned getopt wants	       single letter names */	    daemon_mode++;	    close(0);	    close(1);	    close(2);	    stdfd_closed = 1;	    pid = fork();	    if (pid < 0) {		/* We've closed stderr! */		exit(1);	    }	    else if (pid > 0) exit(0);	    /* We're the child, so we continue on */	    daemon_pid = getpid();	    break;	case 'p':	    daemon_port = atoi(optarg);	    break;	case 'l':	    strcpy(logfile, optarg);	    break;	case '?':	default:	    fprintf(stderr, "\Usage: %s [-d] [-D] [-p port] [-l logfile] [-o]\n",argv[0]);	    exit(1);	}    }    if ((logfile_fp = fopen(logfile, "a")) == NULL)    {	if (getuid() != 0)	{	    fprintf( stdout_fp, "Cannot open logfile, disabling logging\n");	    logfile_fp = fopen("/dev/null", "w");	    	}	else	{	    fprintf( stderr, "Cannot open logfile %s: %s\n",		    logfile, strerror(errno));	    exit(1);	}    }    else {	if (!stdfd_closed)	    fprintf( stdout_fp, "Logging to %s\n", logfile);    }    logfile_fd = fileno( logfile_fp );    setbuf(logfile_fp, NULL);        fprintf( logfile_fp, "%s pid=%d starting at %s, logfile fd is %d\n",	    argv[0], (int)getpid(), timestamp(), logfile_fd );	         fflush( logfile_fp );    if (stdfd_closed) {	/* redirect stdout and stderr to logfile */	dup2( logfile_fd, 1 );	dup2( logfile_fd, 2 );    }    if (daemon_mode)    {	int lfd, /* lfd is listener fd */	    fd,  /* fd is accepted connection fd */            pid; /* pid of child when forking a process to handle connection */	signal(SIGCHLD, reaper);	if (daemon_port == 0)	{	    net_setup_anon_listener(2, &daemon_port, &lfd);	}	else	{	    net_setup_listener(2, daemon_port, &lfd);	}	fprintf( logfile_fp, "Listening on port %d\n", daemon_port );	if ((debug || daemon_port != DEFAULT_PORT) && !stdfd_closed)	    fprintf( stdout_fp, "Listening on %d\n", daemon_port);	    	if (!debug)	{	    /* Create an orphan process and exit.  This is for	       root use only (debug set to 1 if getuid() != 0) 	       NOTE: Since changes in handling of fd's, this code	       may no longer work.	     */	    if (fork())		exit(0);	    for (fd = 0; fd < 10; fd++)		if (fd != lfd && fd != logfile_fd)		    close(fd);	    #ifdef P4SYSV	    fd = open ("/dev/console", O_RDWR);	    if (fd < 0)		fd = open ("/dev/tty", O_RDWR);	    if (fd < 0)		fd = open ("/dev/null", O_RDWR);#    if defined(CRAY)	    (void) dup2(0, 1);	    (void) dup2(0, 2);#    else	    (void) dup2(STDIN_FILENO, STDOUT_FILENO);	    (void) dup2(STDIN_FILENO, STDERR_FILENO);#    endif            /* If your system says "too few arguments to function setpgrp"               then you do NOT have the SYSV version of this function (that               version takes no arguments) */	    (void) setpgrp();#else	    (void) open("/", 0);	    (void) dup2(0, 1);	    (void) dup2(0, 2);	    fd = open("/dev/tty", O_RDWR);	    if (fd >= 0) {		ioctl(fd, TIOCNOTTY, 0);		(void) close(fd);	    }#endif	}	while (1)	{	    /* Wait for a new connection attempt */	    fd = net_accept(lfd);	    pid = fork();	    if (pid < 0)	    {		fprintf( logfile_fp, "Fork failed: %s\n",			 strerror(errno));		exit(pid);	    }	    if (pid == 0)	    {		fprintf( logfile_fp, 		 "Started subprocess for connection at %s with pid %d\n", 			 timestamp(), (int)getpid() );#if defined(HP)		(void) setpgrp();#else		{		    int ttyfd = open("/dev/tty",O_RDWR);		    if (ttyfd >= 0)		    {#    if !defined(CRAY)			ioctl(ttyfd, TIOCNOTTY, 0);#    endif			close(ttyfd);		    }		}#endif		/* Make stdin/stdout refer to fd */		if (stdfd_closed) {		    stdin_fp  = fdopen( fd, "r" );		    stdout_fp = fdopen( fd, "a" );		    stderr_fp = logfile_fp;		    if (stdin_fp == NULL || stdout_fp == NULL) {			fprintf( logfile_fp, 				 "Could not fdopen stdin or out\n" );			exit(1);		    }		    close(lfd);		    		    doit(fd);		}		else {		    close(0);		    dup2(fd, 0);		    close(1);		    dup2(fd, 1);		    close(2); 		    dup2( logfile_fd, 2);		    close(lfd);		    		    doit(0);		}		exit(0);	    }	    /* We can't close the new fd until we're sure that the fork has 	       successfully started */	    /* What we REALLY want to do is close the fd when the child exits	     */	    /* sleep(2); */	    close(fd);	}    }    else    {	doit(0);    }	}/* This is called (possibly in a subprocess) to process create p4-process * requests. */void doit(fd)int fd;{    struct sockaddr_in name;    int namelen;    struct hostent *hp;    struct passwd *pw;    char client_user[80], server_user[80];    char pgm[1024], pgm_args[1024];    char *user_home;    int superuser;    int valid;    FILE *fp;    int stdout_port;    char stdout_port_str[16];    char filename[1024], progline[1024];    struct stat statbuf, statbuf_pgm, statbuf_apps_entry;    this_uid = getuid();    pw = getpwuid(this_uid);    if (pw == NULL)    {	fprintf( logfile_fp, "Cannot get pw entry for user %d\n", this_uid);	exit(1);    }    this_username = save_string(pw->pw_name);    if (this_uid != 0)	fprintf( logfile_fp, "WARNING: Not run as root\n");    setbuf(stdout_fp, NULL);    fprintf( logfile_fp, "Got connection at %s", timestamp());    namelen = sizeof(name);    if (getpeername(fd, (struct sockaddr *) &name, &namelen) != 0)    {	fprintf( logfile_fp, "getpeername failed: %s\n",		 strerror(errno));	exit(1);    }    fromhost = inet_ntoa(name.sin_addr);        hp = gethostbyaddr((char *) &name.sin_addr,		       sizeof(name.sin_addr),		       (int) name.sin_family);    if (hp == NULL)	failure2("Cannot get remote address for %s", fromhost);    fromhost = hp->h_name;    if (!getline(client_user, sizeof(client_user)))	failure("No client user");    if (!getline(server_user, sizeof(server_user)))	failure("No server user");    pw = getpwnam(server_user);    if (pw == NULL)	failure2("No such user: %s\n", server_user);    if (this_uid != 0 && this_uid != pw->pw_uid)	failure2("Server is not running as root. Only %s can start processes\n",		 this_username);    user_home = pw->pw_dir;    superuser = (pw->pw_uid == 0);    fprintf( logfile_fp, "Starting ruserok at %s\n", timestamp() );    valid = ruserok(fromhost, superuser, client_user, server_user);    fprintf( logfile_fp, "Completed ruserok at %s\n", timestamp() );    if (valid != 0)    {	char user_pw[80];	char *xpw;		fprintf( stdout_fp, "Password\n");	if (!getline(user_pw, sizeof(user_pw)))	    failure("No server user");	xpw = crypt(user_pw, pw->pw_passwd);	if (strcmp(pw->pw_passwd, xpw) != 0)	    failure("Invalid password");	fprintf( stdout_fp, "Proceed\n");    }    else	fprintf( stdout_fp, "Proceed\n");    /* Make sure that the proceed message is delivered */    fflush( stdout_fp );    sprintf(tmpbuf, "authenticated client_id=%s server_id=%s\n",	    client_user, server_user);    notice(tmpbuf);    /*        At this point, we have an authenticated user.  We could accept       additional commands beyond just "start program".  For example,       we could accept "exit", which would allow simpler management of       the servers.  (Note that we'd have to kill the parent, since we're       probably just a forked child).     */    /* Get the program to execute */    if (!getline(pgm, sizeof(pgm)))	failure("No pgm");    /* Check for key words:       %id (give id)       %run (run program)       %exit (exit)     */    if (strcmp( pgm, "%id" ) == 0) {	fprintf( stdout_fp, "Port %d for client %s and server user %s\n", 		daemon_port, client_user, server_user );	exit(0);    }    else if (strcmp( pgm, "%run" ) == 0) {	/* Just get the program */	if (!getline(pgm, sizeof(pgm)))	    failure("No pgm");    }    else if (strcmp( pgm, "%exit" ) == 0) {	kill( daemon_pid, SIGINT );	sleep(1);	kill( daemon_pid, SIGQUIT );	exit(1);    }    if (!getline(pgm_args, sizeof(pgm_args)))	failure("No pgm args");    notice2("got args %s", pgm_args);    if (pgm[0] != '/')	failure2("%s is not a full pathname", pgm);    if (this_uid == 0)    {#if defined(HP) && !defined(SUN_SOLARIS)	if (setresuid(-1, pw->pw_uid, -1) != 0)	    failure2("setresuid failed: %s", strerror(errno));#else#ifndef _AIX	if (seteuid(pw->pw_uid) != 0)	    failure2("seteuid failed: %s", strerror(errno));#endif#endif    }    #define P4_APP_TEST#ifdef P4_APP_TEST    sprintf(filename, "%s/.p4apps", user_home);    valid = 0;    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -