#include #include #include #include #include #include #include #include "shell.h" /* * READ ME * What works: * - remote shell, weitesgehend die funktionalität der vorhergehenden aufgabe (damit auch pipes und background, * auch wenn wir das nicht ausführlich getestet haben) * - get und put für dateien * - mehrere clients an einem server * Known bugs: * - das erkennen, wann eine neue prompt geprintet werden muss ist aktuell sehr hacky client-seitig implementiert, * scheitert teilweise - die eingabe geht trzd ganz normal, es wird nur keine prompt angezeigt */ #define PORT 9000 #define BUF_SIZE 256 static inline void die(const char *msg) { perror(msg); exit(-1); } int main() { setvbuf(stderr, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); struct sockaddr_in srv_addr, cli_addr; int sockopt = 1; socklen_t sad_sz = sizeof(struct sockaddr_in); int sfd; srv_addr.sin_family = AF_INET; srv_addr.sin_port = htons(PORT); srv_addr.sin_addr.s_addr = INADDR_ANY; if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) die("Could not open socket"); setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char *) &sockopt, sizeof(sockopt)); if (bind(sfd, (struct sockaddr *) &srv_addr, sad_sz) < 0) die("Could not bind socket"); if (listen(sfd, 1) < 0) die("Could not listen on socket"); while (1) { int cfd, pid; cfd = accept(sfd, (struct sockaddr *) &cli_addr, &sad_sz); if (cfd < 0) { perror("Could not accept incoming connection"); break; } // fork new process pid = fork(); if (pid < 0) { perror("ERROR in new process creation"); } if (pid == 0) { // child process close(sfd); printf("srv: connected: %s\n", inet_ntoa(cli_addr.sin_addr)); int status = shell(cfd); fprintf(stdout, "srv: client disconnected: %s (%d)\n", inet_ntoa(cli_addr.sin_addr), status); fflush(stdout); close(cfd); } else { // parent process close(cfd); } } close(sfd); return 0; }