aboutsummaryrefslogtreecommitdiff
path: root/src/client.c
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2015-12-26 21:02:54 -0500
committerFranklin Wei <git@fwei.tk>2015-12-26 21:03:15 -0500
commit0a2f9197058cc5248ec8e4bed7c361397c8d1c79 (patch)
treeb4ac31dcaa64bdfded9cdb2450bf936904802d08 /src/client.c
parentf7041112f179aa79b6e315e7d57afbf76d3cd8bb (diff)
downloadnetcosm-0a2f9197058cc5248ec8e4bed7c361397c8d1c79.zip
netcosm-0a2f9197058cc5248ec8e4bed7c361397c8d1c79.tar.gz
netcosm-0a2f9197058cc5248ec8e4bed7c361397c8d1c79.tar.bz2
netcosm-0a2f9197058cc5248ec8e4bed7c361397c8d1c79.tar.xz
stuff mostly works, need to fix error on client exit
Diffstat (limited to 'src/client.c')
-rw-r--r--src/client.c79
1 files changed, 46 insertions, 33 deletions
diff --git a/src/client.c b/src/client.c
index b50e71d..090ffa1 100644
--- a/src/client.c
+++ b/src/client.c
@@ -1,3 +1,21 @@
+/*
+ * NetCosm - a MUD server
+ * Copyright (C) 2015 Franklin Wei
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
#include "netcosm.h"
static int client_fd, to_parent, from_parent;
@@ -35,35 +53,33 @@ void __attribute__((format(printf,1,2))) out(const char *fmt, ...)
static volatile sig_atomic_t request_complete;
-static void signal_master(void)
+void send_master(unsigned char cmd, const void *data, size_t sz)
{
request_complete = 0;
- sigset_t block, old;
+ sigset_t block, old;
sigemptyset(&block);
- sigaddset(&block, SIGUSR2);
+ sigaddset(&block, SIGRTMIN);
sigprocmask(SIG_BLOCK, &block, &old);
- kill(getppid(), SIGUSR1);
+ pid_t our_pid = getpid();
+ size_t total_len = (data?sz:0) + 1;
- /* wait for a signal */
- printf("Waiting for signal.\n");
+ char header[sizeof(pid_t) + sizeof(size_t) + 1];
- sigsuspend(&old);
- sigprocmask(SIG_SETMASK, &old, NULL);
+ memcpy(header, &our_pid, sizeof(pid_t));
+ memcpy(header + sizeof(pid_t), &total_len, sizeof(size_t));
+ memcpy(header + sizeof(pid_t) + sizeof(size_t), &cmd, 1);
- errno = 0;
+ write(to_parent, header, sizeof(header));
- /* spin until we're done handling the request */
- while(!request_complete) usleep(1);
-}
-
-void send_master(unsigned char cmd, const void *data, size_t sz)
-{
- write(to_parent, &cmd, 1);
if(data)
write(to_parent, data, sz);
- signal_master();
+
+ sigsuspend(&old);
+ sigprocmask(SIG_SETMASK, &old, NULL);
+
+ while(!request_complete) usleep(1);
}
#define BUFSZ 128
@@ -92,7 +108,7 @@ tryagain:
return buf;
}
-/* still not encrypted, but a bit more secure than echoing the pass */
+/* still not encrypted, but a bit more secure than echoing the password! */
char *client_read_password(void)
{
telnet_echo_off();
@@ -111,17 +127,16 @@ void all_upper(char *s)
}
}
-void sigusr2_handler(int s, siginfo_t *info, void *vp)
+void sig_rt_0_handler(int s, siginfo_t *info, void *v)
{
(void) s;
- (void) vp;
-
- sig_printf("PID %d got SIGUSR2\n", getpid());
+ (void) v;
+ sig_printf("PID %d got SIGRTMIN+1\n", getpid());
/* we only listen to requests from our parent */
if(info->si_pid != getppid())
{
- sig_printf("Unknown PID sent SIGUSR2\n");
+ sig_printf("Unknown PID sent SIGRTMIN+1\n");
return;
}
@@ -145,6 +160,9 @@ void sigusr2_handler(int s, siginfo_t *info, void *vp)
ssize_t len = read(from_parent, buf, MSG_MAX);
buf[MSG_MAX] = '\0';
out_raw(buf, len);
+ union sigval junk;
+ /* the master still expects an ACK */
+ sigqueue(getppid(), SIGRTMIN+1, junk);
exit(EXIT_SUCCESS);
}
case REQ_MOVE:
@@ -165,6 +183,10 @@ void sigusr2_handler(int s, siginfo_t *info, void *vp)
sig_printf("Client finishes handling request.\n");
request_complete = 1;
+
+ /* signal the master that we're done */
+ union sigval junk;
+ sigqueue(getppid(), SIGRTMIN+1, junk);
}
static void client_change_state(int state)
@@ -246,15 +268,6 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from)
output_locked = 0;
- 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();
char *ip = inet_ntoa(addr->sin_addr);
@@ -334,7 +347,7 @@ auth:
char *tok = strtok_r(cmd, WSPACE, &save);
if(!tok)
- continue;
+ goto next_cmd;
all_upper(tok);
if(admin)