initial
This commit is contained in:
commit
0a67fb480a
|
@ -0,0 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
CC=${CC:-cc}
|
||||
CFLAGS="-Wall -Wextra -std=c99 -pedantic -lm -g"
|
||||
|
||||
$CC $CFLAGS serve.c -o serve
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
printf "what's your name? "
|
||||
read name
|
||||
echo "hello $name!"
|
|
@ -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`.
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue