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

📄 gateway.cc

📁 EPICS CA gateway, base on channel access protocol
💻 CC
📖 第 1 页 / 共 3 页
字号:
		fprintf(stderr,"\tinactive=%ld\n",gr->inactiveTimeout());		fprintf(stderr,"\tmask=%s\n",gr->eventMaskString());#ifndef WIN32		fprintf(stderr,"\tuser id=%ld\n",(long)getuid());		fprintf(stderr,"\tgroup id=%ld\n",(long)getgid());#endif		if(gr->isReadOnly())			fprintf(stderr,"\tread only mode\n");		fprintf(stderr,"  (The default filenames depend on which "		  "files exist in home)\n");		return -1;	}		// Change to the specified home directory	if(home_dir)	{		if(chdir(home_dir)<0)		{			perror("Change to home directory failed");			fprintf(stderr,"-->Bad home <%s>\n",home_dir); fflush(stderr);			return -1;		}	}	getcwd(home_directory,HOME_DIR_SIZE);	// Get the default resources. The values of access_file,	// pvlist_file, command_file, putlog_file, and report_file depend	// on whether the default filenames exist in the cwd.	global_resources = new gateResources;	gateResources* gr = global_resources;	// Set command-line values, order is somewhat important	if(level)				gr->setDebugLevel(level);	if(read_only)			gr->setReadOnly();	if(mask)				gr->setEventMask(mask);	if(connect_tout>=0)		gr->setConnectTimeout(connect_tout);	if(inactive_tout>=0)	gr->setInactiveTimeout(inactive_tout);	if(dead_tout>=0)		gr->setDeadTimeout(dead_tout);	if(disconnect_tout>=0)	gr->setDisconnectTimeout(disconnect_tout);	if(reconnect_tinhib>=0)	gr->setReconnectInhibit(reconnect_tinhib);	if(access_file)			gr->setAccessFile(access_file);	if(pvlist_file)			gr->setListFile(pvlist_file);	if(command_file)		gr->setCommandFile(command_file);	if(putlog_file)	    	gr->setPutlogFile(putlog_file);	if(report_file)	    	gr->setReportFile(report_file);#ifndef WIN32	gr->setServerMode(make_server);#endif#ifndef WIN32	if(make_server)	{		// Start watcher process		if(manage_gateway()) return 0;	}	else	{		parent_pid=getpid();	}#endif	// *******************************************	// gets here if this is an interactive gateway	// *******************************************	// Change stderr and stdout to the log file	if(log_file || make_server)	{		if(log_file==NULL) log_file=GATE_LOG_FILE;		time(&t);#ifndef WIN32		char *logerror=NULL;		char *putlogerror=NULL;		// Save log file if it exists		if(stat(log_file,&sbuf)==0)		{			if(sbuf.st_size>0)			{				sprintf(logSaveFile,"%s.%lu",log_file,(unsigned long)t);				if(link(log_file,logSaveFile)<0)				{					fprintf(stderr,"%s Failed to move old log to %s\n",						timeStamp(),logSaveFile);					char *error=strerror(errno);					if(error && *error) {						logerror=(char *)malloc(strlen(error)+1);						if(logerror) {							strcpy(logerror,error);							fprintf(stderr,"  Reason: %s\n",logerror);						}					}				}				else					unlink(log_file);			}		}		// Save putlog file if it exists		if(stat(putlog_file,&sbuf)==0)		{			if(sbuf.st_size>0)			{				sprintf(putlogSaveFile,"%s.%lu",putlog_file,(unsigned long)t);				if(link(putlog_file,putlogSaveFile)<0)				{					fprintf(stderr,"%s Failed to move old putlog to %s\n",						timeStamp(),putlogSaveFile);					char *error=strerror(errno);					if(error && *error) {						putlogerror=(char *)malloc(strlen(error)+1);						if(putlogerror) {							strcpy(putlogerror,error);							fprintf(stderr,"  Reason: %s\n",putlogerror);						}					}				}				else					unlink(putlog_file);			}		}#endif		// Redirect stdout and stderr		// Open it and close it to empty it (Necessary on WIN32,		// apparently not necessary on Solaris)		FILE *fp=fopen(log_file,"w");		if(fp == NULL) {			fprintf(stderr,"Cannot open %s\n",log_file);			fflush(stderr);		} else {			fclose(fp);		}		// KE: This was formerly "w" instead of "a" and stderr was		//  overwriting the top of the log file		if((freopen(log_file,"a",stderr))==NULL ) {			fprintf(stderr,"Redirect of stderr to file %s failed\n",log_file);			fflush(stderr);		}		if((freopen(log_file,"a",stdout))==NULL ) {			fprintf(stderr,"Redirect of stdout to file %s failed\n",log_file);			fflush(stderr);		}#ifndef WIN32		// Repeat error messages to log		if(logerror) {			fprintf(stderr,"%s Failed to move old log to %s\n",			  timeStamp(),logSaveFile);			if(logerror) {				fprintf(stderr,"  Reason: %s\n",logerror);				fflush(stderr);				free(logerror);			}		}		if(putlogerror) {			fprintf(stderr,"%s Failed to move old putlog to %s\n",			  timeStamp(),putlogSaveFile);			if(putlogerror) {				fprintf(stderr,"  Reason: %s\n",putlogerror);				fflush(stderr);				free(putlogerror);			}		}#endif	}	else	{		log_file="<terminal>";	}	gr->setUpAccessSecurity();	if(gr->debugLevel()>10)	{		fprintf(stderr,"\noption dump:\n");		fprintf(stderr," home = <%s>\n",home_directory);		fprintf(stderr," log file = <%s>\n",log_file);		fprintf(stderr," access file = <%s>\n",gr->accessFile());		fprintf(stderr," list file = <%s>\n",gr->listFile());		fprintf(stderr," command file = <%s>\n",gr->commandFile());		fprintf(stderr," putlog file = <%s>\n",gr->putlogFile());		fprintf(stderr," report file = <%s>\n",gr->reportFile());		fprintf(stderr," debug level = %d\n",gr->debugLevel());		fprintf(stderr," connect timeout = %ld\n",gr->connectTimeout());		fprintf(stderr," disconnect timeout = %ld\n",gr->disconnectTimeout());		fprintf(stderr," reconnect inhibit time = %ld\n",gr->reconnectInhibit());		fprintf(stderr," inactive timeout = %ld\n",gr->inactiveTimeout());		fprintf(stderr," dead timeout = %ld\n",gr->deadTimeout());		fprintf(stderr," event mask = %s\n",gr->eventMaskString());#ifndef WIN32		fprintf(stderr," user id= %ld\n",(long)getuid());		fprintf(stderr," group id= %ld\n",(long)getgid());#endif		if(gr->isReadOnly()) {			fprintf(stderr," read only mode\n");		}		fflush(stderr);	}	// Open putlog file.  This could be done the first time it is	// used, but we want to open it and keep it open because of	// possible problems with FOPEN_MAX.	if(putlog_file)	{		FILE *fp=fopen(putlog_file,"w");		if(fp == NULL) {			fprintf(stderr,"Cannot open %s\n",putlog_file);			fflush(stderr);		}		gr->setPutlogFp(fp);	}		startEverything(stat_prefix);	delete global_resources;	return 0;}static void stopEverything(void){	if(server) {		// Set the flag and let it stop itself.  This will cause it to		// clean up.  Setting quit_flag to 2 keeps it from printing a		// message in the main loop.		server->setQuitFlag(2u);	} else {		exit(0);	}}#define pr fprintfstatic void print_instructions(void){	pr(stderr,"-debug value: Enter value between 0-100.  50 gives lots of\n");	pr(stderr," info, 1 gives small amount.\n\n");		pr(stderr,"-pvlist file_name: Name of file with all the allowed PVs in it\n");	pr(stderr," See the sample file gateway.pvlist in the source distribution\n");	pr(stderr," for a description of how to create this file.\n");		pr(stderr,"-access file_name: Name of file with all the EPICS access\n");	pr(stderr," security rules in it.  PVs in the pvlist file use groups\n");	pr(stderr," and rules defined in this file.\n");		pr(stderr,"-log file_name: Name of file where all messages from the\n");	pr(stderr," gateway go, including stderr and stdout.\n\n");		pr(stderr,"-command file_name: Name of file where gateway command(s) go\n");	pr(stderr," Commands are executed when a USR1 signal is sent to gateway.\n\n");		pr(stderr,"-putlog file_name: Name of file where gateway put logging goes.\n");	pr(stderr," Put logging is specified with TRAPWRITE in the access file.\n\n");		pr(stderr,"-report file_name: Name of file where gateway reports go.\n");	pr(stderr," Reports are appended to this file if it exists.\n\n");		pr(stderr,"-home directory: Home directory where all your gateway\n");	pr(stderr," configuration files are kept where log and command files go.\n\n");		pr(stderr,"-sip IP_address: IP address that gateway's CA server listens\n");	pr(stderr," for PV requests.  Sets env variable EPICS_CAS_INTF_ADDR.\n\n");		pr(stderr,"-signore IP_address_list: IP address that gateway's CA server\n");	pr(stderr," ignores.  Sets env variable EPICS_CAS_IGNORE_ADDR_LIST.\n\n");		pr(stderr,"-cip IP_address_list: IP address list that the gateway's CA\n");	pr(stderr," client uses to find the real PVs.  See CA reference manual.\n");	pr(stderr," This sets environment variables EPICS_CA_AUTO_LIST=NO and\n");	pr(stderr," EPICS_CA_ADDR_LIST.\n\n");		pr(stderr,"-sport CA_server_port: The port which the gateway's CA server\n");	pr(stderr," uses to listen for PV requests.  Sets environment variable\n");	pr(stderr," EPICS_CAS_SERVER_PORT.\n\n");		pr(stderr,"-cport CA_client_port:  The port which the gateway's CA client\n");	pr(stderr," uses to find the real PVs.  Sets environment variable\n");	pr(stderr," EPICS_CA_SERVER_PORT.\n\n");		pr(stderr,"-connect_timeout seconds: The amount of time that the\n");	pr(stderr," gateway will allow a PV search to continue before marking the\n");	pr(stderr," PV as being not found.\n\n");		pr(stderr,"-inactive_timeout seconds: The amount of time that the gateway\n");	pr(stderr," will hold the real connection to an unused PV.  If no gateway\n");	pr(stderr," clients are using the PV, the real connection will still be\n");	pr(stderr," held for this long.\n\n");		pr(stderr,"-dead_timeout seconds:  The amount of time that the gateway\n");	pr(stderr," will hold requests for PVs that are not found on the real\n");	pr(stderr," network that the gateway is using.  Even if a client's\n");	pr(stderr," requested PV is not found on the real network, the gateway\n");	pr(stderr," marks the PV dead, holds the request and continues trying\n");	pr(stderr," to connect for this long.\n\n");		pr(stderr,"-disconnect_timeout seconds:  The amount of time that the gateway\n");	pr(stderr," will hold requests for PVs that were connected but have been\n");	pr(stderr," disconnected. When a disconnected PV reconnects, the gateway will\n");	pr(stderr," broadcast a beacon signal to inform the clients that they may\n");	pr(stderr," reconnect to the gateway.\n\n");	pr(stderr,"-reconnect_inhibit seconds:  The minimum amount of time between\n");	pr(stderr," additional beacons that the gateway will send to its clients\n");	pr(stderr," when channels from the real network reconnect.\n\n");	pr(stderr,"-server: Start as server. Detach from controlling terminal\n");	pr(stderr," and start a daemon that watches the gateway and automatically\n");	pr(stderr," restarts it if it dies.\n");		pr(stderr,"-mask event_mask: Event mask that is used for connections on the\n");	pr(stderr," real network: use any combination of v (value), a (alarm), l (log).\n");	pr(stderr," Default is va (forward value and alarm change events).\n");		pr(stderr,"-prefix string: Set the prefix for the gateway statistics PVs.\n");	pr(stderr," Defaults to the hostname the gateway is running on.\n");		pr(stderr,"-uid number: Run the server with this id, server does a\n");	pr(stderr," setuid(2) to this user id number.\n\n");	pr(stderr,"-gid number: Run the server with this id, server does a\n");	pr(stderr," setgid(2) to this group id number.\n\n");}#ifndef WIN32// -------------------------------------------------------------------//  part that watches the gateway process and ensures that it stays upstatic int manage_gateway(void){	time_t t,prevt=0;	int rc;	int i;	// Initialize time array	for(i=0; i < NRESTARTS; i++) {		startTime[i]=0;	}	save_chld=signal(SIGCHLD,sig_chld);	save_hup=signal(SIGHUP,sig_stop);	save_term=signal(SIGTERM,sig_stop);	save_int=signal(SIGINT,sig_stop);		// Fork.  Parent will exit, child will be a session leader	pid_t pid=fork();	switch(pid)	{	case -1:		// Error		perror("Cannot create gateway processes");		return -1;  // Will cause main to return 0;	case 0:		// Child		// Make this process a session leader		// KE: Not sure why this is necessary		// Used to use setgrp() for UNIX, else setgrp(0,0)		//   but this failed for Darwin		setpgid(0,0);		// Make a new session		setsid();		break;	default:		// Parent		return 1;  // Will cause main to return 0;	}		parent_pid=getpid();		// 	do {		// Don't allow runaway restarts		time(&t);		if(nStart < NRESTARTS) {			startTime[nStart]=t;			nStart++;		} else {			// Check the interval since NRESTARTSth previous start			if(t-startTime[0] < RESTART_INTERVAL) {				// Too many recent starts				fprintf(stderr,				  "\nGateway: There were too many [%d] restarts in the last %d seconds\n",				  NRESTARTS+1,RESTART_INTERVAL);				fprintf(stderr,"Aborting Gateway ServerPID %d\n",(int)parent_pid);				exit(1);			} else {				// Reset the start times				for(i=0; i < NRESTARTS-1; i++) {					startTime[i]=startTime[i+1];				}				nStart=NRESTARTS;				startTime[NRESTARTS-1]=t;			}		}				// Don't respawn faster than every RESTART_DELAY seconds		if((t-prevt) < RESTART_DELAY) sleep(RESTART_DELAY);		prevt=t;		// Fork.  Parent will be the server and child will be the		// gateway.  Parent will pause until receiving a signal that is		// handled by sig_stop, which sets death_flag to 1.		switch(gate_pid=fork())	{		case -1:			// Error			perror("Cannot create gateway processes");			gate_pid=0;			break;		case 0:			// Child			break;		default:			// Pause until we receive a signal.  If the signal is HUP,			// TERM, or INT (handled by sig_stop), then death_flag is			// set to 1 andc the server exits.  If it is SIG_CHLD,			// then a new fork occurs after executing sig_chld, which			// waits for all information to come in.  Note that any			// other non-ignored signal will end the pause and fork a			// new gateway, if there are any.			pause();			break;		}	} while(gate_pid && death_flag==0);		if(death_flag || gate_pid==-1) rc=1;	else rc=0;	return rc;}#endif //#ifdef WIN32static int setEnv(const char *var, const char *val, char **envString){	int len=strlen(var)+strlen(val)+2;	*envString=(char *)malloc(len);	if(!*envString) {		fprintf(stderr,"Memory allocation error for %s",var);		return 1;	}	sprintf(*envString,"%s=%s",var,val);#if 0	// There is no putenv on Linux	int status=putenv(*envString);	if(status) {		fprintf(stderr,"putenv failed for:\n  %s\n",*envString);	}#else	epicsEnvSet(var,val);#endif	return 0;}static int setEnv(const char *var, int ival, char **envString){	// Allow 40 for size of ival	int len=strlen(var)+40+2;	*envString=(char *)malloc(len);	if(!*envString) {		fprintf(stderr,"Memory allocation error for %s",var);		return 1;	}	sprintf(*envString,"%s=%d",var,ival);#if 0	// There is no putenv on Linux	int status=putenv(*envString);	if(status) {		fprintf(stderr,"putenv failed for:\n  %s\n",*envString);	}#else	char *pVal=strchr(*envString,'=');	if(!pVal || !(pVal+1)) {		epicsEnvSet(var,"");	} else {		epicsEnvSet(var,pVal+1);	}#endif	return 0;}void printRecentHistory(void){#ifndef WIN32	int nStarts=0;	int i;	if(nStart < 1) return;	for(i=0; i < nStart-1; i++) {		if((startTime[nStart-1]-startTime[i]) < RESTART_INTERVAL) {			nStarts++;		}	}	if(nStarts) {		fflush(stderr);		printf("There have been %d restarts for serverPID %d "		  "in the last %d seconds\n",		  nStarts+1,parent_pid,RESTART_INTERVAL);		printf("  Only %d restarts are allowed in this interval\n",NRESTARTS);		fflush(stdout);	}#endif}static void printEnv(FILE *fp, const char *var){	if(!fp || !var) return;		char *value=getenv(var);	fprintf(fp,"%s=%s\n", var, value?value:"Not specified");}/* **************************** Emacs Editing Sequences ***************** *//* Local Variables: *//* tab-width: 4 *//* c-basic-offset: 4 *//* c-comment-only-line-offset: 0 *//* c-file-offsets: ((substatement-open . 0) (label . 0)) *//* End: */

⌨️ 快捷键说明

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