This commit is contained in:
opfez 2022-04-11 02:40:49 +02:00
commit 0a67fb480a
4 changed files with 100 additions and 0 deletions

6
build.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/sh
CC=${CC:-cc}
CFLAGS="-Wall -Wextra -std=c99 -pedantic -lm -g"
$CC $CFLAGS serve.c -o serve

5
ex-server.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
printf "what's your name? "
read name
echo "hello $name!"

10
readme.txt Normal file
View File

@ -0,0 +1,10 @@
# serve
`serve` is a super simple server. It takes as input a port to run the server on,
and the path to a program. The program's stdin and stdout will work on the
client which is connected to it.
An example server is found in `ex-server.sh` and can be tried out with
`serve 1234 ./ex-server.sh`.
You can connect to the server with `nc -vn 127.0.0.1 1234`.

79
serve.c Normal file
View File

@ -0,0 +1,79 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
void
die(const char *s, ...)
{
va_list argp;
va_start(argp, s);
vfprintf(stderr, s, argp);
fputc('\n', stderr);
va_end(argp);
exit(1);
}
int
main(int argc, char *argv[], char *envp[])
{
if (argc < 3)
die("usage: serve port program args ...");
short port = atoi(argv[1]);
if (port == 0) {
die("invalid port number");
}
/* now skip the two first args so that we can pass argv to execve later */
argv += 2;
int sfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server, client;
if (sfd < 0)
die("error encountered while initializing socket");
if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0)
die("setsockopt(SO_REUSEADDR) failed");
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(port);
/* assigning an address to the socket */
if (bind(sfd, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("bind");
exit(1);
}
/* start accepting connections */
if (listen(sfd, 10) < 0)
die("error encountered while trying to listen for connections");
/* handling connections */
for (;;) {
socklen_t client_len = sizeof(client);
int cfd = accept(sfd, (struct sockaddr *)&client, &client_len);
if (cfd < 0)
die("error encountered while accepting connection");
/* start new process and change stdout/stdin so that the process can
* read/write to the client */
pid_t p = fork();
if (!p) {
/* in the new process */
dup2(cfd, STDIN_FILENO);
dup2(cfd, STDOUT_FILENO);
int err = execve(argv[0], argv, envp);
die("execve() error: %d\n", err);
}
else {
/* in the old process */
close(cfd);
}
}
}