📄 gateway.cc
字号:
/*************************************************************************\* 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 + -