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

📄 sd_rexd.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic  char sccsid[] = "@(#)sd_rexd.c 1.1 92/07/30 Copyright Sun Micro";#endif/* * sd_rexd - Sundiag's remote execution daemon based on rexd. * * Copyright (c) 1985 Sun Microsystems, Inc. */#include <sys/param.h>#include <rpc/rpc.h>#include <stdio.h>#include <netdb.h>#include <signal.h>#include <sys/socket.h>#include <sys/wait.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <fcntl.h>#include <mntent.h>#include <errno.h>#include <rpcsvc/rex.h>#include "sundiag_rpcnums.h"# define ListnerTimeout 300	/* seconds listner stays alive */# define WaitLimit 10		/* seconds to wait after io is closed */# define TempDir "/tmp_rex"	/* directory to hold temp mounts */# define TempName "/tmp_rex/sd_rexdXXXXXX"				/* name template for temp mount points */# define TempMatch 13		/* unique prefix of above */#define PROGRAMNAME	"sd_rexd"SVCXPRT *ListnerTransp;		/* non-null means still a listner */static char **Argv;		/* saved argument vector (for ps) */static char *LastArgv;		/* saved end-of-argument vector */int OutputSocket;		/* socket for stop/cont notification */int MySocket;			/* transport socket */int HasHelper = 0;		/* must kill helpers (interactive mode) */int debug = 0;extern int Master;		/* half of the pty */main(argc, argv)	int argc;	char **argv;{	  /*	   * the server is a typical RPC daemon, except that we only	   * accept TCP connections.	   */	struct sockaddr_in addr;	int len = sizeof(struct sockaddr_in);	int dorex(), ListnerTimer(), CatchChild();	char c;	int  fdes = 0;	/*	 * Remember the start and extent of argv for setproctitle().	 * Open the console for error printouts, but don't let it be	 * our controlling terminal.	 */		if (geteuid()) {		fprintf(stderr, "sd_rexd: must be super-user to run\n");		exit(1);	}	while ((c=getopt(argc, argv, "d")) != EOF) {		switch(c) {		case 'd':			debug = 1;			break;		}	}	if (debug)		printf("%s started.\n", PROGRAMNAME);	Argv = argv;	if (argc > 0)		LastArgv = argv[argc-1] + strlen(argv[argc-1]);	else		LastArgv = NULL;	close(1); /* close stdout */	close(2); /* close stderr */		/*		 * redirect stdout (file descriptor 1) to console		 * since open returns the lowest number fd available.		 */	/* fdes = open("/dev/console", 1); */	fdes = open("/dev/tty", 1);	if (debug)		printf("opening /dev/console returned fd = %d\n", fdes);	fdes = dup(1);	if (debug)		printf("dup(1) returned fd = %d\n", fdes);	/* NoControl(); */	signal(SIGCHLD, CatchChild);	signal(SIGPIPE, SIG_IGN);	signal(SIGALRM, ListnerTimer);	if (issock(0)) {		if (debug)			printf("started from inetd.\n");		/*		 * Started from inetd: use fd 0 as socket		 */		if ((ListnerTransp = svctcp_create(0, 0, 0)) == NULL) {			fprintf(stderr, "sd_rexd: svctcp_create error\n");			exit(1);		}		if (!svc_register(ListnerTransp, SD_REXPROG, SD_REXVERS, 			dorex, 0)) {			fprintf(stderr, "sd_rexd: service register error\n");			exit(1);		}		alarm(ListnerTimeout);	} else {		/*		 * Started from shell, background thyself and run forever.		 */		int pid = fork();		if (pid < 0) {			perror("rpc.rexd: can't fork");			exit(1);		}		if (pid) {			if (debug) printf("parent exiting. pid = %d.\n", pid);			exit(0);		}		if ((ListnerTransp = svctcp_create(RPC_ANYSOCK, 0, 0)) 				== NULL) {			fprintf(stderr, "sd_rexd: svctcp_create: error\n");			exit(1);		}		if (debug)			printf("started from shell.  pid = %d.\n", pid);		pmap_unset(SD_REXPROG, SD_REXVERS);		if (!svc_register(ListnerTransp, SD_REXPROG, SD_REXVERS, 				dorex, IPPROTO_TCP)) {			fprintf(stderr, "sd_rexd: service rpc register: error\n");			exit(1);		}		if (debug)			printf("dorex registered.\n");	}	/*	 * Create a private temporary directory to hold sd_rexd's mounts	 */	if (mkdir (TempDir, 0777) < 0) {		if (errno != EEXIST) {			perror ("sd_rexd: mkdir");			fprintf (stderr, 				 "sd_rexd: can't create temp directory %s\n",				 TempDir);			exit (1);		} else if (debug)			printf("temp directory %s already exists.\n", TempDir);	} else if (debug)		printf("made temp directory %s.\n", TempDir);/* * normally we would call svc_run() at this point, but we need to be informed * of when the RPC connection is broken, in case the other side crashes. */	while (TRUE) {	    extern int errno;	    fd_set readfds;	    if (MySocket && !FD_ISSET(MySocket, &svc_fdset) ) {		char *waste;		   /*		    * This is when the connection dies for some 		    * random reason, e.g. client crashes.		    */		(void) rex_wait(&waste);		rex_cleanup();		exit(1);	    }	    readfds = svc_fdset;	    switch (select(FD_SETSIZE, &readfds, (int *)0, (int *)0, 0)) {	      case -1:  if (errno == EINTR) continue;	      		perror("sd_rexd: select failed");			exit(1);	      case 0: 	      		fprintf(stderr,"sd_rexd: Select returned zero\r\n");			continue;	      default:	      		if (HasHelper) HelperRead(&readfds);			svc_getreqset(&readfds);	    }	}}/* * This function gets called after the listner has timed out waiting * for any new connections coming in. */ListnerTimer(){  svc_destroy(ListnerTransp);  exit(0);}/* * dorex - handle one of the rex procedure calls, dispatching to the  *	correct function. */dorex(rqstp, transp)	register struct svc_req *rqstp;	register SVCXPRT *transp;{	struct rex_start *rst;	struct rex_result result;		if (ListnerTransp) {		  /*		   * First call - fork a server for this connection		   */		int fd, pid, count;		if (debug)			printf("entering dorex. still a listner.\n");		for (count=0; (pid = fork()) < 0; count++) {			if (count > 4) {				perror("sd_rexd: cannot fork");				break;			}			sleep(5);		}		if (pid != 0) {		    /*		     * Parent - return to service loop to accept further		     * connections.		     */			if (debug)			    printf("dorex: parent; return to service loop.\n");			/* alarm(ListnerTimeout); */			svc_destroy (transp);			return;		}		  /*		   * child - close listner transport to avoid confusion		   * Also need to close all other service transports		   * besides the one we are interested in.		   * Save ours so that we know when it goes away.		   */		alarm(0);		if (transp != ListnerTransp) {			close(ListnerTransp->xp_sock);			xprt_unregister(ListnerTransp);			if (debug)				printf("transp != ListnerTransp\n");		}		ListnerTransp = NULL;		MySocket = transp->xp_sock;		for (fd=0; fd<FD_SETSIZE; fd++)		  if (fd != transp->xp_sock && FD_ISSET(fd, &svc_fdset) ) {			close(fd);			FD_CLR(fd, &svc_fdset);		  }		if (debug)			printf("dorex: child; closed listner transport.\n");	}	switch (rqstp->rq_proc) {	case NULLPROC:		if (svc_sendreply(transp, xdr_void, 0) == FALSE) {			fprintf(stderr, "sd_rexd: nullproc err");			exit(1);		}		return;	case REXPROC_START:		rst = (struct rex_start *)malloc(sizeof (struct rex_start));		bzero((char *)rst, sizeof *rst);		if (svc_getargs(transp, xdr_rex_start, rst) == FALSE) {			svcerr_decode(transp);			exit(1);		}		if (rqstp->rq_cred.oa_flavor != AUTH_UNIX) {			svcerr_auth(transp);			exit(1);		}		result.rlt_stat = rex_start(rst,			(struct authunix_parms *)rqstp->rq_clntcred,			&result.rlt_message, transp->xp_sock);		if (svc_sendreply(transp, xdr_rex_result, &result) == FALSE) {			fprintf(stderr, "sd_rexd: reply failed\n");			rex_cleanup();			exit(1);		}		if (result.rlt_stat) {			rex_cleanup();			exit(0);		}		return;	case REXPROC_MODES:		{		    struct rex_ttymode mode;		    if (svc_getargs(transp, xdr_rex_ttymode, &mode)==FALSE) {			svcerr_decode(transp);			exit(1);		    }		    SetPtyMode(&mode);		    if (svc_sendreply(transp, xdr_void, 0) == FALSE) {			fprintf(stderr, "sd_rexd: mode reply failed");			exit(1);		    }		}		return;	case REXPROC_WINCH:		{		    struct ttysize size;		    if (svc_getargs(transp, xdr_rex_ttysize, &size)==FALSE) {			svcerr_decode(transp);			exit(1);		    }		    SetPtySize(&size);		    if (svc_sendreply(transp, xdr_void, 0) == FALSE) {			fprintf(stderr, "sd_rexd: window change reply failed");			exit(1);		    }		}		return;	case REXPROC_SIGNAL:		{		    int sigNumber;		    if (svc_getargs(transp, xdr_int, &sigNumber)==FALSE) {			svcerr_decode(transp);			exit(1);		    }		    SendSignal(sigNumber);		    if (svc_sendreply(transp, xdr_void, 0) == FALSE) {			fprintf(stderr, "sd_rexd: signal reply failed");			exit(1);		    }		}		return;	case REXPROC_WAIT:		result.rlt_stat = rex_wait(&result.rlt_message);		if (svc_sendreply(transp, xdr_rex_result, &result) == FALSE) {			fprintf(stderr, "sd_rexd: reply failed\n");			exit(1);		}		rex_cleanup();		exit(0);		/* NOTREACHED */	default:		svcerr_noproc(transp);		exit(1);	}}int child = 0;			/* pid of the executed process */int ChildStatus = 0;		/* saved return status of child */int ChildDied = 0;		/* true when above is valid */char nfsdir[MAXPATHLEN];	/* file system we mounted */char *tmpdir;			/* where above is mounted, NULL if none *//* * signal handler for SIGCHLD - called when user process dies or is stopped */CatchChild(){  int pid;  union wait status;    while ((pid = wait3(&status, WNOHANG|WUNTRACED, NULL)) > 0) {    if (pid==child) {      if (WIFSTOPPED(status)) {	  send(OutputSocket, "", 1, MSG_OOB);	/* tell remote client to stop */	  sigpause(0);				/* wait for SIGURG */	  killpg(child, SIGCONT);		/* restart child */	  return;      }      ChildStatus = status.w_retcode;      ChildDied = 1;      if (HasHelper && !FD_ISSET (Master, &svc_fdset)) {	  KillHelper(child);	  HasHelper = 0;	}    }  }}/* * oob -- called when we should restart the stopped child. */oob(){	int atmark;	char waste[BUFSIZ], mark;	for (;;) {

⌨️ 快捷键说明

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