[mw-devel] MW3 r1172 - in trunk/src: . webclient

arthur at sucs.org arthur at sucs.org
Mon Oct 4 16:48:18 BST 2010


Author: arthur
Date: 2010-10-04 16:48:18 +0100 (Mon, 04 Oct 2010)
New Revision: 1172

Added:
   trunk/src/webclient/
   trunk/src/webclient/Makefile
   trunk/src/webclient/comms.c
   trunk/src/webclient/comms.h
   trunk/src/webclient/import.c
   trunk/src/webclient/import.h
   trunk/src/webclient/list.h
   trunk/src/webclient/mwpoll.c
Log:
early stages of web client


Added: trunk/src/webclient/Makefile
===================================================================
--- trunk/src/webclient/Makefile	                        (rev 0)
+++ trunk/src/webclient/Makefile	2010-10-04 15:48:18 UTC (rev 1172)
@@ -0,0 +1,70 @@
+libdir := /usr/lib
+localstatedir := /var
+
+LOGDIR := $(localstatedir)/log/mw
+MSGDIR := $(localstatedir)/run/mw
+STATEDIR := $(localstatedir)/lib/mw
+HOMEPATH := $(libdir)/mw
+
+# cflags for standard 'cc' compiler
+CFLAGS+= -Wall -pedantic -fpie -std=gnu99 -D_GNU_SOURCE -I..
+LDFLAGS+= -pie
+LDLIBS+=
+
+# info strings, do not edit.
+DEFS:= -DBUILD_DATE=\"$(shell date +%Y%m%d)\"
+DEFS+= -DBUILD_USER=\"$(shell whoami | awk -f ../capitalise.awk)\"
+DEFS+= -DVER_MAJ=\"$(VERSION_MAJOR)\"
+DEFS+= -DVER_MIN=\"$(VERSION_MINOR)\"
+DEFS+= -DVER_TWK=\"$(VERSION_TWEAK)\"
+DEFS+= -DHOMEPATH=\"$(HOMEPATH)\"
+DEFS+= -DLOGDIR=\"$(LOGDIR)\"
+DEFS+= -DSTATEDIR=\"$(STATEDIR)\"
+DEFS+= -DMSGDIR=\"$(MSGDIR)\"
+
+### uncomment for gdb debugging
+LDFLAGS+= -ggdb -g
+CFLAGS+= -ggdb -g -D__NO_STRING_INLINE -fstack-protector-all -std=c99
+
+### Optimisation - uncomment for release & extra testing
+CFLAGS+=-O3
+
+### Only ever uncomment for final release versions
+DEFS+= -DRELEASE
+
+CFLAGS += $(DEFS)
+
+build: mwpoll
+
+### The magic which lets us autogenerate dependencies
+CFLAGS += -MMD
+
+CODE=$(wildcard *.c)
+HDRS=$(wildcard *.h)
+
+%.o: %.c
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+-include $(CODE:.c=.d)
+
+.PHONY: build install clean test
+
+mwpoll: mwpoll.o import.o comms.o ../perms.o ../strings.o ../files.o
+	$(CC) $(LDFLAGS) $(LDLIBS) -o $@ $^
+
+clean:
+	-rm -f *.o *.d mwpoll
+
+ifndef TESTDIR
+test:
+	make TESTDIR=$(CURDIR)/mwtest $@
+else
+test:
+	mkdir -p "$(TESTDIR)"
+	cd "$(TESTDIR)" && mkdir -p mw run/mw log/mw lib/mw
+	for d in $(INSTALLFILES); do \
+		svn export --force ../$$d "$(TESTDIR)/mw/$$d"; \
+	done
+	make libdir="$(TESTDIR)" localstatedir="$(TESTDIR)"
+
+endif

Added: trunk/src/webclient/comms.c
===================================================================
--- trunk/src/webclient/comms.c	                        (rev 0)
+++ trunk/src/webclient/comms.c	2010-10-04 15:48:18 UTC (rev 1172)
@@ -0,0 +1,307 @@
+#include <files.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <strings.h>
+
+#include <talker_privs.h>
+#include <ipc.h>
+#include <perms.h>
+#include <bb.h>
+#include "import.h"
+#include "comms.h"
+#include "list.h"
+
+extern int incoming_pipe;
+int command_sock;
+
+static int die = 0;
+
+#define min(a,b) a<b?a:b
+#define max(a,b) a>b?a:b
+
+#define UNIX_PATH_MAX 108
+
+typedef struct {
+	struct list_head list;
+	enum ipc_types state;
+	int pid;
+	struct person user;
+	char *text;
+} MESG;
+
+
+static struct list_head msglist;
+
+typedef struct {
+	struct list_head list;
+	int fd;
+} CONNECTION;
+
+struct list_head connlist;
+
+/* unix socket to accept control commands from */
+void open_command_socket()
+{
+	struct sockaddr_un sa;
+	command_sock = socket(PF_UNIX, SOCK_SEQPACKET, 0);
+	if (command_sock == -1) {
+		fprintf(stderr, "Error creating socket: %s\n", strerror(errno));
+		exit(1);
+	}
+	sa.sun_family = AF_UNIX;
+	snprintf(sa.sun_path, UNIX_PATH_MAX, "/tmp/mwnoddy.%d", getpid());
+	if (bind(command_sock, &sa, sizeof(sa))) {
+		fprintf(stderr, "Error binding %s: %s\n", sa.sun_path, strerror(errno));
+		close(command_sock);
+		command_sock = -1;
+		exit(1);
+	}
+	chmod(sa.sun_path, 0777);
+
+	if (listen(command_sock, 1)) {
+		fprintf(stderr, "Error listening on socket: %s\n", strerror(errno));
+		exit(1);
+	}
+
+	INIT_LIST_HEAD(&msglist);
+	INIT_LIST_HEAD(&connlist);
+}
+
+
+/* we got a message */
+void accept_pipe_cmd(enum ipc_types state, char *newbuff, int mesg_pid, struct person *mesg_user)
+{
+	MESG *msg = malloc(sizeof(MESG));
+	msg->state = state;
+	msg->pid = mesg_pid;
+	msg->user = *mesg_user;
+	msg->text = strdup(newbuff);
+
+	list_add_tail(&msg->list, &msglist);
+
+	printf("From=%s type=%d msg='%s'\n", mesg_user->name, state, newbuff);
+
+}
+
+static void accept_new(void)
+{
+	CONNECTION *new = malloc(sizeof(CONNECTION));
+	struct sockaddr sa;
+	socklen_t sal = sizeof(sa);
+	new->fd = accept(command_sock, &sa, &sal);
+	if (new->fd == -1) {
+		fprintf(stderr, "Error on accept: %s\n", strerror(errno));
+		free(new);
+		return;
+	}
+	list_add(&(new->list), &connlist);
+	printf("Adding connection fd %d\n", new->fd);
+}
+
+int mainloop(int millis)
+{
+	fd_set readfds, exceptfds;
+	static struct timeval tmout;
+	int nfds;
+	int ret;
+	int select_error;
+	struct list_head *pos, *q;
+
+        FD_ZERO(&readfds);
+        FD_ZERO(&exceptfds);
+        FD_SET(incoming_pipe, &readfds);
+        FD_SET(incoming_pipe, &exceptfds);
+        FD_SET(command_sock, &readfds);
+        FD_SET(command_sock, &exceptfds);
+
+	nfds = max(incoming_pipe, command_sock);
+
+	list_for_each(pos, &connlist) {
+		CONNECTION *co = list_entry(pos, CONNECTION, list);
+		FD_SET(co->fd, &readfds);
+		FD_SET(co->fd, &exceptfds);
+		nfds = max(nfds, co->fd);
+	}
+	nfds += 1;
+
+        if (millis >= 0)
+        {
+                tmout.tv_sec = millis / 1000;
+                tmout.tv_usec = (millis % 1000) * 1000;
+        }
+        ret = select(nfds, &readfds, NULL, &exceptfds, (millis<0)?(NULL):(&tmout));
+        select_error = errno;
+        if (ret > 0) {
+                if (FD_ISSET(incoming_pipe, &exceptfds)) {
+                        fprintf(stderr, "\nError reading incoming message pipe. panic.\n");
+                        return -1;
+                }
+                if (FD_ISSET(command_sock, &exceptfds)) {
+                        fprintf(stderr, "\nError on command socket, argh.\n");
+                        return -1;
+                }
+                if (FD_ISSET(incoming_pipe, &readfds))
+                       handle_mesg();
+                if (FD_ISSET(command_sock, &readfds)) {
+			accept_new();
+		}
+		list_for_each_safe(pos, q, &connlist) {
+			CONNECTION *co = list_entry(pos, CONNECTION, list);
+			if (FD_ISSET(co->fd, &exceptfds)) {
+				printf("Dropping connection fd=%d\n", co->fd);
+				list_del(pos);
+				close(co->fd);
+				free(co);
+			}else
+			if (FD_ISSET(co->fd, &readfds)) {
+				if (handle_command(co->fd)) {
+					printf("Finishing connection fd=%d\n", co->fd);
+					list_del(pos);
+					close(co->fd);
+					free(co);
+				}
+			}
+		}
+        }
+
+        errno = select_error;
+        if (ret<0 && select_error == EINVAL)
+        {
+                char buf[256];
+                snprintf(buf, sizeof buf, "\n{EINVAL: command_sock=%d, incoming_pipe=%d}\n", command_sock, incoming_pipe);
+		fwrite(buf, strlen(buf), 1, stderr);
+        }
+	if (die) return -1; else
+        if (nfds < 0) return nfds; else 
+		return 0;
+}
+
+int handle_command(int sock)
+{
+	/* read and answer the command socket */
+	char buff[8192];
+	int ret;
+
+	if ((ret = recv(sock, buff, sizeof buff, MSG_DONTWAIT))<0) {
+		fprintf(stderr, "Error on cmd sock read: %s\n", strerror(errno));
+		return 1;
+	}
+
+	if (strcasecmp(buff, "quit")==0) {
+		snprintf(buff, sizeof buff, "BYE");
+		send(sock, buff, strlen(buff), 0);
+		die = 1;
+		return 1;
+	}else
+	if (strcasecmp(buff, "fetch")==0) {
+		MESG *tmp;
+		struct list_head *pos, *q;
+		int len;
+
+		buff[0] = 0;
+		int n=0;
+		snprintf(buff, sizeof buff, "[");
+		list_for_each_safe(pos, q, &msglist) {
+			tmp = list_entry(pos, MESG, list);
+			list_del(pos);
+
+			len = strlen(buff);
+			snprintf(&buff[len], sizeof(buff)-len, "{\"state\":%d,\"pid\":%d,\"username\":\"%s\",\"text\":\"%s\"}", tmp->state, tmp->pid, tmp->user.name, tmp->text);
+			free(tmp->text);
+			free(tmp);
+			n++;
+		}
+		len = strlen(buff);
+		snprintf(&buff[len], sizeof(buff)-len, "]");
+
+		send(sock, buff, strlen(buff), 0);
+		return 1;
+	}
+	return 0;
+}
+
+void handle_mesg()
+{
+        static uint32_t mesg_pid;
+        long mesg_posn;
+        static struct person mesg_user;
+	int fl;
+
+        int nos,i;
+        char buff[MAXTEXTLENGTH];
+        static char newbuff[MAXPIPELENGTH];
+        static char pidbuff[4];
+        static int ptr=0;
+        static int pidp=0;
+        static int midread = 0;
+        static int quotemode=0;
+        enum ipc_types msgtype = IPC_NOOP;
+
+	fl = fcntl(incoming_pipe, F_GETFL);
+	fcntl(incoming_pipe, F_SETFL, fl | O_NDELAY);
+
+        while ((nos=read(incoming_pipe,buff,MAXTEXTLENGTH))>0)
+        {
+                for (i = 0; i < nos; i++) {
+                        if (! midread) {
+                                midread = 1;
+                                msgtype = buff[i];
+                                if (ptr>0) /* discard partial message */
+                                        printf("\n*** handle_mesg: discarded %d chars.\n\007", ptr);
+                                pidp=0;
+                        } else {
+                                if (pidp<4) {
+                                        pidbuff[pidp] = buff[i];
+                                        pidp++;
+                                        if (pidp>=4) {
+                                                memcpy(&mesg_pid, &pidbuff, 4);
+                                                if ((mesg_posn=get_who_userposn(mesg_pid))<0)
+                                                        strcpy(mesg_user.name,"System");
+                                                else
+                                                        fetch_user(&mesg_user, mesg_posn);
+                                                ptr=0;
+                                        }
+                                        continue;
+                                }
+                                if (! quotemode) {
+                                        if (buff[i] == 1) {
+                                                quotemode = 1;
+                                                continue;
+                                        } else if (buff[i] == '|') {
+                                                newbuff[ptr] = 0;
+                                                accept_pipe_cmd(msgtype, newbuff, mesg_pid, &mesg_user);
+                                                ptr = 0;
+                                                midread = 0;
+                                                continue;
+                                        }
+                                }
+                                /* just another character, buffer it for now */
+                                if (ptr < MAXPIPELENGTH)
+                                {
+                                        newbuff[ptr]=buff[i];
+                                        ptr++;
+                                }
+                                quotemode=0;
+                        }
+                }
+        }
+	fcntl(incoming_pipe, F_SETFL, fl);
+}
+
+void close_cmd(void)
+{
+	char path[UNIX_PATH_MAX];
+	close(command_sock);
+	command_sock = -1;
+	snprintf(path, UNIX_PATH_MAX, "/tmp/mwnoddy.%d", getpid());
+	unlink(path);
+}

Added: trunk/src/webclient/comms.h
===================================================================
--- trunk/src/webclient/comms.h	                        (rev 0)
+++ trunk/src/webclient/comms.h	2010-10-04 15:48:18 UTC (rev 1172)
@@ -0,0 +1,9 @@
+#include <ipc.h>
+
+/* comms.c */
+void open_command_socket(void);
+void accept_pipe_cmd(enum ipc_types state, char *newbuff, int mesg_pid, struct person *mesg_user);
+int mainloop(int millis);
+int handle_command(int sock);
+void handle_mesg(void);
+void close_cmd(void);

Added: trunk/src/webclient/import.c
===================================================================
--- trunk/src/webclient/import.c	                        (rev 0)
+++ trunk/src/webclient/import.c	2010-10-04 15:48:18 UTC (rev 1172)
@@ -0,0 +1,104 @@
+#include <files.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <strings.h>
+#include <stdbool.h>
+
+#include <talker_privs.h>
+#include <ipc.h>
+#include <perms.h>
+#include <bb.h>
+
+int incoming_pipe = -1;
+
+#define min(a,b) a<b?a:b
+#define max(a,b) a>b?a:b
+
+int get_person(int file, struct person *tmp)
+{
+        int no;
+        if (!(no=read(file,tmp,sizeof(*tmp))))
+        {
+                return(false);
+        }else
+        if (no<sizeof(*tmp))
+        {
+                printf("Problem in get_person: my uid=%d my euid=%d", getuid(), geteuid());
+                return(false);
+        }
+
+        return(true);
+}
+
+void update_user(struct person *record, int32_t userposn)
+{
+        int outfile;
+
+        outfile=openuserfile(O_RDWR|O_CREAT);
+        /*Lock_File(outfile); */
+        lseek(outfile,userposn,0);
+        write(outfile,record,sizeof(*record));
+        /*Unlock_File(outfile); */
+        close(outfile);
+}
+
+/* chatmode flags, as in currently active modes */
+unsigned long cm_flags(unsigned long cm, unsigned long flags, int mode)
+{       
+        if (mode==CM_MODE_CLEAR) return( cm & (~flags) );
+        else    
+        if (mode==CM_MODE_SET) return(cm | flags);
+        else            
+        if (mode==CM_MODE_ANY) {
+                if ((cm&flags)>0) return(true); else return(false);
+        } else  
+        if (mode==CM_MODE_ALL) {
+                if ((cm&flags)==flags) return(true); else return(false);
+        }               
+        return(0);
+}
+
+int ipc_send_to_pid(pid_t dest, enum ipc_types msgtype, const char * data) 
+{
+	return 0;
+}
+
+int32_t get_who_userposn(int pid)
+{
+        struct who w;
+        int wfile;
+        long found=-1;
+
+        if ((wfile=openwhofile(O_RDONLY))<0) return(-1);
+
+        while (read(wfile,&w,sizeof(w)))
+        {
+                if (w.posn >= 0 &&
+                    (pid==-w.pid || (pid==w.pid && (! ipc_send_to_pid(w.pid, IPC_NOOP, NULL)))))
+                {
+                        found=w.posn;
+                        break;
+                }
+        }
+        close(wfile);
+
+        return(found);
+}
+
+void fetch_user(struct person *record, int32_t userposn)
+{
+        int outfile;  
+ 
+        outfile=openuserfile(O_RDWR|O_CREAT);
+        lseek(outfile,userposn,0);
+        read(outfile,record,sizeof(*record));
+        close(outfile);
+}
+

Added: trunk/src/webclient/import.h
===================================================================
--- trunk/src/webclient/import.h	                        (rev 0)
+++ trunk/src/webclient/import.h	2010-10-04 15:48:18 UTC (rev 1172)
@@ -0,0 +1,13 @@
+#include <ipc.h>
+
+/* import.c */
+int get_person(int file, struct person *tmp);
+char *get_pipe_name(int pid);
+void create_pipe(void);
+void update_user(struct person *record, int32_t userposn);
+unsigned long cm_flags(unsigned long cm, unsigned long flags, int mode);
+void open_fifo(void);
+void close_fifo(void);
+int ipc_send_to_pid(pid_t dest, enum ipc_types msgtype, const char *data);
+int32_t get_who_userposn(int pid);
+void fetch_user(struct person *record, int32_t userposn);

Added: trunk/src/webclient/list.h
===================================================================
--- trunk/src/webclient/list.h	                        (rev 0)
+++ trunk/src/webclient/list.h	2010-10-04 15:48:18 UTC (rev 1172)
@@ -0,0 +1,244 @@
+#ifndef __LIST_H
+#define __LIST_H
+
+/* This file is from Linux Kernel (include/linux/list.h) 
+ * and modified by simply removing hardware prefetching of list items. 
+ * Here by copyright, credits attributed to wherever they belong.
+ * Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu)
+ */
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+	struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+	struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries. 
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+			      struct list_head *prev,
+			      struct list_head *next)
+{
+	next->prev = new;
+	new->next = next;
+	new->prev = prev;
+	prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head *prev, struct list_head *next)
+{
+	next->prev = prev;
+	prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+	entry->next = (void *) 0;
+	entry->prev = (void *) 0;
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+	INIT_LIST_HEAD(entry); 
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+        __list_del(list->prev, list->next);
+        list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+				  struct list_head *head)
+{
+        __list_del(list->prev, list->next);
+        list_add_tail(list, head);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(struct list_head *head)
+{
+	return head->next == head;
+}
+
+static inline void __list_splice(struct list_head *list,
+				 struct list_head *head)
+{
+	struct list_head *first = list->next;
+	struct list_head *last = list->prev;
+	struct list_head *at = head->next;
+
+	first->prev = head;
+	head->next = first;
+
+	last->next = at;
+	at->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+	if (!list_empty(list))
+		__list_splice(list, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+				    struct list_head *head)
+{
+	if (!list_empty(list)) {
+		__list_splice(list, head);
+		INIT_LIST_HEAD(list);
+	}
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:	the &struct list_head pointer.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+	((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+/**
+ * list_for_each	-	iterate over a list
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @head:	the head for your list.
+ */
+#define list_for_each(pos, head) \
+	for (pos = (head)->next; pos != (head); \
+        	pos = pos->next)
+/**
+ * list_for_each_prev	-	iterate over a list backwards
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @head:	the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+	for (pos = (head)->prev; pos != (head); \
+        	pos = pos->prev)
+        	
+/**
+ * list_for_each_safe	-	iterate over a list safe against removal of list entry
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @n:		another &struct list_head to use as temporary storage
+ * @head:	the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+	for (pos = (head)->next, n = pos->next; pos != (head); \
+		pos = n, n = pos->next)
+
+/**
+ * list_for_each_entry	-	iterate over list of given type
+ * @pos:	the type * to use as a loop counter.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)				\
+	for (pos = list_entry((head)->next, typeof(*pos), member);	\
+	     &pos->member != (head); 					\
+	     pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos:	the type * to use as a loop counter.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member)			\
+	for (pos = list_entry((head)->next, typeof(*pos), member),	\
+		n = list_entry(pos->member.next, typeof(*pos), member);	\
+	     &pos->member != (head); 					\
+	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+
+#endif

Added: trunk/src/webclient/mwpoll.c
===================================================================
--- trunk/src/webclient/mwpoll.c	                        (rev 0)
+++ trunk/src/webclient/mwpoll.c	2010-10-04 15:48:18 UTC (rev 1172)
@@ -0,0 +1,82 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <time.h>
+
+#include <bb.h>
+#include <talker_privs.h>
+#include <strings.h>
+#include <files.h>
+#include <who.h>
+#include "import.h"
+#include "comms.h"
+
+struct person me;
+struct person *user = &me;
+
+/* unused */
+int internet = 0;
+int idle = 0;
+
+void usage(const char *name)
+{
+	printf("Usage: %s [-u username] [-c channel]\n", name);
+}
+
+int main(int argc, char ** argv)
+{
+	char *username;
+	int opt;
+	int32_t userposn;
+	int channel = 0;
+
+	username = strdup("Arthur2");
+	while ((opt=getopt(argc,argv,"u:c:"))!=-1) {
+		switch (opt) {
+			case 'u':
+				if (username) free(username);
+				username = strdup(optarg);
+				break;
+			case 'c':
+				channel = atoi(optarg);
+				break;
+			default:
+				usage(argv[0]);
+				return 1;
+				break;
+		}
+	}
+
+	/* fetch the user record */
+	if (!is_old(&me, username, &userposn)) {
+		printf("User '%s' not found.\n", username);
+		return 1;
+	}
+
+	/* mark as in talker */
+	user->chatmode=0;
+	user->chatmode=cm_flags(user->chatmode,CM_ONCHAT,CM_MODE_SET);
+	user->idletime=time(0);
+	user->room = channel;
+	update_user(user,userposn);
+
+	printf("Starting up session %d\n", getpid());
+
+	/* load us up */
+	create_pipe();
+	open_incoming_fifo();
+	open_command_socket();
+	who_add(getpid(),userposn);
+
+	/* the main loop */
+	while (mainloop(-1)==0) {};
+
+	close_fifo();
+	close_cmd();
+}




More information about the mw-devel mailing list