More code.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore Wed Mar 21 23:37:25 2007 +0100
@@ -0,0 +1,4 @@
+^.*\.o$
+core
+test
+\.exrc
--- a/Makefile Wed Mar 21 21:01:36 2007 +0100
+++ b/Makefile Wed Mar 21 23:37:25 2007 +0100
@@ -1,3 +1,3 @@
CFLAGS=-g
-test: main.o server.o server_start.o client.o
+test: main.o server.o server_start.o client.o msgdump.o jobs.o
gcc -o test $^
--- a/client.c Wed Mar 21 21:01:36 2007 +0100
+++ b/client.c Wed Mar 21 23:37:25 2007 +0100
@@ -1,7 +1,53 @@
#include <assert.h>
#include "msg.h"
+#include "main.h"
-int shutdown_server()
+void c_new_job(const char *command)
+{
+ struct msg m;
+ int res;
+
+ m.type = NEWJOB;
+
+ strcpy(m.u.command, command);
+
+ res = write(server_socket, &m, sizeof(m));
+ if(res == -1)
+ perror("write");
+}
+
+void c_wait_server_commands()
+{
+ struct msg m;
+ int res;
+
+ while (1)
+ {
+ res = read(server_socket, &m, sizeof(m));
+ if(res == -1)
+ perror("read");
+
+ if (res == 0)
+ break;
+ assert(res == sizeof(m));
+ if (m.type == NEWJOB_OK)
+ ;
+ }
+}
+
+void c_list_jobs(const char *command)
+{
+ struct msg m;
+ int res;
+
+ m.type = LIST;
+
+ res = write(server_socket, &m, sizeof(m));
+ if(res == -1)
+ perror("write");
+}
+
+int c_shutdown_server()
{
struct msg m;
int res;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jobs.c Wed Mar 21 23:37:25 2007 +0100
@@ -0,0 +1,99 @@
+#include <assert.h>
+#include "msg.h"
+
+struct Job
+{
+ int jobid;
+ char command[CMD_LEN];
+ enum Jobstate state;
+ struct Job *next;
+};
+
+/* Globals */
+static struct Job *firstjob = 0;
+static jobids = 0;
+
+void s_list(int s)
+{
+ int i;
+ struct Job *p;
+
+ printf("ID\tState\tCommand\n");
+
+ p = firstjob;
+
+ while(p != 0)
+ {
+ printf("%i\t", p->jobid);
+ printf("%i\t", p->state);
+ printf("%s\n", p->command);
+ p = p->next;
+ }
+}
+
+static struct Job * newjobptr()
+{
+ struct Job *p;
+
+ if (firstjob == 0)
+ {
+ firstjob = (struct Job *) malloc(sizeof(*firstjob));
+ firstjob->next = 0;
+ return firstjob;
+ }
+
+ p = firstjob;
+ while(p->next != 0)
+ p = p->next;
+
+ p->next = (struct Job *) malloc(sizeof(*p));
+ p->next->next = 0;
+
+ return p->next;
+}
+
+/* Returns job id */
+int s_newjob(struct msg *m)
+{
+ struct Job *p;
+
+ p = newjobptr();
+
+ p->jobid = jobids++;
+ p->state = QUEUED;
+ strcpy(p->command, m->u.command);
+
+ return p->jobid;
+}
+
+void s_removejob(int jobid)
+{
+ struct Job *p;
+ struct Job *newnext;
+
+ printf("Remove job %i\n", jobid);
+ if (firstjob->jobid == jobid)
+ {
+ struct Job *newfirst;
+ /* First job is to be removed */
+ newfirst = firstjob->next;
+ free(firstjob);
+ firstjob = newfirst;
+ return;
+ }
+
+ p = firstjob;
+ /* Not first job */
+ while (p->next != 0)
+ {
+ if (p->next->jobid == jobid)
+ break;
+ p = p->next;
+ }
+ assert(p->next != 0);
+
+ newnext = p->next->next;
+
+ free(p->next);
+ p->next = newnext;
+}
--- a/main.c Wed Mar 21 21:01:36 2007 +0100
+++ b/main.c Wed Mar 21 23:37:25 2007 +0100
@@ -2,21 +2,26 @@
#include <stdio.h>
+#include "main.h"
+
extern char *optarg;
extern int optind, opterr, optopt;
int kill_server = 0;
int need_server = 0;
+int list_jobs = 0;
int server_socket;
+char *new_command = 0;
+
void parse_opts(int argc, char **argv)
{
int c;
/* Parse options */
while(1) {
- c = getopt(argc, argv, "k");
+ c = getopt(argc, argv, "kl");
if (c == -1)
break;
@@ -26,10 +31,18 @@
case 'k':
kill_server = 1;
break;
+ case 'l':
+ list_jobs = 1;
+ break;
}
}
- if (kill_server == 0)
+ if (optind < argc)
+ {
+ new_command = argv[optind];
+ }
+
+ if (list_jobs || kill_server || (new_command != 0))
need_server = 1;
}
@@ -37,18 +50,24 @@
{
parse_opts(argc, argv);
- need_server = 1;
+ if (need_server)
+ ensure_server_up();
+
+ if (new_command != 0)
+ {
+ c_new_job(new_command);
+ c_wait_server_commands();
+ }
+
+ if (list_jobs != 0)
+ c_list_jobs(new_command);
+
+ if (kill_server)
+ c_shutdown_server();
if (need_server)
{
- fprintf(stderr, "Ensure server up.\n");
- ensure_server_up();
- }
-
- if (kill_server)
- {
- printf("Trying to kill server.\n");
- shutdown_server();
+ close(server_socket);
}
return 0;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.h Wed Mar 21 23:37:25 2007 +0100
@@ -0,0 +1,26 @@
+
+
+struct msg;
+
+/* client.c */
+void c_new_job(const char *command);
+void c_wait_server_commands();
+void c_list_jobs(const char *command);
+int c_shutdown_server();
+
+/* jobs.c */
+void s_list(int s);
+int s_newjob(struct msg *m);
+void s_removejob(int jobid);
+
+/* msgdump.c */
+void msgdump(const struct msg *m);
+
+/* server.c */
+void server_main();
+
+/* server_start.c */
+int try_connect(int s);
+void wait_server_up();
+void fork_server();
+int ensure_server_up();
--- a/msg.h Wed Mar 21 21:01:36 2007 +0100
+++ b/msg.h Wed Mar 21 23:37:25 2007 +0100
@@ -1,8 +1,18 @@
extern int server_socket;
+enum
+{
+ CMD_LEN=500
+};
+
enum msg_types
{
- KILL
+ KILL,
+ NEWJOB,
+ NEWJOB_OK,
+ RUNJOB,
+ ENDJOB,
+ LIST,
};
struct msg
@@ -11,8 +21,19 @@
union
{
- int data1;
- int data2;
+ char command[CMD_LEN];
+ int jobid;
+ int errorlevel;
} u;
};
+
+enum Jobstate
+{
+ QUEUED,
+ RUNNING,
+ FINISHED,
+};
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/msgdump.c Wed Mar 21 23:37:25 2007 +0100
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include "msg.h"
+#include "main.h"
+
+void msgdump(const struct msg *m)
+{
+ printf("msgdump:\n");
+ switch(m->type)
+ {
+ case KILL:
+ printf(" KILL\n");
+ break;
+ case NEWJOB:
+ printf(" NEWJOB\n");
+ printf(" Command: '%s'\n", m->u.command);
+ break;
+ case NEWJOB_OK:
+ printf(" NEWJOB_OK\n");
+ printf(" JobID: '%s'\n", m->u.jobid);
+ break;
+ case RUNJOB:
+ printf(" RUNJOB\n");
+ break;
+ case ENDJOB:
+ printf(" ENDJOB\n");
+ break;
+ case LIST:
+ printf(" LIST\n");
+ break;
+ }
+}
--- a/server.c Wed Mar 21 21:01:36 2007 +0100
+++ b/server.c Wed Mar 21 23:37:25 2007 +0100
@@ -3,10 +3,12 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
+#include <string.h>
#include <stdio.h>
#include "msg.h"
+#include "main.h"
const char path[] = "/tmp/prova.socket";
@@ -21,10 +23,22 @@
NOBREAK
};
-void server_loop(int ls);
-enum Break
-client_read(int index, int *connections, int *nconnections);
-void end_server(int ls);
+/* Prototypes */
+static void server_loop(int ls);
+static enum Break
+ client_read(int index);
+static void end_server(int ls);
+
+struct Client_conn
+{
+ int socket;
+ int hasjob;
+ int jobid;
+};
+
+/* Globals */
+static struct Client_conn client_cs[MAXCONN];
+static int nconnections;
void server_main()
{
@@ -32,6 +46,8 @@
struct sockaddr_un addr;
int res;
+ nconnections = 0;
+
ls = socket(PF_UNIX, SOCK_STREAM, 0);
assert(ls != -1);
@@ -52,15 +68,12 @@
return;
}
- printf("server loop\n");
server_loop(ls);
}
-void server_loop(int ls)
+static void server_loop(int ls)
{
fd_set readset;
- int connections[MAXCONN];
- int nconnections;
int i;
int maxfd;
int keep_loop = 1;
@@ -72,26 +85,24 @@
maxfd = ls;
for(i=0; i< nconnections; ++i)
{
- FD_SET(connections[i], &readset);
- if (connections[i] > maxfd)
- maxfd = connections[i];
+ FD_SET(client_cs[i].socket, &readset);
+ if (client_cs[i].socket > maxfd)
+ maxfd = client_cs[i].socket;
}
- printf("select: nc = %i\n", nconnections);
+ printf("select of %i\n", nconnections);
select(maxfd + 1, &readset, NULL, NULL, NULL);
- printf("Select unblocks\n");
if (FD_ISSET(ls,&readset))
{
int cs;
cs = accept(ls, NULL, NULL);
assert(cs != -1);
- connections[nconnections++] = cs;
+ client_cs[nconnections++].socket = cs;
}
for(i=0; i< nconnections; ++i)
- if (FD_ISSET(connections[i], &readset))
+ if (FD_ISSET(client_cs[i].socket, &readset))
{
enum Break b;
- b = client_read(i, connections,
- &nconnections);
+ b = client_read(i);
/* Check if we should break */
if (b == BREAK)
keep_loop = 0;
@@ -101,46 +112,65 @@
end_server(ls);
}
-void end_server(int ls)
+static void end_server(int ls)
{
close(ls);
unlink(path);
}
-void remove_connection(int index, int *connections, int *nconnections)
+static void remove_connection(int index)
{
int i;
- for(i=index; i<(*nconnections-1); ++i)
+
+ if(client_cs[index].hasjob)
{
- connections[i] = connections[i+1];
+ printf("s: removing job [%i] %i\n", index, client_cs[index].jobid);
+ s_removejob(client_cs[index].jobid);
}
- (*nconnections)--;
+
+ for(i=index; i<(nconnections-1); ++i)
+ {
+ memcpy(&client_cs[i], &client_cs[i+1], sizeof(client_cs[0]));
+ }
+ nconnections--;
}
-enum Break
-client_read(int index, int *connections, int *nconnections)
+
+static enum Break
+ client_read(int index)
{
- struct msg data;
+ struct msg m;
int s;
int res;
- s = connections[index];
+ s = client_cs[index].socket;
/* Read the message */
- res = read(s, &data, sizeof(data));
+ res = read(s, &m, sizeof(m));
assert(res != -1);
if (res == 0)
{
close(s);
- remove_connection(index, connections, nconnections);
+ remove_connection(index);
return NOBREAK;
}
- printf("recv. data.type = %i\n", data.type);
+ client_cs[index].hasjob = 0;
+
+ msgdump(&m);
/* Process message */
- if (data.type == KILL)
+ if (m.type == KILL)
return BREAK; /* break in the parent*/
+ if (m.type == NEWJOB)
+ {
+ client_cs[index].jobid = s_newjob(&m);
+ client_cs[index].hasjob = 1;
+ }
+
+ if (m.type == LIST)
+ s_list(index);
+
return NOBREAK; /* normal */
}
--- a/server_start.c Wed Mar 21 21:01:36 2007 +0100
+++ b/server_start.c Wed Mar 21 23:37:25 2007 +0100
@@ -3,6 +3,9 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
+#include <stdlib.h>
+
+#include "main.h"
extern int server_socket;
@@ -34,7 +37,9 @@
switch (pid)
{
case 0: /* Child */
+ close(server_socket);
server_main();
+ exit(0);
break;
case -1: /* Error */
return;
@@ -57,9 +62,12 @@
return 1;
/* If error other than "No one listens on the other end"... */
- if (errno != ENOENT)
+ if (!(errno == ENOENT || errno == ECONNREFUSED))
return 0;
+ if (errno == ECONNREFUSED)
+ unlink("/tmp/prova.socket");
+
/* Try starting the server */
fork_server();
wait_server_up();