diff --git a/.travis.yml b/.travis.yml index b6ff8e6..5b746e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,15 @@ cache: directories: - $HOME/.cache +addons: + apt: + packages: + - autoconf-archive + homebrew: + packages: + - autoconf-archive + update: true + jobs: include: - os: linux diff --git a/Makefile.Epics.in b/Makefile.Epics.in index 711f942..9cd0715 100644 --- a/Makefile.Epics.in +++ b/Makefile.Epics.in @@ -15,6 +15,7 @@ procServ_SRCS = procServ.cc connectionItem.cc acceptFactory.cc \ procServ_OBJS = @LIBOBJS@ USR_CXXFLAGS += @DEFS@ +USR_CXXFLAGS += @CXXFLAGS@ procServ_SYS_LIBS += $(subst -l,,@LIBS@) include $(TOP)/configure/RULES diff --git a/clientFactory.cc b/clientFactory.cc index 9a926ca..24c789d 100644 --- a/clientFactory.cc +++ b/clientFactory.cc @@ -95,32 +95,26 @@ clientItem::clientItem(int socketIn, bool readonly) : char procServStart_buf[32]; // Time when this procServ started - as string struct tm IOCStart_tm; // Time when the current IOC was started char IOCStart_buf[32]; // Time when the current IOC was started - as string -#define BUFLEN 512 - char buf1[BUFLEN], buf2[BUFLEN]; - char greeting1[] = "@@@ Welcome to procServ (" PROCSERV_VERSION_STRING ")" NL; -#define GREETLEN 256 - char greeting2[GREETLEN] = ""; + const char greeting1[] = "@@@ Welcome to procServ (" PROCSERV_VERSION_STRING ")" NL; + std::string greeting2 {}; struct timeval send_timeout; send_timeout.tv_sec = 10; send_timeout.tv_usec = 0; PRINTF("New clientItem %p\n", this); if ( killChar ) { - snprintf(greeting2, GREETLEN, "@@@ Use %s%c to kill the child, ", CTL_SC(killChar)); + greeting2 += "@@@ Use " + ctl_str(killChar) + " to kill the child, "; } else { - snprintf(greeting2, GREETLEN, "@@@ Kill command disabled, "); + greeting2 += "@@@ Kill command disabled, "; } - snprintf(buf1, BUFLEN, "auto restart mode is %s, ", restartModeString()); + greeting2 += std::string("auto restart mode is ") + restartModeString() + ", "; if ( toggleRestartChar ) { - snprintf(buf2, BUFLEN, "use %s%c to toggle auto restart" NL, CTL_SC(toggleRestartChar)); + greeting2 += "use " + ctl_str(toggleRestartChar) + " to toggle auto restart" NL; } else { - snprintf(buf2, BUFLEN, "auto restart toggle disabled" NL); + greeting2 += "auto restart toggle disabled" NL; } - strncat(greeting2, buf1, GREETLEN-strlen(greeting2)-1); - strncat(greeting2, buf2, GREETLEN-strlen(greeting2)-1); if (logoutChar) { - snprintf(buf2, BUFLEN, "@@@ Use %s%c to logout from procServ server" NL, CTL_SC(logoutChar)); - strncat(greeting2, buf2, GREETLEN-strlen(greeting2)-1); + greeting2 += "@@@ Use " + ctl_str(logoutChar) + " to logout from procServ server" NL; } localtime_r( &procServStart, &procServStart_tm ); @@ -131,17 +125,13 @@ clientItem::clientItem(int socketIn, bool readonly) : strftime( IOCStart_buf, sizeof(IOCStart_buf)-1, timeFormat, &IOCStart_tm ); - snprintf(buf1, BUFLEN, "@@@ procServ server started at: %s" NL, - procServStart_buf); + std::string buf1 = std::string("@@@ procServ server started at: ") + procServStart_buf + NL; if ( processClass::exists() ) { - snprintf(buf2, BUFLEN, "@@@ Child \"%s\" started at: %s" NL, - childName, IOCStart_buf ); - strncat(buf1, buf2, BUFLEN-strlen(buf1)-1); + buf1 += std::string("@@@ Child \"") + childName + "\" started at: " + IOCStart_buf + NL; } - snprintf(buf2, BUFLEN, "@@@ %d user(s) and %d logger(s) connected (plus you)" NL, - _users, _loggers); + std::string buf2 = "@@@ " + std::to_string(_users) + " user(s) and " + std::to_string(_loggers) + " logger(s) connected (plus you)" NL; setsockopt( socketIn, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval) ); setsockopt( socketIn, SOL_SOCKET, SO_SNDTIMEO, &send_timeout, sizeof(send_timeout) ); @@ -151,16 +141,16 @@ clientItem::clientItem(int socketIn, bool readonly) : } else { // Regular (user) client _users++; ignore_result( write(_fd, greeting1, strlen(greeting1)) ); - ignore_result( write(_fd, greeting2, strlen(greeting2)) ); + ignore_result( write(_fd, greeting2.c_str(), greeting2.length() + 1) ); } - ignore_result( write(_fd, infoMessage1, strlen(infoMessage1)) ); - ignore_result( write( _fd, infoMessage2, strlen(infoMessage2)) ); - ignore_result( write( _fd, buf1, strlen(buf1)) ); + ignore_result( write(_fd, infoMessage1.c_str(), infoMessage1.length() + 1) ); + ignore_result( write( _fd, infoMessage2.c_str(), infoMessage2.length() + 1) ); + ignore_result( write( _fd, buf1.c_str(), buf1.length() + 1) ); if ( ! _readonly ) - ignore_result( write(_fd, buf2, strlen(buf2)) ); + ignore_result( write(_fd, buf2.c_str(), buf2.length() + 1) ); if ( ! processClass::exists() ) - ignore_result( write(_fd, infoMessage3, strlen(infoMessage3)) ); + ignore_result( write(_fd, infoMessage3.c_str(), infoMessage3.length() + 1) ); _telnet = telnet_init(my_telopts, telnet_eh, 0, this); diff --git a/configure.ac b/configure.ac index 03fd213..f6093ab 100644 --- a/configure.ac +++ b/configure.ac @@ -44,6 +44,7 @@ AC_TYPE_MODE_T AC_TYPE_PID_T AC_C_RESTRICT AC_STRUCT_TM +AX_CXX_COMPILE_STDCXX_11([noext], [mandatory]) # Checks for library functions. AC_FUNC_FORK diff --git a/procServ.cc b/procServ.cc index a693541..59dd3d8 100644 --- a/procServ.cc +++ b/procServ.cc @@ -82,13 +82,9 @@ char defaulttimeFormat[] = "%c"; // default bool stampLog = false; // Prefix log lines with time stamp const char *stampFormat; // Log time stamp format string -const size_t INFO1LEN = 512; -const size_t INFO2LEN = 128; -const size_t INFO3LEN = 128; - -char infoMessage1[INFO1LEN]; // Sign on message: server PID, child pwd and command line -char infoMessage2[INFO2LEN]; // Sign on message: child PID -char infoMessage3[INFO3LEN]; // Sign on message: available server commands +std::string infoMessage1; // Sign on message: server PID, child pwd and command line +std::string infoMessage2; // Sign on message: child PID +std::string infoMessage3; // Sign on message: available server commands char *logFile = NULL; // File name for log int logFileFD=-1; // FD for log file @@ -118,6 +114,19 @@ static volatile sig_atomic_t sigPipeSet; static volatile sig_atomic_t sigTermSet; static volatile sig_atomic_t sigHupSet; +bool is_cntrl_char(const char c) { + return c > 0 && c < 32; +} + +std::string ctl_str(const char c) { + if (is_cntrl_char(c)) { + const char human_readable_representation = c + 64; + return std::string("^") + human_readable_representation; + } else { + return std::string(c, 1); + } +} + void writePidFile() { int pid = getpid(); @@ -212,8 +221,6 @@ int main(int argc,char * argv[]) std::vector ctlSpecs; char *command; bool bailout = false; - const size_t BUFLEN = 512; - char buff[BUFLEN]; std::string infofile; time(&procServStart); // remember start time @@ -440,15 +447,14 @@ int main(int argc,char * argv[]) // Set up available server commands message PRINTF("Setting up messages\n"); - snprintf(infoMessage3, INFO3LEN,\ - "@@@ %s%c or %s%c restarts the child, %s%c quits the server", - CTL_SC(restartChar), CTL_SC(killChar), CTL_SC(quitChar)); + infoMessage3 = std::string("@@@ ") + ctl_str(restartChar).c_str() + " or " + + ctl_str(killChar).c_str() + " restarts the child, " + + ctl_str(quitChar).c_str() + " quits the server"; if (logoutChar) { - snprintf(buff, BUFLEN, ", %s%c closes this connection", - CTL_SC(logoutChar)); - strncat(infoMessage3, buff, INFO3LEN-strlen(infoMessage3)-1); + infoMessage3 += std::string(", ") + ctl_str(logoutChar).c_str() + + " closes this connection"; } - strncat(infoMessage3, NL, INFO3LEN-strlen(infoMessage3)-1); + infoMessage3 += NL; if (singleEndpointStyle) { ctlSpecs.push_back(argv[optind++]); @@ -569,29 +575,21 @@ int main(int argc,char * argv[]) } // Record some useful data for managers - snprintf(infoMessage1, INFO1LEN, - "@@@ procServ server PID: %ld" NL - "@@@ Server startup directory: %s" NL - "@@@ Child startup directory: %s" NL, - (long) getpid(), - myDir, - chDir); + infoMessage1 = std::string("@@@ procServ server PID: ") + std::to_string(getpid()) + NL + + "@@@ Server startup directory: " + myDir + NL + + "@@@ Child startup directory: " + chDir + NL; if ( strcmp( childName, command ) ) - snprintf(buff, BUFLEN, "@@@ Child \"%s\" started as: %s" NL, - childName, command ); + infoMessage1 += std::string("@@@ Child \"") + childName + "\" started as: " + + command + NL; else - snprintf(buff, BUFLEN, "@@@ Child started as: %s" NL, - command ); - strncat(infoMessage1, buff, INFO1LEN-strlen(infoMessage1)-1); - snprintf(infoMessage2, INFO2LEN, "@@@ Child \"%s\" is SHUT DOWN" NL, childName); + infoMessage1 += std::string("@@@ Child started as: ") + command + NL; + infoMessage2 = std::string("@@@ Child \"") + childName + "\" is SHUT DOWN" NL; if ( logFile ) { if ( -1 == logFileFD ) - snprintf(buff, BUFLEN, "@@@ Child log file: unable to open log file %s" NL, - logFile ); + infoMessage1 += std::string("@@@ Child log file: unable to open log file ") + + logFile + NL; else - snprintf(buff, BUFLEN, "@@@ Child log file: %s" NL, - logFile ); - strncat(infoMessage1, buff, INFO1LEN-strlen(infoMessage1)-1); + infoMessage1 += std::string("@@@ Child log file: ") + logFile + NL; } firstRun = true; diff --git a/procServ.h b/procServ.h index 0dcb381..08f7ca7 100644 --- a/procServ.h +++ b/procServ.h @@ -51,12 +51,9 @@ extern char restartChar; extern char quitChar; extern char logoutChar; extern int killSig; -extern const size_t INFO1LEN; -extern const size_t INFO2LEN; -extern const size_t INFO3LEN; -extern char infoMessage1[]; -extern char infoMessage2[]; -extern char infoMessage3[]; +extern std::string infoMessage1; +extern std::string infoMessage2; +extern std::string infoMessage3; extern pid_t procservPid; extern rlim_t coreSize; extern char *chDir; @@ -64,7 +61,7 @@ extern time_t holdoffTime; #define NL "\r\n" -#define CTL_SC(c) c > 0 && c < 32 ? "^" : "", c > 0 && c < 32 ? c + 64 : c +std::string ctl_str(const char c); class connectionItem; diff --git a/processFactory.cc b/processFactory.cc index f86e4dd..bae8ce3 100644 --- a/processFactory.cc +++ b/processFactory.cc @@ -106,12 +106,12 @@ processClass::~processClass() "oneshot mode: server will exit")); // Update client connect message - snprintf(infoMessage2, INFO2LEN, "@@@ Child \"%s\" is SHUT DOWN" NL, childName); + infoMessage2 = std::string("@@@ Child \"") + childName + "\" is SHUT DOWN" NL; SendToAll( now_buf, strlen(now_buf), this ); SendToAll( goodbye, strlen(goodbye), this ); if (restartMode != oneshot) - SendToAll( infoMessage3, strlen(infoMessage3), this ); + SendToAll( infoMessage3.c_str(), infoMessage3.length() + 1, this ); // Negative PID sends signal to all members of process group if ( _pid > 0 ) kill( -_pid, SIGKILL ); @@ -188,7 +188,7 @@ processClass::processClass(char *exe, char *argv[]) _restartTime = holdoffTime + time(0); // Update client connect message - snprintf(infoMessage2, INFO2LEN, "@@@ Child \"%s\" PID: %ld" NL, childName, (long) _pid); + infoMessage2 = std::string("@@@ Child \"") + childName + "\" PID: " + std::to_string(_pid) + NL; snprintf(buf, BUFLEN, "@@@ The PID of new child \"%s\" is: %ld" NL, childName, (long) _pid); SendToAll( buf, strlen(buf), this );