[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