--- /dev/null
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fnmatch.h>
+#include <signal.h>
+#include <syslog.h>
+#include <sys/wait.h>
+
+#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;
+}
+