aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2015-12-24 14:57:16 -0500
committerFranklin Wei <git@fwei.tk>2015-12-24 14:57:16 -0500
commit460d13ccd6242da9d25558aac6ffb7c6e9df03a6 (patch)
treedc872bc1a5afb940ec9ca2e0ab706bee811ef7e1
parentf1e708a631d7d5fbe6fc2f74e5f681d6a6786b4e (diff)
downloadnetcosm-460d13ccd6242da9d25558aac6ffb7c6e9df03a6.zip
netcosm-460d13ccd6242da9d25558aac6ffb7c6e9df03a6.tar.gz
netcosm-460d13ccd6242da9d25558aac6ffb7c6e9df03a6.tar.bz2
netcosm-460d13ccd6242da9d25558aac6ffb7c6e9df03a6.tar.xz
stuff
-rw-r--r--Makefile6
-rw-r--r--src/client.c151
-rw-r--r--src/netcosm.h106
-rw-r--r--src/server.c156
-rw-r--r--src/telnet.c12
-rw-r--r--src/telnet.h29
6 files changed, 337 insertions, 123 deletions
diff --git a/Makefile b/Makefile
index 5f28c9a..2f2df8d 100644
--- a/Makefile
+++ b/Makefile
@@ -2,12 +2,12 @@ CC = gcc
OUT = build
PLATFORM = unix
-NETCOSM_OBJ = src/server.o src/client.o src/auth.o src/telnet.o src/util.o
+NETCOSM_OBJ = src/server.o src/client.o src/auth.o src/telnet.o src/util.o src/room.o world.o
-CFLAGS = -O3 -g -I src/ -I target/$(PLATFORM) -Wall -Wextra
+CFLAGS = -Og -g -I src/ -I target/$(PLATFORM) -Wall -Wextra -Wshadow -Wpedantic
LDFLAGS = -lgcrypt
-all: $(OUT)/$(PLATFORM).bin
+all: $(OUT)/$(PLATFORM).bin Makefile
$(OUT)/$(PLATFORM).bin: $(NETCOSM_OBJ) Makefile
mkdir -p $(OUT)
diff --git a/src/client.c b/src/client.c
index d64846c..8006154 100644
--- a/src/client.c
+++ b/src/client.c
@@ -2,7 +2,9 @@
static int client_fd, to_parent, from_parent;
-static volatile sig_atomic_t output_locked = 0, done_printing;
+static room_id client_room;
+
+static volatile sig_atomic_t output_locked = 0;
void out_raw(const unsigned char *buf, size_t len)
{
@@ -15,7 +17,6 @@ try_again:
output_locked = 1;
write(client_fd, buf, len);
output_locked = 0;
- done_printing = 1;
}
else
goto try_again;
@@ -32,10 +33,36 @@ void __attribute__((format(printf,1,2))) out(const char *fmt, ...)
out_raw((unsigned char*)buf, len);
}
+static volatile sig_atomic_t request_complete;
+
+static void signal_master(void)
+{
+ request_complete = 0;
+ sigset_t block, old;
+
+ sigemptyset(&block);
+ sigaddset(&block, SIGUSR2);
+ sigprocmask(SIG_BLOCK, &block, &old);
+
+ kill(getppid(), SIGUSR1);
+
+ /* wait for a signal */
+ printf("Waiting for signal.\n");
+
+ sigsuspend(&old);
+ sigprocmask(SIG_SETMASK, &old, NULL);
+
+ errno = 0;
+ printf("Spinning until completed flag set.\n");
+ /* spin until we're done handling the request */
+ while(!request_complete) usleep(1);
+ printf("Request completely done.\n");
+}
+
void send_master(unsigned char cmd)
{
write(to_parent, &cmd, 1);
- kill(getppid(), SIGUSR1);
+ signal_master();
}
#define BUFSZ 128
@@ -51,10 +78,6 @@ tryagain:
if(read(client_fd, buf, BUFSZ - 1) < 0)
error("lost connection");
buf[BUFSZ - 1] = '\0';
- const unsigned char ctrlc[] = { 0xff, 0xf4, 0xff, 0xfd, 0x06 };
-
- if(!memcmp(buf, ctrlc, sizeof(ctrlc)))
- exit(0);
printf("Read '%s'\n", buf);
if(buf[0] & 0x80)
@@ -68,6 +91,16 @@ tryagain:
return buf;
}
+/* still not encrypted, but a bit more secure than echoing the pass */
+char *client_read_password(void)
+{
+ telnet_echo_off();
+ char *ret = client_read();
+ telnet_echo_on();
+ out("\n");
+ return ret;
+}
+
void all_upper(char *s)
{
while(*s)
@@ -77,10 +110,17 @@ void all_upper(char *s)
}
}
-void sigusr2_handler(int s)
+void sigusr2_handler(int s, siginfo_t *info, void *vp)
{
(void) s;
- printf("got SIGUSR2\n");
+ (void) vp;
+
+ sig_printf("got SIGUSR2\n");
+
+ /* we only listen to requests from our parent */
+ if(info->si_pid != getppid())
+ return;
+
unsigned char cmd;
read(from_parent, &cmd, 1);
unsigned char buf[MSG_MAX + 1];
@@ -88,32 +128,40 @@ void sigusr2_handler(int s)
{
case REQ_BCASTMSG:
{
- printf("reading...\n");
- size_t len = read(from_parent, buf, MSG_MAX);
- printf("done reading\n");
+ sig_printf("reading...\n");
+ ssize_t len = read(from_parent, buf, MSG_MAX);
+ sig_printf("done reading\n");
buf[MSG_MAX] = '\0';
out_raw(buf, len);
break;
}
case REQ_KICK:
{
- size_t len = read(from_parent, buf, MSG_MAX);
+ ssize_t len = read(from_parent, buf, MSG_MAX);
buf[MSG_MAX] = '\0';
out_raw(buf, len);
exit(EXIT_SUCCESS);
}
+ case REQ_NOP:
+ break;
default:
- fprintf(stderr, "WARNING: client process received unknown request\n");
+ sig_printf("WARNING: client process received unknown code %d\n", cmd);
break;
}
+
+ sig_printf("Client finishes handling request.\n");
+
+ request_complete = 1;
}
void client_change_state(int state)
{
+ printf("Client requesting state transition\n");
unsigned char cmdcode = REQ_CHANGESTATE;
write(to_parent, &cmdcode, sizeof(cmdcode));
write(to_parent, &state, sizeof(state));
- kill(getppid(), SIGUSR1);
+ signal_master();
+ printf("State transition completed.\n");
}
void client_change_user(const char *user)
@@ -121,7 +169,7 @@ void client_change_user(const char *user)
unsigned char cmdcode = REQ_CHANGEUSER;
write(to_parent, &cmdcode, sizeof(cmdcode));
write(to_parent, user, strlen(user) + 1);
- kill(getppid(), SIGUSR1);
+ signal_master();
}
#define WSPACE " \t\r\n"
@@ -134,7 +182,14 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from)
output_locked = 0;
- signal(SIGUSR2, sigusr2_handler);
+ struct sigaction sa;
+
+ sigemptyset(&sa.sa_mask);
+
+ sa.sa_flags = SA_RESTART | SA_SIGINFO;
+ sa.sa_sigaction = sigusr2_handler;
+ if(sigaction(SIGUSR2, &sa, NULL) < 0)
+ error("sigaction");
telnet_init();
@@ -142,6 +197,8 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from)
printf("New client %s\n", ip);
printf("Total clients: %d\n", total);
+auth:
+
out("NetCosm " NETCOSM_VERSION "\n");
if(total > 1)
out("%d clients connected.\n", total);
@@ -164,11 +221,8 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from)
out("login: ");
current_user = client_read();
remove_cruft(current_user);
- telnet_echo_off();
out("Password: ");
- char *pass = client_read();
- telnet_echo_on();
- out("\n");
+ char *pass = client_read_password();
client_change_state(STATE_CHECKING);
struct authinfo_t auth = auth_check(current_user, pass);
memset(pass, 0, strlen(pass));
@@ -177,7 +231,6 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from)
authlevel = auth.authlevel;
if(auth.success)
{
- client_change_state(STATE_LOGGEDIN);
out("Access Granted.\n\n");
break;
}
@@ -198,6 +251,8 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from)
bool admin = (authlevel == PRIV_ADMIN);
if(admin)
client_change_state(STATE_ADMIN);
+ else
+ client_change_state(STATE_LOGGEDIN);
/* authenticated */
printf("Authenticated as %s\n", current_user);
@@ -220,6 +275,9 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from)
if(!strcmp(tok, "USER"))
{
char *what = strtok_r(NULL, WSPACE, &save);
+ if(!what)
+ goto next_cmd;
+
all_upper(what);
if(!strcmp(what, "DEL"))
@@ -253,7 +311,20 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from)
out("New Password (_DO_NOT_USE_A_VALUABLE_PASSWORD_): ");
/* BAD BAD BAD BAD BAD BAD BAD CLEARTEXT PASSWORDS!!! */
- char *pass = client_read();
+ char *pass = client_read_password();
+
+ out("Verify Password: ");
+ char *pass2 = client_read_password();
+
+ if(strcmp(pass, pass2))
+ {
+ memset(pass, 0, strlen(pass));
+ memset(pass2, 0, strlen(pass2));
+ free(pass);
+ free(pass2);
+ out("Failure.\n");
+ goto next_cmd;
+ }
out("Admin privileges [y/N]? ");
char *allow_admin = client_read();
@@ -281,19 +352,19 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from)
else if(!strcmp(tok, "CLIENT"))
{
char *what = strtok_r(NULL, WSPACE, &save);
- all_upper(what);
if(!what)
{
out("Usage: CLIENT <LIST|KICK> <PID>\n");
+ goto next_cmd;
}
+
+ all_upper(what);
+
if(!strcmp(what, "LIST"))
{
- done_printing = 0;
unsigned char cmd_code = REQ_LISTCLIENTS;
write(to_parent, &cmd_code, sizeof(cmd_code));
- kill(getppid(), SIGUSR1);
- waitpid(-1, NULL, 0);
- while(!done_printing);
+ signal_master();
}
else if(!strcmp(what, "KICK"))
{
@@ -307,7 +378,8 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from)
char buf[128];
int len = snprintf(buf, sizeof(buf), "You were kicked.\n");
write(to_parent, buf, len);
- kill(getppid(), SIGUSR1);
+ signal_master();
+ printf("Success.\n");
}
else
out("Usage: CLIENT KICK <PID>\n");
@@ -330,7 +402,26 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from)
unsigned char cmd_code = REQ_BCASTMSG;
write(to_parent, &cmd_code, sizeof(cmd_code));
dprintf(to_parent, "%s says %s", current_user, what);
- kill(getppid(), SIGUSR1);
+ signal_master();
+ }
+ else if(!strcmp(tok, "DATE"))
+ {
+ time_t t = time(NULL);
+ out("%s", ctime(&t));
+ }
+ else if(!strcmp(tok, "LOGOUT"))
+ {
+ out("Logged out.\n");
+ goto auth;
+ }
+ else if(!strcmp(tok, "LOOK"))
+ {
+ //out(room_get(client_room)->data.desc);
+ //out("\n");
+ }
+ else if(!strcmp(tok, "WAIT"))
+ {
+ send_master(REQ_WAIT);
}
next_cmd:
diff --git a/src/netcosm.h b/src/netcosm.h
index 16ace01..ac2c72c 100644
--- a/src/netcosm.h
+++ b/src/netcosm.h
@@ -30,21 +30,106 @@
#define PRIV_USER 0
#define PRIV_ADMIN 1337
+/* child<->master commands */
+/* children might not implement all of these */
+#define REQ_NOP 0
+#define REQ_BCASTMSG 1
+#define REQ_LISTCLIENTS 2
+#define REQ_CHANGESTATE 3
+#define REQ_CHANGEUSER 4
+#define REQ_HANG 5
+#define REQ_KICK 6
+#define REQ_WAIT 7
+
+/* child states */
+#define STATE_INIT 0
+#define STATE_AUTH 1
+#define STATE_CHECKING 2
+#define STATE_LOGGEDIN 3
+#define STATE_ADMIN 4
+#define STATE_FAILED 5
+
+/* for convenience when writing world specs */
+#define NONE_N NULL
+#define NONE_NE NULL
+#define NONE_E NULL
+#define NONE_SE NULL
+#define NONE_S NULL
+#define NONE_SW NULL
+#define NONE_W NULL
+#define NONE_NW NULL
+#define NONE_UP NULL
+#define NONE_DN NULL
+
struct authinfo_t {
bool success;
const char *user;
int authlevel;
};
+/* logged in users are identified by the PID of the process serving them */
+struct user_t {
+ pid_t pid;
+};
+
+enum direction_t { DIR_N = 0, DIR_NE, DIR_E, DIR_SE, DIR_S, DIR_SW, DIR_W, DIR_NW, DIR_UP, DIR_DOWN, NUM_DIRECTIONS };
+
+struct item_t {
+ const char *class;
+
+};
+
+struct verb_t {
+ const char *name;
+
+ /* toks is strtok_r's pointer */
+ void (*execute)(const char *toks);
+};
+
+typedef int room_id;
+
+/* the data we get from a world module */
+struct roomdata_t {
+ const char *uniq_id;
+ const char *name;
+ const char *desc;
+
+ const char *adjacent[NUM_DIRECTIONS];
+
+ void (*hook_init)(room_id id);
+ void (*hook_enter)(room_id room, pid_t player);
+ void (*hook_say)(room_id room, pid_t player, const char *msg);
+ void (*hook_leave)(room_id room, pid_t player);
+};
+
+struct room_t {
+ room_id id;
+ struct roomdata_t data;
+
+ room_id adjacent[NUM_DIRECTIONS];
+
+ /* arrays instead of linked lists because insertion should be rare for these */
+ struct item_t *items;
+ size_t items_sz;
+
+ struct verb_t *verbs;
+ size_t verbs_sz;
+};
+
+extern const struct roomdata_t netcosm_world[];
+extern const size_t netcosm_world_sz;
+
void client_main(int sock, struct sockaddr_in *addr, int, int to_parent, int from_parent);
void __attribute__((noreturn)) error(const char *fmt, ...);
void first_run_setup(void);
struct authinfo_t auth_check(const char*, const char*);
-/* add or change a user */
+/* add or change a user, NOT reentrant */
bool add_change_user(const char *user2, const char *pass2, int level);
bool auth_remove(const char*);
+
void telnet_handle_command(const unsigned char*);
+
#define ARRAYLEN(x) (sizeof(x)/sizeof(x[0]))
void out(const char *fmt, ...) __attribute__((format(printf,1,2)));
@@ -56,21 +141,6 @@ void telnet_echo_off(void);
void remove_cruft(char*);
-/* child<->master commands */
-/* children might not implement all of these */
-#define REQ_NOP 0
-#define REQ_BCASTMSG 1
-#define REQ_LISTCLIENTS 2
-#define REQ_CHANGESTATE 3
-#define REQ_CHANGEUSER 4
-#define REQ_HANG 5
-#define REQ_KICK 6
-
-#define STATE_INIT 0
-#define STATE_AUTH 1
-#define STATE_CHECKING 2
-#define STATE_LOGGEDIN 3
-#define STATE_ADMIN 4
-#define STATE_FAILED 5
-
void auth_list_users(void);
+void world_init(const struct roomdata_t *data, size_t sz);
+void sig_printf(const char *fmt, ...);
diff --git a/src/server.c b/src/server.c
index 46d0ac4..abbad30 100644
--- a/src/server.c
+++ b/src/server.c
@@ -36,12 +36,13 @@ void __attribute__((noreturn)) error(const char *fmt, ...)
/* assume int is atomic */
volatile int num_clients = 0;
-struct child_data {
+static struct child_data {
pid_t pid;
int readpipe[2];
int outpipe[2];
int state;
+ room_id room;
char *user;
struct in_addr addr;
@@ -50,7 +51,7 @@ struct child_data {
struct child_data *next;
} *child_data;
-void sigchld_handler(int s, siginfo_t *info, void *vp)
+static void sigchld_handler(int s, siginfo_t *info, void *vp)
{
(void) s;
(void) info;
@@ -86,15 +87,15 @@ void sigchld_handler(int s, siginfo_t *info, void *vp)
int port;
-void handle_client(int fd, struct sockaddr_in *addr,
- int num_clients, int to, int from)
+static void handle_client(int fd, struct sockaddr_in *addr,
+ int nclients, int to, int from)
{
- client_main(fd, addr, num_clients, to, from);
+ client_main(fd, addr, nclients, to, from);
}
int server_socket;
-void serv_cleanup(void)
+static void serv_cleanup(void)
{
write(STDOUT_FILENO, "Shutdown server.\n", strlen("Shutdown server.\n"));
if(shutdown(server_socket, SHUT_RDWR) > 0)
@@ -102,31 +103,28 @@ void serv_cleanup(void)
close(server_socket);
}
-void sigint_handler(int s)
+static void sigint_handler(int s)
{
(void) s;
serv_cleanup();
}
-void write_client(int child_pipe, struct child_data *iter)
-{
- char buf[128];
- printf("writing ip\n");
- char *ip = inet_ntoa(iter->addr);
- int len = snprintf(buf, sizeof(buf), "Client %s PID %d\n", ip, iter->pid);
- write(child_pipe, buf, len);
-}
-
-void req_pass_msg(unsigned char *data, size_t datalen,
+static void req_pass_msg(unsigned char *data, size_t datalen,
struct child_data *sender, struct child_data *child)
{
(void) sender;
+ if(sender->pid != child->pid)
+ {
+ unsigned char cmd = REQ_BCASTMSG;
+ write(child->outpipe[1], &cmd, 1);
+ }
+
write(child->outpipe[1], data, datalen);
kill(child->pid, SIGUSR2);
}
-void req_send_clientinfo(unsigned char *data, size_t datalen,
+static void req_send_clientinfo(unsigned char *data, size_t datalen,
struct child_data *sender, struct child_data *child)
{
(void) data;
@@ -148,29 +146,33 @@ void req_send_clientinfo(unsigned char *data, size_t datalen,
else
len = snprintf(buf, sizeof(buf), "Client %s PID %d [%s]\n",
inet_ntoa(child->addr), child->pid, state[child->state]);
- write(sender->outpipe[1], buf, len);
-}
-void req_signal_sender(struct child_data *sender)
-{
- kill(sender->pid, SIGUSR2);
+ write(sender->outpipe[1], buf, len);
}
-void req_change_state(unsigned char *data, size_t datalen,
+static void req_change_state(unsigned char *data, size_t datalen,
struct child_data *sender, struct child_data *child)
{
(void) child;
if(datalen == sizeof(sender->state))
{
sender->state = *((int*)data);
+ printf("State changed to %d\n", sender->state);
}
else
- printf("State data is of the wrong size.\n");
+ {
+ printf("State data is of the wrong size\n");
+ for(size_t i = 0; i < datalen; ++i)
+ printf("%02x\n", data[i]);
+ }
}
-void req_change_user(unsigned char *data, size_t datalen,
+static void req_change_user(unsigned char *data, size_t datalen,
struct child_data *sender, struct child_data *child)
{
+ (void) data;
+ (void) datalen;
+ (void) child;
if(sender->user)
free(sender->user);
sender->user = strdup((char*)data);
@@ -182,9 +184,10 @@ void req_change_user(unsigned char *data, size_t datalen,
// while(1);
//}
-void req_kick_client(unsigned char *data, size_t datalen,
+static void req_kick_client(unsigned char *data, size_t datalen,
struct child_data *sender, struct child_data *child)
{
+ (void) sender;
if(datalen >= sizeof(pid_t))
{
pid_t kicked_pid = *((pid_t*)data);
@@ -198,6 +201,11 @@ void req_kick_client(unsigned char *data, size_t datalen,
}
}
+static void req_wait(struct child_data *sender)
+{
+ sleep(10);
+}
+
static const struct child_request {
unsigned char code;
@@ -212,26 +220,40 @@ static const struct child_request {
void (*finalize)(struct child_data *sender);
- /* what byte to write back to the sender if != REQ_NOP */
+ /* byte to write back to the sender */
unsigned char cmd_to_send;
} requests[] = {
- { REQ_NOP, false, CHILD_NONE, NULL, NULL, REQ_NOP},
- { REQ_BCASTMSG, true, CHILD_ALL, req_pass_msg, NULL, REQ_BCASTMSG},
- { REQ_LISTCLIENTS, false, CHILD_ALL, req_send_clientinfo, req_signal_sender, REQ_BCASTMSG},
- { REQ_CHANGESTATE, true, CHILD_SENDER, req_change_state, NULL, REQ_NOP },
- { REQ_CHANGEUSER, true, CHILD_SENDER, req_change_user, NULL, REQ_NOP },
+ { REQ_NOP, false, CHILD_NONE, NULL, NULL, REQ_NOP },
+ { REQ_BCASTMSG, true, CHILD_ALL, req_pass_msg, NULL, REQ_BCASTMSG },
+ { REQ_LISTCLIENTS, false, CHILD_ALL, req_send_clientinfo, NULL, REQ_BCASTMSG },
+ { REQ_CHANGESTATE, true, CHILD_SENDER, req_change_state, NULL, REQ_NOP },
+ { REQ_CHANGEUSER, true, CHILD_SENDER, req_change_user, NULL, REQ_NOP },
//{ REQ_HANG, false, CHILD_SENDER, req_hang, NULL, REQ_NOP },
- { REQ_KICK, true, CHILD_ALL, req_kick_client, NULL, REQ_NOP },
+ { REQ_KICK, true, CHILD_ALL, req_kick_client, NULL, REQ_NOP },
+ { REQ_WAIT, false, CHILD_NONE, NULL, req_wait, REQ_NOP },
};
+void sig_printf(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+
+ char buf[128];
+ int len = vsnprintf(buf, sizeof(buf), fmt, ap);
+
+ write(STDOUT_FILENO, buf, len);
+
+ va_end(ap);
+}
+
/* SIGUSR1 is used by children to communicate with the master process */
/* the master handles commands that involve multiple children, i.e. message passing, listing clients, etc. */
-void sigusr1_handler(int s, siginfo_t *info, void *vp)
+static void sigusr1_handler(int s, siginfo_t *info, void *vp)
{
(void) s;
(void) vp;
pid_t sender_pid = info->si_pid;
- printf("PID %d sends a client request\n", sender_pid);
+ sig_printf("PID %d sends a client request\n", sender_pid);
unsigned char cmd, data[MSG_MAX + 1];
const struct child_request *req = NULL;
@@ -261,18 +283,17 @@ void sigusr1_handler(int s, siginfo_t *info, void *vp)
}
if(!req)
{
- printf("Unknown request.\n");
+ sig_printf("Unknown request.\n");
return;
}
- printf("Got command %d\n", cmd);
+ sig_printf("Got command %d\n", cmd);
if(req->havedata)
{
datalen = read(iter->readpipe[0], data, sizeof(data));
}
- if(req->cmd_to_send)
- write(sender->outpipe[1], &req->cmd_to_send, 1);
+ write(sender->outpipe[1], &req->cmd_to_send, 1);
switch(req->which)
{
@@ -321,10 +342,18 @@ void sigusr1_handler(int s, siginfo_t *info, void *vp)
finish:
- if(req->finalize)
+ if(req && req->finalize)
req->finalize(sender);
- printf("finished handling client request\n");
+ if(sender)
+ kill(sender->pid, SIGUSR2);
+ else
+ sig_printf("WARN: unknown child sent request.\n");
+
+ if(!req)
+ sig_printf("WARN: unknown request, request ignored\n");
+
+ sig_printf("finished handling client request\n");
}
void init_signals(void)
@@ -352,13 +381,17 @@ void init_signals(void)
error("sigaction");
}
-int main(int argc, char *argv[])
+static void check_userfile(void)
+{
+ if(access(USERFILE, F_OK) < 0)
+ first_run_setup();
+
+ if(access(USERFILE, R_OK | W_OK) < 0)
+ error("cannot access "USERFILE);
+}
+
+static int server_bind(void)
{
- if(argc != 2)
- port = PORT;
- else
- port = strtol(argv[1], NULL, 0);
- srand(time(0));
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock<0)
@@ -381,17 +414,27 @@ int main(int argc, char *argv[])
if(listen(sock, BACKLOG) < 0)
error("listen");
- server_socket = sock;
+ return sock;
+}
+
+int main(int argc, char *argv[])
+{
+ if(argc != 2)
+ port = PORT;
+ else
+ port = strtol(argv[1], NULL, 0);
+
+ srand(time(0));
+
+ server_socket = server_bind();
/* set up signal handlers for SIGCHLD, SIGUSR1, and SIGINT */
- /* SIGUSR1 is used for broadcast signalling */
+ /* SIGUSR1 is used for broadcast signaling */
init_signals();
- if(access(USERFILE, F_OK) < 0)
- first_run_setup();
+ check_userfile();
- if(access(USERFILE, R_OK | W_OK) < 0)
- error("cannot access "USERFILE);
+ world_init(netcosm_world, netcosm_world_sz);
child_data = NULL;
@@ -401,7 +444,7 @@ int main(int argc, char *argv[])
{
struct sockaddr_in client;
socklen_t client_len = sizeof(client);
- int new_sock = accept(sock, (struct sockaddr*) &client, &client_len);
+ int new_sock = accept(server_socket, (struct sockaddr*) &client, &client_len);
if(new_sock < 0)
error("accept");
@@ -421,9 +464,10 @@ int main(int argc, char *argv[])
if(!pid)
{
+ /* child */
close(readpipe[0]);
close(outpipe[1]);
- close(sock);
+ close(server_socket);
printf("Child with PID %d spawned\n", getpid());
diff --git a/src/telnet.c b/src/telnet.c
index 1838b45..377f5cf 100644
--- a/src/telnet.c
+++ b/src/telnet.c
@@ -37,7 +37,14 @@ void telnet_handle_command(const unsigned char *buf)
goto found;
}
}
- printf("??? ");
+ switch(c)
+ {
+ case IP:
+ exit(0);
+ default:
+ break;
+ }
+ printf("???: %d ", c);
found:
++buf;
@@ -74,8 +81,9 @@ void telnet_init(void)
IAC, DONT, NAWS,
IAC, WONT, STATUS,
IAC, DONT, STATUS,
- IAC, DO, ECHO,
+ IAC, DO, ECHO,
IAC, WONT, ECHO,
+ IAC, DONT, LINEMODE,
};
out_raw(init_seq, ARRAYLEN(init_seq));
}
diff --git a/src/telnet.h b/src/telnet.h
index 475cfce..11d1a42 100644
--- a/src/telnet.h
+++ b/src/telnet.h
@@ -1,20 +1,21 @@
/* commands */
-
-#define IAC 255
+#define IAC 255
#define DONT 254
-#define DO 253
+#define DO 253
#define WONT 252
#define WILL 251
-#define SB 250
-#define GA 249
-#define EL 248
-#define EC 247
-#define AYT 246
-#define NOP 241
-#define SE 240
+#define SB 250
+#define GA 249
+#define EL 248
+#define EC 247
+#define AYT 246
+#define IP 244
+#define NOP 241
+#define SE 240
/* options */
-#define ECHO 1
-#define SGA 3
-#define STATUS 5
-#define NAWS 31
+#define ECHO 1
+#define SGA 3
+#define STATUS 5
+#define NAWS 31
+#define LINEMODE 34