/***************************************************************************** * Systemprogrammierung I - Klausur vom Juli 2003 * * Datei: rshd.c * Autor: Goethe * Datum: 07.09.2005 *****************************************************************************/ #include #include #include #include #include #include #include #include #include #define MAXCMD 1024 /* Funktionsdeklarationen, globale Variablen */ void setstdio(int); void sigchld_handler(int); int execute_job(int); /* Funktion main */ int main( int argc, char *argv[] ) { /* lokale Variablen und was man sonst am Anfang so braucht */ int sd, cd; struct sockaddr_in sin; struct sigaction action; if( argc != 2 ) { fprintf( stderr, "usage: %s \n", argv[0] ); return -1; } /* Socket öffnen */ if( (sd = socket( PF_INET, SOCK_STREAM, 0 )) == -1 ) { perror( "Fehler beim Öffnen des Sockets" ); return -1; } /* Socket an angegebenen Port und beliebige IP-Adressen binden */ sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_port = htons(atoi(argv[1])); if( bind( sd, (struct sockaddr*)&sin, sizeof(sin) ) == -1 ) { perror( "Fehler beim Binden des Sockets" ); return -1; } /* Warteschlange ankommender Verbindungen auf 5 einstellen */ if( listen( sd, 5 ) == -1 ) { perror( "Fehler beim Einrichten der Verbindungswarteschlange" ); return -1; } /* Signalhandler für SIGCHLD einrichten */ memset( &action, 0, sizeof(action) ); sigemptyset( &action.sa_mask ); action.sa_handler = sigchld_handler; action.sa_flags = 0; if( sigaction( SIGCHLD, &action, NULL ) == -1 ) { perror( "Fehler beim Einrichten des Signalhandlers" ); return -1; } /* Server-Schleife */ while(1) { /* Verbindung annehmen */ if( (cd = accept( sd, NULL, 0 )) == -1 ) continue; /* Kommando ausführen */ execute_job(cd); close(cd); } } /* Ende Funktion main */ /* execute_job Funktion */ int execute_job( int cd ) { char cmd[MAXCMD]; char *arguments[] = { cmd, NULL }; pid_t pid; int i; /* Kommando von Socket einlesen */ read( cd, cmd, MAXCMD-1 ); cmd[MAXCMD-1] = '\0'; for( i = strlen(cmd)-1; i >= 0; i-- ) { if( cmd[i] == '\n' || cmd[i] == 13 ) cmd[i] = '\0'; } /* Sohnprozess erzeugen und Kommando ausführen */ if( (pid = fork()) == -1 ) { perror( "Erzeugen des Sohnprozesses fehlgeschlagen" ); return -1; } else if( pid == 0 ) { setstdio(cd); execvp( cmd, arguments ); perror( "Fehler beim Ausführen des Kommandos" ); exit( EXIT_FAILURE ); } return 0; } /* Signalhandler für SIGCHLD */ void sigchld_handler( int sig ) { /* lokale Variablen */ FILE *log; pid_t pid; int status; /* logfile öffnen */ if( (log = fopen( "logfile", "a" )) == NULL ) perror( "Fehler beim Öffnen der Logfile 'logfile'" ); /* terminierte Sohnprozesse abfragen und Status in logfile schreiben */ while( (pid = waitpid( -1, &status, WNOHANG )) != -1 ) { if( pid == 0 ) break; if( log == NULL ) continue; if( WIFEXITED(status) ) fprintf( log, "PID: %d Exitstatus: %d\n", pid, WEXITSTATUS(status) ); else if( WIFSIGNALED(status) ) fprintf( log, "PID: %d Signal: %d\n", pid, WTERMSIG(status) ); } fclose(log); } void setstdio( int socket ) { FILE *fsocket = fdopen( socket, "r+" ); fclose(stdin); fclose(stdout); fclose(stderr); stdin = fsocket; stdout = fsocket; stderr = fsocket; }