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

📄 spm.c

📁 Porting the Simple Sockets Library Dr. Charles E. Campbell, Jr.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Spm: The PortMaster *	This program is expected to run as a daemon on every machine *  which uses Terry McRoberts' Socket Library. * *  Its purpose in life is to: *   a) receive messages from processes starting up servers to maintain *	    a list of process names and associated ports, *   b) to inform processes starting up client sockets about the port *	    numbers of designed servers. * *  This program's services are generally hidden from the users, and is *  accessed by the Sopen() functions.  Since processes from anywhere *	need to access this process, it has a fixed port number (PORTMASTER) *	unless overridden from the command line.  This information is hard-coded *	into the <sockets.h> header file. * *  Routines Include: <Spm.c> *    int main( int argc, char **argv) *    static Socket *Sopen_prtmstr() *    static PortTable *makePortTable(SKTEVENT port,char *sharehost) *    static void delPortTable(PortTable *p) *    void pm_server(Socket *client) *    void pm_client(Socket *client) *    void pm_close(Socket *client) *    void pm_quit( Socket *server, Socket *client) *    void pm_table(Socket *client) *    void pm_rmserver(Socket *client) *    int firewall(Socket *skt) *    void firewall_init(char *fwfile) *    void pm_fwinit(Socket *skt) */#include <stdio.h>#include "sockets.h"#include <setjmp.h>#ifdef __WIN32__# include <windows.h>#endif#ifdef unix# include <sys/types.h># include <unistd.h>#endif/* ---------------------------------------------------------------------- * Definitions: */#define SPMFIREWALL		/* select PortMaster firewall code				*/#define BUFSIZE		128	/* size of character buffers					*/#define SPMFWDATA	6	/* SSL PortMaster Firewall data quantity		*/#define TIMEOUT		20L	/* wait no more than 20 seconds at a Sread...	*/# ifdef unix/* #  define CloseStdio */# endif/* ---------------------------------------------------------------------- * Typedefs: */#ifdef SPMFIREWALLtypedef struct spmfw_str    SpmFW;#endiftypedef struct PortTablestr PortTable;/* ---------------------------------------------------------------------- * Data Structures: *//* PortTable: this data structure supports matching host/process name *  to ports */struct PortTablestr {	char      *sktname;		/* name of skt							*/	char      *sharehost;	/* optional Portmaster-sharing hostname	*/	SKTEVENT   port;		/* port of socket						*/	PortTable *nxt,*prv;	/* linked list							*/	};#ifdef SPMFIREWALLstruct spmfw_str {	int    data[SPMFWDATA];	SpmFW *nxt;	};#endif/* ---------------------------------------------------------------------- * Global Data: */static struct sockaddr_in sin;static char       hostname[BUFSIZE];static char       hostaddr[4];static char       sktname[BUFSIZE];static SKTEVENT   ok     = 0;static SKTEVENT   sorry  = 0;static SKTEVENT   resend = 0;static SKTEVENT   okshare= 0;static PortTable *phd    = NULL;static PortTable *ptl    = NULL;static jmp_buf    timedout;#ifdef SPMFIREWALLstatic SpmFW     *spmfwhd=NULL;#endif/* ---------------------------------------------------------------------- * Usage: */static char *usage[]={	XYELLOW,"Spm ",XGREEN,"[",XCYAN,"-f firewallfilename",XGREEN,"]\n\n",		XUWHITE,"Author",XGREEN,": Dr. Charles E. Campbell, Jr.\n\n",	XUWHITE,"Options:\n\n",	XCYAN,"  -f firewallfilename",XGREEN,": optional firewall file\n",		XUWHITE,"Explanation:\n\n",XGREEN,		"The ",XYELLOW,"Spm",XGREEN," is the PortMaster for the Sockets library\n",	"written by Dr. Charles E. Campbell, Jr. and Terry McRoberts of NASA.\n",	"The Spm program provides a \"phonebook\" of server names and their\n",	"associated port identifiers used by the Sopen function.  The data\n",	"is maintained in an internal \"PortTable\" linked list in memory.\n",	"The PortMaster (Spm) must be run on any machine using the Sockets\n",	"library.\n\n",		"The PortMaster is not intended to be used directly by the user.\n",	"Instead, Sopen, Sclose, and Srmsrvr are the primary interfaces to the\n",	"PortMaster for the user.  These functions follow a simple protocol and\n",	"pass PortMaster \"event\"s to and from the PortMaster.\n\n",		"There are some additional functions that the PortMaster provides: one\n",	"may use PortMaster events to close down the PortMaster (PM_QUIT) and\n",	"to query the PortMaster as to what servers are available (PM_TABLE).\n",	"These functions do not have nice interfaces provided; one must be\n",	"conversant with the PortMaster protocol to get them to work.\n\n",	"\n",XUWHITE,"Version",XGREEN,": ",#ifdef unix	"unix",#endif#ifdef vms	"vms",#endif#ifdef msdos	"msdos",#endif	"\n",		"",""};/* ---------------------------------------------------------------------- * Prototypes: */#ifdef __PROTOTYPE__int main( int, char **);                               /* Spm.c           */static Socket *Sopen_prtmstr(void);                    /* Spm.c           */static PortTable *makePortTable(SKTEVENT,char *);      /* Spm.c           */static void delPortTable(PortTable *);                 /* Spm.c           */void pm_server(Socket *,SKTEVENT);                     /* Spm.c           */void pm_client(Socket *);                              /* Spm.c           */void pm_close(Socket *);                               /* Spm.c           */void pm_quit( Socket *, Socket *);                     /* Spm.c           */void pm_table(Socket *);                               /* Spm.c           */void pm_rmserver(Socket *);                            /* Spm.c           */#ifdef SPMFIREWALLint firewall(Socket *);                                /* Spm.c           */void firewall_init(char *);                            /* Spm.c           */void pm_fwinit(Socket *);                              /* Spm.c           */#endif#elseextern int main();                                     /* Spm.c           */static Socket *Sopen_prtmstr();                        /* Spm.c           */static PortTable *makePortTable();                     /* Spm.c           */static void delPortTable();                            /* Spm.c           */extern void pm_server();                               /* Spm.c           */extern void pm_client();                               /* Spm.c           */extern void pm_close();                                /* Spm.c           */extern void pm_quit();                                 /* Spm.c           */extern void pm_table();                                /* Spm.c           */extern void pm_rmserver();                             /* Spm.c           */#ifdef SPMFIREWALLextern int firewall();                                 /* Spm.c           */extern void firewall_init();                           /* Spm.c           */extern void pm_fwinit();                               /* Spm.c           */#endif#endif	/* __PROTOTYPE__ *//* ---------------------------------------------------------------------- *//* main: this is where it starts, ladies and gentlemen! */#ifdef __WIN32__// WinMain: Entry point of all Windows programsint APIENTRY WinMain(  HINSTANCE  hInstance,  HINSTANCE  hPrevInstance,  LPSTR      lpCmdLine,  int        nCmdShow)#else# ifdef __PROTOTYPE__int main(  int    argc,  char **argv)# elseint main(  argc,  argv)int    argc;char **argv;# endif#endif{SKTEVENT        event;Socket         *client     = NULL;Socket         *server     = NULL;int             resend_cnt = 0;struct hostent *he         = NULL;#ifdef unixint daemon=0;int tty_fd;daemon= fork();if(daemon < 0) error(XTDIO_ERROR,"Spm: PortMaster cannot fork");else if(daemon) {	/* we're the parent, so bye-bye! */	/* give out credits */	fprintf(stderr,"\n");	fprintf(stderr,"      *** Simple Sockets PortMaster ***\n");	fprintf(stderr,"   Authors: Charles E. Campbell, Jr., Ph.D.\n");	fprintf(stderr,"               Terry McRoberts\n");	fprintf(stderr,"\n");	fprintf(stderr,"of Goddard Space Flight Center, Maryland, USA\n");	fprintf(stderr,"               (uses port %4d)\n",PORTMASTER);	exit(0);	}setsid();			/* release controlling terminal */#elif defined(__WIN32__)static int  argc      = 1;static char argv[1][4]={"Spm"};#else/* give out credits */fprintf(stderr,"\n");fprintf(stderr,"      *** Simple Sockets PortMaster ***\n");fprintf(stderr,"   Authors: Charles E. Campbell, Jr., Ph.D.\n");fprintf(stderr,"               Terry McRoberts\n");fprintf(stderr,"\n");fprintf(stderr,"of Goddard Space Flight Center, Maryland, USA\n");fprintf(stderr,"               (uses port %4d)\n",PORTMASTER);#endif	/* #if unix .. else if windoz ... endif */rdcolor();				/* read color strings	*/Sinit();				/* initialize sockets	*//* handle command line */if(argc > 1 && !strcmp(argv[1],"?")) {	/* give usage message */	char **u;	for(u= usage; u[0][0] || u[1][0]; ++u) rdcputs(*u,stdout);	exit(0);	}/* initialize */ok     = htons(PM_OK);okshare= htons(PM_OKSHARE);sorry  = htons(PM_SORRY);resend = htons(PM_RESEND);/* get the current hostname */gethostname(hostname,BUFSIZE);#ifdef SPMFIREWALLhe= gethostbyname(hostname); /* get host address */if(he) {	hostaddr[0]= he->h_addr_list[0][0];	hostaddr[1]= he->h_addr_list[0][1];	hostaddr[2]= he->h_addr_list[0][2];	hostaddr[3]= he->h_addr_list[0][3];	if(hostaddr[0] < 0) hostaddr[0]+= 256;	if(hostaddr[1] < 0) hostaddr[1]+= 256;	if(hostaddr[2] < 0) hostaddr[2]+= 256;	if(hostaddr[3] < 0) hostaddr[3]+= 256;	/* initialize firewall: -f <firewallfile>	 *  If no such option, then the "SPMFIREWALL" environment variable	 *  is examined	 */	if(argc > 1 && argv[1][0] == '-' && argv[1][1] == 'f')	  firewall_init(argv[1]+2);	else firewall_init("");	}else hostaddr[0]= hostaddr[1]= hostaddr[2]= hostaddr[3]= '\0';#endif/* open a server for the PortMaster */server= Sopen_prtmstr();if(!server) {	error(XTDIO_ERROR,"%s PortMaster's port (#%d) already in use!!!\n",	  hostname, PORTMASTER);#ifdef vms	exit(1);#else	exit(0);#endif	}#ifdef CloseStdio/* get rid of things we no longer need */fflush(stdin);fflush(stdout);fflush(stderr);fclose(stdin);fclose(stdout);fclose(stderr);#endif/* set up a timeout return point */(void) setjmp(timedout);/* accept clients */while(1) {	/* close out old connection		*/	if(client) {		shutdown(client->skt,2);		close(client->skt);		client->skt= NULL;		freeSocket(client);	/* free client Socket			*/		client= NULL;		/* paranoia is good medicine	*/		}	/* accept a client connection */	client= Saccept(server);	if(!client) {		continue;		}#ifdef SPMFIREWALL	if(firewall(client)) {	/* reject clients not inside firewall */		Swrite(client,(char *) &sorry,sizeof(sorry));		shutdown(client->skt,2);		close(client->skt); client->skt= NULL;		freeSocket(client); client     = NULL;		continue;		}#endif	/* SPMFIREWALL */	/* get a PrtMstrEvent */	resend_cnt= 0;	do {		/* get the event that PortMaster is to handle */		if(Stimeoutwait(client,TIMEOUT,0L) < 0) longjmp(timedout,1);		Sreadbytes(client,(char *) &event,sizeof(event));		event= ntohs( event);	/* The PortMaster handles several events: /===============================================\ |            Client        PortMaster           | | Event      Sends         Sends                | |===============================================| | PM_SERVER                PM_OK / PM_RESEND    | |            sktname                            | |            port                               | |                          PM_OK / PM_SORRY     | |-----------------------------------------------| | PM_CLIENT                                     | |                          PM_OK / PM_RESEND    | |            sktname                            | |                          PM_OK / PM_SORRY     | |                          port                 | |-----------------------------------------------| | PM_CLOSE                                      | |                          PM_OK / PM_RESEND    | |           port                                | |                          PM_OK / PM_SORRY     | |-----------------------------------------------| | PM_TABLE                                      | |                          PM_OK / PM_RESEND    | |                          count of servers     | |                          "server : port#"     | |-----------------------------------------------| | PM_QUIT                                       | |                          PM_OK / PM_RESEND    | |           "PortMaster"                        | |-----------------------------------------------| | PM_FWINIT                                     | |                          PM_OK / PM_RESEND    | |-----------------------------------------------| | PM_SHARE                 PM_OK / PM_RESEND    |  Supports new portmaster |           hostname                            |  sharing mode.  Now, a |           sktname                             |  single Portmaster can support |           port                                |  a number of different machines. |                          PM_OK / PM_SORRY     |  The main reason for this is to |-----------------------------------------------|  support PC-only shops, but it | PM_CLIENT                                     |  will work with any PortMaster. |                          PM_OK / PM_RESEND    | |           sktname                             | |                          PM_OKSHARE / PM_SORRY| |                          hostname             | |                          port                 | \===============================================/ */		switch(event) {			case PM_SERVER:	/* enter port into database */		case PM_SHARE:	/* enter hostname & port into database */			pm_server(client,event);			resend_cnt= 0;			break;			case PM_CLIENT:	/* return port from database */			pm_client(client);			resend_cnt= 0;			break;			case PM_CLOSE:	/* delete port from database */			pm_close(client);			resend_cnt= 0;			break;		case PM_QUIT:	/* this function terminates the PortMaster */			pm_quit(server,client);			resend_cnt= 0;			break;			case PM_TABLE:	/* print out the PortTable */			pm_table(client);			resend_cnt= 0;			break;		case PM_RMSERVER:	/* remove a server entry from the PortMaster */			pm_rmserver(client);			resend_cnt= 0;			break;#ifdef SPMFIREWALL		case PM_FWINIT:		/* re-read firewall file */			pm_fwinit(client);			resend_cnt= 0;			break;#endif		default:		/* huh?  whaddaIdonow?	*/			Swrite(client,(char *) &resend,sizeof(resend));			/* terminate resending after PM_MAXTRY attempts */			if(++resend_cnt > PM_MAXTRY) {				resend_cnt= 0;				shutdown(client->skt,2);				close(client->skt); client->skt= NULL;				freeSocket(client); client     = NULL;				}			break;			}		} while(resend_cnt);	}}/* ---------------------------------------------------------------------- *//* Sopen_prtmstr: this function opens a socket handle for the Portmaster */static Socket *Sopen_prtmstr(){int     length;int     status=1;Socket *skt;/* allocate a Socket */skt= makeSocket(hostname,"PortMaster",PM_SERVER);/*	create a socket      */if((skt->skt= socket(AF_INET, SOCK_STREAM, 0)) <0 ) {	freeSocket(skt); skt= NULL;	return skt;	}#ifndef SSLNOSETSOCKOPT/* allow PortMaster to be brought back up quickly (this should seldom be necessary!) */status= 1;if(setsockopt(skt->skt,SOL_SOCKET,SO_REUSEADDR,(char *) &status,sizeof(status)) < 0) {	}#endif/*	initialize socket data structure     */sin.sin_family      = AF_INET;sin.sin_addr.s_addr = INADDR_ANY;sin.sin_port        = htons((u_short) PORTMASTER);/*	bind socket data structure to this socket     */if(bind(skt->skt,(struct sockaddr *) &sin,sizeof(sin))) {	freeSocket(skt); skt= NULL;	return skt;	}/* getsockname fills in the socket structure with information,

⌨️ 快捷键说明

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