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

📄 gateway.cc

📁 EPICS CA gateway, base on channel access protocol
💻 CC
📖 第 1 页 / 共 3 页
字号:
/*************************************************************************\* Copyright (c) 2002 The University of Chicago, as Operator of Argonne* National Laboratory.* Copyright (c) 2002 Berliner Speicherring-Gesellschaft fuer Synchrotron-* Strahlung mbH (BESSY).* Copyright (c) 2002 The Regents of the University of California, as* Operator of Los Alamos National Laboratory.* This file is distributed subject to a Software License Agreement found* in the file LICENSE that is included with this distribution. \*************************************************************************/// Author: Jim Kowalkowski// Date: 2/96#define DEBUG_ENV 0#define DEBUG_OPENFILES 0// Use this to truncate the core file if GATEWAY_CORE_SIZE is// specified in the environment.  (Truncating makes it unusable so// consider truncation to 0 if anything.)#define TRUNC_CORE_FILE 1#define NRESTARTS 10#define RESTART_INTERVAL 10*60  // sec#define RESTART_DELAY 10        // sec#if DEBUG_OPENFILES#include <limits.h>#include <unistd.h>#endif#include <stdio.h>#include <string.h>#include <fcntl.h>#include <stdlib.h>#ifdef USE_SYSLOG#include <syslog.h>#endif#include <signal.h>#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#ifdef WIN32# include <direct.h># include <process.h># define WIN32_MAXSTDIO 2048#else# include <sys/wait.h># include <unistd.h># include <sys/resource.h>#endif#include <envDefs.h>#include <osiProcess.h>#include <gdd.h>#include <epicsVersion.h>#include "gateResources.h"#include "gateServer.h"// Function Prototypesstatic int startEverything(char *prefix);static void stopEverything(void);static void print_instructions(void);static int manage_gateway(void);static int setEnv(const char *var, const char *val, char **envString);static int setEnv(const char *var, const int ival, char **envString);static void printEnv(FILE *fp, const char *var);// Global variables#ifndef WIN32static pid_t gate_pid;#endifstatic int death_flag=0;static int nStart=0;static time_t startTime[NRESTARTS];static gateServer *server=NULL;// still need to add client and server IP addr info using // the CA environment variables.// still need to add ability to load and run user servers dynamically#if 0void* operator new(size_t x){	void* y = (void*)malloc(x);	fprintf(stderr,"in op new for %d %8.8x\n",(int)x,y);	return y;}void operator delete(void* x){	fprintf(stderr,"in op del for %8.8x\n",x);	free((char*)x);}#endif// The parameters passed in from the user are://	-debug ? = set debug level, ? is the integer level to set//	-pvlist file_name = process variable list file//	-log//	-access file_name = access security file//	-command file_name = USR1 command list file//	-putlog file_name = putlog file//	-report file_name = report file//	-home directory = the program's home directory//	-connect_timeout number = clear PV connect requests every number seconds//	-inactive_timeout number = Hold inactive PV connections for number seconds//	-dead_timeout number = Hold PV connections with no user for number seconds//	-cip ip_addr_list = CA client library IP address list (exclusive)//	-sip ip_addr = IP address where CAS listens for requests//	-signore ip_addr_list = IP address CAS ignores//	-cport port_number = CA client library port//	-sport port_number = CAS port number//	-ro = read only server, no puts allowed//	-? = display usage////	GATEWAY_HOME = environment variable pointing to the home of the gateway//// Defaults://	Home directory = .//	Access security file = gateway.access//	process variable list file = gateway.pvlist//	USR1 command list file = gateway.command//	putlog file = gateway.putlog//	report file = gateway.report//	log file = gateway.log//	debug level = 0 (none)//  connect_timeout = 1 second//  inactive_timeout = 60*60*2 seconds (2 hours)//  dead_timeout = 60*2 seconds (2 minutes)//	cport/sport = CA default port number//	cip = nothing, the normal interface//	sip = nothing, the normal interface//// Precedence://	(1) Command line parameter //	(2) environment variables//	(3) defaults#define PARM_DEBUG             0#define PARM_PVLIST            1#define PARM_LOG               2#define PARM_ACCESS            3#define PARM_HOME              4#define PARM_COMMAND           5#define PARM_PUTLOG            6#define PARM_REPORT            7#define PARM_CONNECT           8#define PARM_INACTIVE          9#define PARM_DEAD             10#define PARM_USAGE            11#define PARM_SERVER_IP        12#define PARM_CLIENT_IP        13#define PARM_SERVER_PORT      14#define PARM_CLIENT_PORT      15#define PARM_HELP             16#define PARM_SERVER           17#define PARM_RO               18#define PARM_UID              19#define PARM_PREFIX           20#define PARM_GID              21#define PARM_RECONNECT        22#define PARM_DISCONNECT       23#define PARM_MASK             24#define PARM_SERVER_IGNORE_IP 25#define HOME_DIR_SIZE    300static char *gate_ca_auto_list=NULL;static char *server_ip_addr=NULL;static char *server_ignore_ip_addr=NULL;static char *client_ip_addr=NULL;static int server_port=0;static int client_port=0;static int make_server=0;static char *home_directory;static const char *log_file=NULL;static const char *putlog_file=NULL;static const char *report_file=NULL;#ifndef WIN32static pid_t parent_pid;#endifstruct parm_stuff{	const char* parm;	int len;	int id;	const char* desc;};typedef struct parm_stuff PARM_STUFF;// Second parameter is length of first not including nullstatic PARM_STUFF ptable[] = {    { "-debug",               6, PARM_DEBUG,       "value" },    { "-log",                 4, PARM_LOG,         "file_name" },    { "-pvlist",              7, PARM_PVLIST,      "file_name" },    { "-access",              7, PARM_ACCESS,      "file_name" },    { "-command",             8, PARM_COMMAND,     "file_name" },    { "-putlog",              7, PARM_PUTLOG,      "file_name" },    { "-report",              7, PARM_REPORT,      "file_name" },    { "-home",                5, PARM_HOME,        "directory" },    { "-sip",                 4, PARM_SERVER_IP,   "IP_address" },    { "-cip",                 4, PARM_CLIENT_IP,   "IP_address_list" },    { "-signore",             8, PARM_SERVER_IGNORE_IP, "IP_address_list" },    { "-sport",               6, PARM_SERVER_PORT, "CA_server_port" },    { "-cport",               6, PARM_CLIENT_PORT, "CA_client_port" },    { "-connect_timeout",    16, PARM_CONNECT,     "seconds" },    { "-inactive_timeout",   17, PARM_INACTIVE,    "seconds" },    { "-dead_timeout",       13, PARM_DEAD,        "seconds" },    { "-disconnect_timeout", 19, PARM_DISCONNECT,  "seconds" },    { "-reconnect_inhibit",  18, PARM_RECONNECT,   "seconds" },    { "-server",              9, PARM_SERVER,      "(start as server)" },    { "-uid",                 4, PARM_UID,         "user_id_number" },    { "-gid",                 4, PARM_GID,         "group_id_number" },    { "-ro",                  3, PARM_RO,          NULL },    { "-prefix",              7, PARM_PREFIX,      "statistics_prefix" },    { "-mask",                5, PARM_MASK,        "event_mask" },    { "-help",                5, PARM_HELP,        NULL },    { NULL,                  -1, -1,               NULL }};extern "C" {typedef void (*SIG_FUNC)(int);static SIG_FUNC save_hup = NULL;static SIG_FUNC save_int = NULL;static SIG_FUNC save_term = NULL;static SIG_FUNC save_bus = NULL;static SIG_FUNC save_ill = NULL;static SIG_FUNC save_segv = NULL;static SIG_FUNC save_chld = NULL;static void sig_end(int sig){	fflush(stdout);	fflush(stderr);		switch(sig)	{#ifndef WIN32	case SIGHUP:#ifdef USE_SYSLOG		syslog(LOG_NOTICE|LOG_DAEMON,"PV Gateway Ending (SIGHUP)");#endif		fprintf(stderr,"%s PV Gateway Ending (SIGHUP)\n",		  timeStamp());		if(save_hup) save_hup(sig);		break;#endif //#ifndef WIN32	case SIGTERM:#ifdef USE_SYSLOG		syslog(LOG_NOTICE|LOG_DAEMON,"PV Gateway Ending (SIGTERM)");#endif		fprintf(stderr,"%s PV Gateway Ending (SIGTERM)\n",		  timeStamp());		if(save_term) save_term(sig);		break;	case SIGINT:#ifdef USE_SYSLOG		syslog(LOG_NOTICE|LOG_DAEMON,"PV Gateway Ending (SIGINT)");#endif		fprintf(stderr,"%s PV Gateway Ending (SIGINT)\n",		  timeStamp());		if(save_int) save_int(sig);		break;	case SIGILL:#ifdef USE_SYSLOG		syslog(LOG_NOTICE|LOG_DAEMON,"PV Gateway Aborting (SIGILL)");#endif		fprintf(stderr,"PV Gateway Aborting (SIGILL)\n");		if(save_ill) save_ill(sig);		abort();#ifndef WIN32	case SIGBUS:#ifdef USE_SYSLOG		syslog(LOG_NOTICE|LOG_DAEMON,"PV Gateway Aborting (SIGBUS)");#endif		fprintf(stderr,"%s PV Gateway Aborting (SIGBUS)\n",		  timeStamp());		if(save_bus) save_bus(sig);		abort();#endif //#ifndef WIN32	case SIGSEGV:#ifdef USE_SYSLOG		syslog(LOG_NOTICE|LOG_DAEMON,"PV Gateway Aborting (SIGSEGV)");#endif		fprintf(stderr,"%s PV Gateway Aborting (SIGSEGV)\n",		  timeStamp());		if(save_segv) save_segv(sig);		abort();	default:#ifdef USE_SYSLOG		syslog(LOG_NOTICE|LOG_DAEMON,"PV Gateway Exiting (Unknown Signal)");#endif		fprintf(stderr,"%s PV Gateway Exiting (Unknown Signal)\n",		  timeStamp());		break;	}		// Have it stop itself if possible by setting the quit_flag	stopEverything();}#ifndef WIN32static void sig_chld(int /*sig*/){#ifdef SOLARIS	while(waitpid(-1,NULL,WNOHANG)>0);#else	while(wait3(NULL,WNOHANG,NULL)>0);#endif	signal(SIGCHLD,sig_chld);}#endif //#ifndef WIN32#ifndef WIN32static void sig_stop(int /*sig*/){	if(gate_pid)	  kill(gate_pid,SIGTERM);		death_flag=1;}#endif} // End extern "C"static int startEverything(char *prefix){	char *gate_cas_port=NULL;	char *gate_cas_addr=NULL;	char *gate_cas_ignore_addr=NULL;	char *gate_ca_list=NULL;	char *gate_ca_port=NULL;	int sid;#ifndef WIN32	FILE* fp;	struct rlimit lim;#endif	if(client_ip_addr) {		int status=setEnv("EPICS_CA_ADDR_LIST",client_ip_addr,		  &gate_ca_list);		// In addition, make EPICS_CA_AUTO_LIST=NO to avoid sending		// search requests to ourself.  Note that if		// EPICS_CA_ADDR_LIST is specified instead of -cip, then		// EPICS_CA_AUTO_ADDR_LIST=NO must be set also as this branch		// will not be taken.		status=setEnv("EPICS_CA_AUTO_ADDR_LIST","NO",&gate_ca_auto_list);		gateDebug1(15,"gateway setting <%s>\n",gate_ca_auto_list);		gateDebug1(15,"gateway setting <%s>\n",gate_ca_list);	}	if(server_ip_addr) {		setEnv("EPICS_CAS_INTF_ADDR_LIST",server_ip_addr,		  &gate_cas_addr);		gateDebug1(15,"gateway setting <%s>\n",gate_cas_addr);	}	if(server_ignore_ip_addr) {		setEnv("EPICS_CAS_IGNORE_ADDR_LIST",server_ignore_ip_addr,		  &gate_cas_ignore_addr);		gateDebug1(15,"gateway setting <%s>\n",gate_cas_ignore_addr);	}	if(client_port) {		setEnv("EPICS_CA_SERVER_PORT",client_port,		  &gate_ca_port);		gateDebug1(15,"gateway setting <%s>\n",gate_ca_port);	}	if(server_port) {		setEnv("EPICS_CAS_SERVER_PORT",server_port,		  &gate_cas_port);		gateDebug1(15,"gateway setting <%s>\n",gate_cas_port);	}	sid=getpid();#ifdef RESERVE_FOPEN_FD	// Open a dummy file to keep a file descriptor open to use for	// fopen to avoid its limit of 256 on Solaris	if(!global_resources->openReserveFile()) {		fprintf(stderr,"Opening reserve file failed: %s\n",		  GATE_RESERVE_FILE);	}#endif	#ifndef WIN32	// Make script file ("gateway.killer" by default)	errno=0;	if((fp=fopen(GATE_SCRIPT_FILE,"w"))==(FILE*)NULL) {		fprintf(stderr,"Opening script file failed: %s\n",		  GATE_SCRIPT_FILE);		fflush(stderr);		perror("Reason");		fflush(stderr);		fp=stderr;	}	fprintf(fp,"\n");	fprintf(fp,"# options:\n");	fprintf(fp,"# home=<%s>\n",home_directory);	fprintf(fp,"# log file=<%s>\n",log_file);	fprintf(fp,"# access file=<%s>\n",global_resources->accessFile());	fprintf(fp,"# pvlist file=<%s>\n",global_resources->listFile());	fprintf(fp,"# command file=<%s>\n",global_resources->commandFile());	fprintf(fp,"# putlog file=<%s>\n",global_resources->putlogFile());	fprintf(fp,"# report file=<%s>\n",global_resources->reportFile());	fprintf(fp,"# debug level=%d\n",global_resources->debugLevel());	fprintf(fp,"# dead timeout=%ld\n",global_resources->deadTimeout());	fprintf(fp,"# connect timeout=%ld\n",global_resources->connectTimeout());	fprintf(fp,"# disconnect timeout=%ld\n",global_resources->disconnectTimeout());	fprintf(fp,"# reconnect inhibit time=%ld\n",global_resources->reconnectInhibit());	fprintf(fp,"# inactive timeout=%ld\n",global_resources->inactiveTimeout());	fprintf(fp,"# event mask=%s\n",global_resources->eventMaskString());	fprintf(fp,"# user id=%ld\n",(long)getuid());	fprintf(fp,"# group id=%ld\n",(long)getgid());	// Print command-line arguments	fprintf(fp,"# \n");	fprintf(fp,"# environment set from command line:\n");	if(client_ip_addr) {		fprintf(fp,"# %s\n",gate_ca_list);		fprintf(fp,"# %s\n",gate_ca_auto_list);	}	if(server_ip_addr) fprintf(fp,"# %s\n",gate_cas_addr);	if(server_ignore_ip_addr) fprintf(fp,"# %s\n",gate_cas_ignore_addr);	if(client_port) fprintf(fp,"# %s\n",gate_ca_port);	if(server_port) fprintf(fp,"# %s\n",gate_cas_port);	// Print kill information	fprintf(fp,"# \n");	fprintf(fp,"# use the following to execute commands in command file:\n");	fprintf(fp,"#    kill -USR1 %d\n",sid);	fprintf(fp,"# use the following to get a PV summary report in the log:\n");	fprintf(fp,"#    kill -USR2 %d\n",sid);	fprintf(fp,"# \n");	if(global_resources->isReadOnly()) {		fprintf(fp,"# Gateway running in read-only mode.\n");	}	fprintf(fp,"\n kill %ld # to kill everything\n\n",(long)parent_pid);	fprintf(fp,"\n # kill %u # to kill off this gateway\n\n",sid);	fflush(fp);		if(fp!=stderr) fclose(fp);	chmod(GATE_SCRIPT_FILE,00755);#endif  //#ifndef WIN32	#ifndef WIN32	// Make script file ("gateway.restart" by default)	errno=0;	if((fp=fopen(GATE_RESTART_FILE,"w"))==(FILE*)NULL) {		fprintf(stderr,"Opening restart file failed: %s\n",		  GATE_RESTART_FILE);		fflush(stderr);		perror("Reason");		fflush(stderr);		fp=stderr;	}		fprintf(fp,"\n kill %d # to kill off this gateway\n\n",sid);	fflush(fp);		if(fp!=stderr) fclose(fp);	chmod(GATE_RESTART_FILE,00755);#endif  //#ifndef WIN32		// Increase process limits to max#ifdef WIN32	// Set open file limit (512 by default, 2048 is max)# if DEBUG_OPENFILES    int maxstdio=_getmaxstdio();    printf("Permitted open files: %d\n",maxstdio);    printf("\nSetting limits to %d...\n",WIN32_MAXSTDIO);# endif  // This will fail and not do anything if WIN32_MAXSTDIO > 2048    int status=_setmaxstdio(WIN32_MAXSTDIO);    if(!status) {		printf("Failed to set STDIO limit\n");    }# if DEBUG_OPENFILES    maxstdio=_getmaxstdio();    printf("Permitted open files (after): %d\n",maxstdio);# endif#else  //#ifdef WIN32	// Set process limits	if(getrlimit(RLIMIT_NOFILE,&lim)<0) {		fprintf(stderr,"Cannot retrieve the process FD limits\n");	} else	{# if DEBUG_OPENFILES		printf("RLIMIT_NOFILE (before): rlim_cur=%d rlim_rlim_max=%d "		  "OPEN_MAX=%d SC_OPEN_MAX=%d FOPEN_MAX=%d\n",		  lim.rlim_cur,lim.rlim_max,		  OPEN_MAX,_SC_OPEN_MAX,FOPEN_MAX);		printf("  sysconf: _SC_OPEN_MAX %d _SC_STREAM_MAX %d\n",		  sysconf(_SC_OPEN_MAX), sysconf(_SC_STREAM_MAX));# endif		if(lim.rlim_cur<lim.rlim_max) {			lim.rlim_cur=lim.rlim_max;			if(setrlimit(RLIMIT_NOFILE,&lim)<0)			  fprintf(stderr,"Failed to set FD limit %d\n",				(int)lim.rlim_cur);		}#if DEBUG_OPENFILES		if(getrlimit(RLIMIT_NOFILE,&lim)<0) {			printf("RLIMIT_NOFILE (after): Failed\n");		} else {			printf("RLIMIT_NOFILE (after): rlim_cur=%d rlim_rlim_max=%d "			  "OPEN_MAX=%d SC_OPEN_MAX=%d FOPEN_MAX=%d\n",			  lim.rlim_cur,lim.rlim_max,			  OPEN_MAX,_SC_OPEN_MAX,FOPEN_MAX);			printf("  sysconf: _SC_OPEN_MAX %d _SC_STREAM_MAX %d\n",			  sysconf(_SC_OPEN_MAX), sysconf(_SC_STREAM_MAX));		}#endif	}	

⌨️ 快捷键说明

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