aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2014-04-22 01:21:07 +0200
committerMattias Andrée <maandree@operamail.com>2014-04-22 01:21:07 +0200
commit8961e2d562cdcd5ed0bfbc3d6e4addf6e8bff5fa (patch)
tree1f97a3485f22b78827bd2339dc96a1be726cac64
parentrun mdsinitrc (diff)
downloadmds-8961e2d562cdcd5ed0bfbc3d6e4addf6e8bff5fa.tar.gz
mds-8961e2d562cdcd5ed0bfbc3d6e4addf6e8bff5fa.tar.bz2
mds-8961e2d562cdcd5ed0bfbc3d6e4addf6e8bff5fa.tar.xz
m + accept incoming connections
Signed-off-by: Mattias Andrée <maandree@operamail.com>
-rw-r--r--Makefile2
-rw-r--r--src/mds-server.c254
-rw-r--r--src/mds-server.h16
3 files changed, 206 insertions, 66 deletions
diff --git a/Makefile b/Makefile
index eafecdb..196258c 100644
--- a/Makefile
+++ b/Makefile
@@ -56,7 +56,7 @@ STD = gnu99
C_FLAGS = $(OPTIMISE) $(WARN) -std=$(STD) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) \
-ftree-vrp -fstrict-aliasing -fipa-pure-const -fstack-usage \
-fstrict-overflow -funsafe-loop-optimizations -fno-builtin \
- -D_GNU_SOURCE
+ -D_GNU_SOURCE -pthread
# Build rules.
diff --git a/src/mds-server.c b/src/mds-server.c
index c829ecc..1ef31c0 100644
--- a/src/mds-server.c
+++ b/src/mds-server.c
@@ -25,6 +25,10 @@
#include <limits.h>
#include <unistd.h>
#include <pwd.h>
+#include <errno.h>
+#include <pthread.h>
+#include <sys/socket.h>
+
/**
@@ -39,6 +43,32 @@ static char** argv;
/**
+ * The program run state, 1 when running,
+ * 0 when shutting down
+ */
+static volatile int running = 1;
+
+/**
+ * The number of running slaves
+ */
+static int running_slaves = 0;
+
+/**
+ * Mutex for slave counter
+ */
+static pthread_mutex_t slave_mutex;
+
+/**
+ * Condition for slave counter
+ */
+static pthread_cond_t slave_cond;
+
+
+
+/* TODO make the server update without all slaves dying on SIGUSR1 */
+
+
+/**
* Entry point of the server
*
* @param argc_ Number of elements in `argv_`
@@ -53,6 +83,7 @@ int main(int argc_, char** argv_)
char* unparsed_args[ARGC_LIMIT + LIBEXEC_ARGC_EXTRA_LIMIT + 1];
int i;
pid_t pid;
+ pthread_t _slave_thread;
argc = argc_;
@@ -155,83 +186,99 @@ int main(int argc_, char** argv_)
}
if (pid == 0) /* Child process exec:s, the parent continues without waiting for it. */
{
- char pathname[PATH_MAX];
- struct passwd* pwd;
- char* env;
- char* home;
- unparsed_args[0] = pathname;
-
- /* Test $XDG_CONFIG_HOME. */
- if ((env = getenv_nonempty("XDG_CONFIG_HOME")) != NULL)
- {
- snprintf(pathname, sizeof(pathname) / sizeof(char), "%s/.%s", env, INITRC_FILE);
- execv(unparsed_args[0], unparsed_args);
- }
-
- /* Test $HOME. */
- if ((env = getenv_nonempty("HOME")) != NULL)
+ run_initrc(unparsed_args);
+ return 1;
+ }
+ }
+
+
+ /* Create mutex and condition for slave counter. */
+ pthread_mutex_init(&slave_mutex, NULL);
+ pthread_cond_init(&slave_cond, NULL);
+
+
+ /* Accepting incoming connections. */
+ while (running)
+ {
+ /* Accept connection. */
+ int client_fd = accept(socket_fd, NULL, NULL);
+
+ /* Handle errors and shutdown. */
+ if (client_fd == -1)
+ {
+ switch (errno)
{
- snprintf(pathname, sizeof(pathname) / sizeof(char), "%s/.config/%s", env, INITRC_FILE);
- execv(unparsed_args[0], unparsed_args);
+ case EINTR:
+ /* Interrupted. */
+ break;
- snprintf(pathname, sizeof(pathname) / sizeof(char), "%s/.%s", env, INITRC_FILE);
- execv(unparsed_args[0], unparsed_args);
- }
-
- /* Test ~. */
- pwd = getpwuid(getuid()); /* Ignore error. */
- if (pwd != NULL)
- {
- home = pwd->pw_dir;
- if ((home != NULL) && (*home != '\0'))
- {
- snprintf(pathname, sizeof(pathname) / sizeof(char), "%s/.config/%s", home, INITRC_FILE);
- execv(unparsed_args[0], unparsed_args);
-
- snprintf(pathname, sizeof(pathname) / sizeof(char), "%s/.%s", home, INITRC_FILE);
- execv(unparsed_args[0], unparsed_args);
- }
- }
-
- /* Test $XDG_CONFIG_DIRS. */
- if ((env = getenv_nonempty("XDG_CONFIG_DIRS")) != NULL)
- {
- char* begin = env;
- char* end;
- int len;
- for (;;)
- {
- end = strchrnul(begin, ':');
- len = (int)(end - begin);
- if (len > 0)
- {
- snprintf(pathname, sizeof(pathname) / sizeof(char), "%.*s/%s", len, begin, INITRC_FILE);
- execv(unparsed_args[0], unparsed_args);
- }
- if (*end == '\0')
- break;
- begin = end + 1;
- }
+ case ECONNABORTED:
+ case EINVAL:
+ /* Closing. */
+ running = 0;
+ break;
+
+ default:
+ /* Error. */
+ perror(*argv);
+ break;
}
-
- /* Test /etc. */
- snprintf(pathname, sizeof(pathname) / sizeof(char), "%s/%s", SYSCONFDIR, INITRC_FILE);
- execv(unparsed_args[0], unparsed_args);
-
- /* Everything failed. */
- fprintf(stderr,
- "%s: unable to run %s file, you might as well kill me.\n",
- *argv, INITRC_FILE);
- return 1;
+ continue;
+ }
+
+ /* Increase number of running slaves. */
+ pthread_mutex_lock(&slave_mutex);
+ running_slaves++;
+ pthread_mutex_unlock(&slave_mutex);
+
+ /* Start slave thread. */
+ errno = pthread_create(&_slave_thread, NULL, slave_loop, (void*)(intptr_t)client_fd);
+ if (errno)
+ {
+ perror(*argv);
+ pthread_mutex_lock(&slave_mutex);
+ running_slaves--;
+ pthread_mutex_unlock(&slave_mutex);
}
}
+ /* Wait for all slaves to close. */
+ pthread_mutex_lock(&slave_mutex);
+ while (running_slaves > 0)
+ pthread_cond_wait(&slave_cond, &slave_mutex);
+ pthread_mutex_unlock(&slave_mutex);
+
return 0;
}
/**
+ * Master function for slave threads
+ *
+ * @param data Input data
+ * @return Outout data
+ */
+void* slave_loop(void* data)
+{
+ int socket_fd = (int)(intptr_t)data;
+
+ /* TODO */
+
+ /* Close socket. */
+ close(socket_fd);
+
+ /* Decrease the slave count. */
+ pthread_mutex_lock(&slave_mutex);
+ running_slaves--;
+ pthread_cond_signal(&slave_cond);
+ pthread_mutex_unlock(&slave_mutex);
+
+ return NULL;
+}
+
+
+/**
* Read an environment variable, but handle it as undefined if empty
*
* @param var The environment variable's name
@@ -245,3 +292,80 @@ char* getenv_nonempty(const char* var)
return rc;
}
+
+/**
+ * Exec into the mdsinitrc script
+ *
+ * @param args The arguments to the child process
+ */
+void run_initrc(char** args)
+{
+ char pathname[PATH_MAX];
+ struct passwd* pwd;
+ char* env;
+ char* home;
+ args[0] = pathname;
+
+
+ /* Test $XDG_CONFIG_HOME. */
+ if ((env = getenv_nonempty("XDG_CONFIG_HOME")) != NULL)
+ {
+ snprintf(pathname, sizeof(pathname) / sizeof(char), "%s/.%s", env, INITRC_FILE);
+ execv(args[0], args);
+ }
+
+ /* Test $HOME. */
+ if ((env = getenv_nonempty("HOME")) != NULL)
+ {
+ snprintf(pathname, sizeof(pathname) / sizeof(char), "%s/.config/%s", env, INITRC_FILE);
+ execv(args[0], args);
+
+ snprintf(pathname, sizeof(pathname) / sizeof(char), "%s/.%s", env, INITRC_FILE);
+ execv(args[0], args);
+ }
+
+ /* Test ~. */
+ pwd = getpwuid(getuid()); /* Ignore error. */
+ if (pwd != NULL)
+ {
+ home = pwd->pw_dir;
+ if ((home != NULL) && (*home != '\0'))
+ {
+ snprintf(pathname, sizeof(pathname) / sizeof(char), "%s/.config/%s", home, INITRC_FILE);
+ execv(args[0], args);
+
+ snprintf(pathname, sizeof(pathname) / sizeof(char), "%s/.%s", home, INITRC_FILE);
+ execv(args[0], args);
+ }
+ }
+
+ /* Test $XDG_CONFIG_DIRS. */
+ if ((env = getenv_nonempty("XDG_CONFIG_DIRS")) != NULL)
+ {
+ char* begin = env;
+ char* end;
+ int len;
+ for (;;)
+ {
+ end = strchrnul(begin, ':');
+ len = (int)(end - begin);
+ if (len > 0)
+ {
+ snprintf(pathname, sizeof(pathname) / sizeof(char), "%.*s/%s", len, begin, INITRC_FILE);
+ execv(args[0], args);
+ }
+ if (*end == '\0')
+ break;
+ begin = end + 1;
+ }
+ }
+
+ /* Test /etc. */
+ snprintf(pathname, sizeof(pathname) / sizeof(char), "%s/%s", SYSCONFDIR, INITRC_FILE);
+ execv(args[0], args);
+
+
+ /* Everything failed. */
+ fprintf(stderr, "%s: unable to run %s file, you might as well kill me.\n", *argv, INITRC_FILE);
+}
+
diff --git a/src/mds-server.h b/src/mds-server.h
index c27498a..cad1fb1 100644
--- a/src/mds-server.h
+++ b/src/mds-server.h
@@ -19,6 +19,15 @@
#define MDS_MDS_SERVER_H
+
+/**
+ * Master function for slave threads
+ *
+ * @param data Input data
+ * @return Outout data
+ */
+void* slave_loop(void* data);
+
/**
* Read an environment variable, but handle it as undefined if empty
*
@@ -27,6 +36,13 @@
*/
char* getenv_nonempty(const char* var);
+/**
+ * Exec into the mdsinitrc script
+ *
+ * @param args The arguments to the child process
+ */
+void run_initrc(char** args);
+
#endif