From: HADES_DAQ Date: Tue, 29 Oct 2013 11:14:32 +0000 (+0100) Subject: added command server,mt X-Git-Tag: pre2018~126 X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=875df5311dfa85dc83a48b73d3cbd8659cabc521;p=hadesdaq.git added command server,mt --- diff --git a/utils/src/command_server/command_server b/utils/src/command_server/command_server new file mode 100755 index 0000000..7bbec03 Binary files /dev/null and b/utils/src/command_server/command_server differ diff --git a/utils/src/command_server/command_server.c b/utils/src/command_server/command_server.c new file mode 100644 index 0000000..9084b1f --- /dev/null +++ b/utils/src/command_server/command_server.c @@ -0,0 +1,313 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_QUEUE 5 +#define BUF_SIZE 2048 + +int sock_1, sock_2; /* file descriptors for sockets */ +FILE *fp; + +void exit(int); + +typedef struct TheArgsS { + unsigned long verbosity; + unsigned long port; +} TheArgs; + +void SIGhandler(int); + +void SIGhandler(int sig) +{ + syslog(LOG_ERR, "Caught signal %d, trying to safely exit...", sig); + + if(fp) + fclose(fp); + + if(sock_2) + close(sock_2); + + if(sock_1) + close(sock_1); + + exit(0); +} +void SigCatcher(int n) +{ + wait3(NULL,WNOHANG,NULL); +} + +static void argsDefault(TheArgs *my) +{ + my->verbosity = 0; + my->port = 4712; +} + +static int argsFromCL(TheArgs *my, int argc, char *argv[]) +{ + extern char *optarg; + int i; + + while ((i = getopt(argc, argv, "vp:")) != -1) { + switch (i) { + case 'p': + my->port = atoi(optarg); + break; + case 'v': + my->verbosity = 1; + break; + default: + return -1; + break; + } + } + + return 0; +} + +static void usage(const char *progName) +{ + printf("Usage: %s\n", progName); + printf(" [-p port] : Port number for connection (default: 4712).\n"); + printf(" [-v] : More verbose.\n"); +} + +void talk2client(int sock_2, TheArgs *theArgs) +{ + int firstCmdLine = 0; + int rec_value; + int r = 0; + + struct stat file_status; + + char buf[BUF_SIZE]; + char buf2[BUF_SIZE+300]; + char buf3[BUF_SIZE+300]; + char tmp[BUF_SIZE+300]; + char *token; + char redirect1[100]; + char redirect2[100]; + char fstdout[100]; + char fstderr[100]; + + sprintf(fstdout, "%s%d%s", "/tmp/stdout", (int) getpid(), ".txt"); + sprintf(fstderr, "%s%d%s", "/tmp/stderr", (int) getpid(), ".txt"); + sprintf(redirect1, "1>%s 2>%s", fstdout, fstderr); + sprintf(redirect2, "1>>%s 2>>%s", fstdout, fstderr); + + + char mypattern[BUF_SIZE+100]; + sprintf(mypattern, "iamfromhadesdaq"); /* password */ + + /* Read command from sock_2 */ + while( (rec_value = read( sock_2, buf, BUF_SIZE )) ){ + if( rec_value < 0 ){ + perror("reading stream message"); + exit(1); + } + else + snprintf( buf2, rec_value, "%s", buf ); + + if(theArgs->verbosity) + printf("Received: \"%s\"\n", buf2); + + /* check password only for the first cmd line */ + if( firstCmdLine == 0 ){ + if( 0 != fnmatch(mypattern, buf2, 0) ){ + sprintf( buf, "Error: wrong password! Break connection.\n" ); + printf( "%s", buf ); + printf( "Local pass : %s", mypattern ); + printf( "Remote pass : %s", buf2 ); + write( sock_2, buf, strlen(buf) ); + break; + } + else{ + sprintf( buf, "------------- Connection accepted -------------\n" ); + write( sock_2, buf, strlen(buf) ); + firstCmdLine = 1; /* set to 1 to avoid checking pass second time */ + continue; + } + } + + /* raise(SIGUSR1); */ + + /* Prepare cmd for execution. Write standard out/err to tmp. */ + strcpy(tmp, buf2); + strcpy(buf3, ""); + + /* Split string and build cmd 'buf3' */ + token = strtok( tmp, ";" ); + while( token != (char*)NULL ){ + if( strcmp(buf3, "") != 0 ) + sprintf( buf3, "%s %s %s;", buf3, token, redirect2); + else + sprintf( buf3, "%s %s;", token, redirect1); + + token = strtok( NULL, ";" ); + } + + /* sprintf( buf3, "%s 1>/tmp/stdout.txt 2>/tmp/stderr.txt", buf2 ); */ + + if(theArgs->verbosity) + printf("Command: \"%s\"\n", buf3); + + if(theArgs->verbosity) + printf("before Return value of system: %d\n", r); + + /* Execute cmd and get the return value */ + r = system(buf3); + + if(theArgs->verbosity) + printf("Return value of system: %d\n", r); + + /* Prepare and send the return value of cmd */ + sprintf( buf, "> return value of command: %i\n", r ); + write( sock_2, buf, strlen(buf) ); + + /* Check size of the stdout file, anything to read from file? */ + if(stat(fstdout, &file_status) != 0){ + perror("could not stat"); + } + + if( (int)file_status.st_size ){ + sprintf( buf, "> stdout: \n" ); + write( sock_2, buf, strlen(buf) ); + + /* Open and send the stardard output */ + fp = fopen(fstdout, "r"); + while( (r = fread( buf, sizeof(char), BUF_SIZE, fp )) ){ + write( sock_2, buf, r ); + } + + fclose(fp); + } + + /* Check size of the stderr file, anything to read from file? */ + if(stat(fstderr, &file_status) != 0){ + perror("could not stat"); + } + + if( (int)file_status.st_size ){ + sprintf( buf, "> stderr: \n" ); + write( sock_2, buf, strlen(buf) ); + + /* Open and send the standard error */ + fp = fopen(fstderr, "r"); + while( (r = fread(buf, sizeof(char), BUF_SIZE, fp)) ){ + write( sock_2, buf, r ); + } + + fclose(fp); + } + + sprintf( buf, "------------- END OF OUTPUT ------------\n" ); + write( sock_2, buf, strlen(buf) ); + + /* write(1,buf,rec_value); */ + + } /* End of while( (rec_value = read( sock_2, buf, BUF_SIZE )) ) */ + + if(remove(fstdout)) syslog(LOG_ERR, "%s:%d: %s %s", __FILE__, __LINE__, "Cannot remove file", fstdout); + if(remove(fstderr)) syslog(LOG_ERR, "%s:%d: %s %s", __FILE__, __LINE__, "Cannot remove file", fstderr); +} + +int main( int argc, char *argv[] ) +{ + int sockopt_on = 1; + struct sockaddr_in server; + int pid; + + TheArgs theArgsS, *theArgs = &theArgsS; + + /* signal(SIGCHLD, SIG_IGN); */ + signal(SIGCHLD, SigCatcher); + signal(SIGUSR1, SIGhandler); + signal(SIGTERM, SIGhandler); + signal(SIGABRT, SIGhandler); + signal(SIGILL, SIGhandler); + signal(SIGINT, SIGhandler); + signal(SIGPIPE, SIGhandler); + signal(SIGSEGV, SIGhandler); + + openlog(argv[0], LOG_PID | LOG_PERROR, LOG_LOCAL0); + setlogmask(LOG_UPTO(LOG_INFO)); + + argsDefault(theArgs); + if (0 > argsFromCL(theArgs, argc, argv)) { + usage(argv[0]); + exit(1); + } + + /* Init to zero */ + bzero((char *) &server, sizeof(server)); + + /* Build address in internet domain */ + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; /* everyone is allowed to connet to server */ + server.sin_port = htons(theArgs->port); + + /* Create stream socket in internet domain */ + sock_1 = socket( AF_INET, SOCK_STREAM, 0 ); + if( sock_1 < 0 ){ + syslog(LOG_ERR, "%s:%d: %s", __FILE__, __LINE__, "Cannot open stream socket"); + exit(1); + } + + /* Make the socket reusable */ + if( 0 > setsockopt( sock_1, SOL_SOCKET, SO_REUSEADDR, &sockopt_on, sizeof(int)) ){ + syslog(LOG_ERR, "%s:%d: %s", __FILE__, __LINE__, "Cannot make socket reusable"); + } + + /* Bind socket */ + if( 0 > bind(sock_1, (struct sockaddr *)&server,sizeof(struct sockaddr_in)) ){ + syslog(LOG_ERR, "%s:%d: %s", __FILE__, __LINE__, "Cannot bind socket"); + exit(1); + } + + listen( sock_1, MAX_QUEUE ); + + while(1){ + /* Start accepting connection */ + sock_2 = accept( sock_1, 0, 0); + + if( sock_2 < 0 ){ + syslog(LOG_ERR, "%s:%d: %s", __FILE__, __LINE__, "Cannot accept connections"); + } + + /* Fork new process */ + pid = fork(); + + if( pid < 0 ) + syslog(LOG_ERR, "%s:%d: %s", __FILE__, __LINE__, "Cannot fork"); + + if( pid == 0 ){ /* Child */ + close(sock_1); + talk2client(sock_2, theArgs); + close(sock_2); + exit(0); + } + else{ /* Parent */ + close(sock_2); + } + + if(theArgs->verbosity){ + printf("Ending connection.\n"); + } + + } /* End of while(1) */ + + close(sock_1); + + return 0; +} +