summaryrefslogtreecommitdiffstats
path: root/03_exercise/srv/server.c
diff options
context:
space:
mode:
Diffstat (limited to '03_exercise/srv/server.c')
-rw-r--r--03_exercise/srv/server.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/03_exercise/srv/server.c b/03_exercise/srv/server.c
new file mode 100644
index 0000000..67fe21c
--- /dev/null
+++ b/03_exercise/srv/server.c
@@ -0,0 +1,89 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#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;
+}