[gpm] [PATCH 4/18] separate-client-handling.patch

Dmitry Torokhov dtor_core@ameritech.net
Tue Aug 10 08:52:26 CEST 2004


===================================================================


ChangeSet@1.8, 2004-08-10 00:52:46-05:00, dtor_core@ameritech.net
  Separate client handling code into separate source file, cleanups.


 Makefile.in      |    2 
 client.c         |  318 ++++++++++++++++++++++++++++++++++++++++++
 gpm.c            |  414 +++++++++----------------------------------------------
 headers/client.h |   57 +++++++
 headers/gpmInt.h |   21 --
 5 files changed, 446 insertions(+), 366 deletions(-)


===================================================================



diff -Nru a/src/Makefile.in b/src/Makefile.in
--- a/src/Makefile.in	2004-08-10 01:17:58 -05:00
+++ b/src/Makefile.in	2004-08-10 01:17:58 -05:00
@@ -14,7 +14,7 @@
 # Main portion: regular build rules
 
 GSRC = main.c gpm.c gpn.c mice.c special.c twiddler.c synaptics.c \
-       startup.c server_tools.c console.c
+       startup.c server_tools.c console.c client.c
 
 GOBJ = $(GSRC:.c=.o) report.o tools.o
 
diff -Nru a/src/client.c b/src/client.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/src/client.c	2004-08-10 01:17:58 -05:00
@@ -0,0 +1,318 @@
+/*
+ * client.c - GPM client handling (server side)
+ *
+ * Copyright (C) 1993        Andreq Haylett <ajh@gec-mrc.co.uk>
+ * Copyright (C) 1994-1999   Alessandro Rubini <rubini@linux.it>
+ * Copyright (C) 1998        Ian Zimmerman <itz@rahul.net>
+ * Copyright (c) 2001,2002   Nico Schottelius <nico-gpm@schottelius.org>
+ * Copyright (C) 2003        Dmitry Torokhov <dtor@mail.ru>
+ *
+ *   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 2 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, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ ********/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>        /* strerror(); ?!?  */
+#include <errno.h>
+#include <unistd.h>        /* select(); */
+#include <signal.h>        /* SIGPIPE */
+#include <time.h>          /* time() */
+#include <sys/fcntl.h>     /* O_RDONLY */
+#include <sys/stat.h>      /* mkdir()  */
+#include <sys/time.h>      /* timeval */
+#include <sys/types.h>     /* socket() */
+#include <sys/socket.h>    /* socket() */
+#include <sys/un.h>        /* struct sockaddr_un */
+
+#include "headers/gpmInt.h"
+#include "headers/message.h"
+#include "headers/console.h"
+#include "headers/client.h"
+
+/* who the f*** runs gpm without glibc? doesn't have dietlibc __socklent_t? */
+#if !defined(__GLIBC__)
+   typedef unsigned int __socklen_t;
+#endif    /* __GLIBC__ */
+
+#ifndef max
+#define max(a,b) ((a)>(b) ? (a) : (b))
+#endif
+
+extern int errno;
+
+struct client_info *cinfo[MAX_VC + 1];
+
+/*-------------------------------------------------------------------*
+ * This was inline, and incurred in a compiler bug (2.7.0)
+ *-------------------------------------------------------------------*/
+static int get_data(int fd, Gpm_Connect *data)
+{
+   static int len;
+
+#ifdef GPM_USE_MAGIC
+   while ((len = read(whence, &check, sizeof(int))) == 4 &&
+          check != GPM_MAGIC)
+      gpm_report(GPM_PR_INFO, GPM_MESS_NO_MAGIC);
+
+   if (len == 0) return 0;
+
+   if (check != GPM_MAGIC) {
+      gpm_report(GPM_PR_INFO, GPM_MESS_NOTHING_MORE);
+      return -1;
+   }
+#endif
+
+   len = read(fd, data, sizeof(Gpm_Connect));
+
+   return len ? (len == sizeof(Gpm_Connect) ? 1 : -1) : 0;
+}
+
+/*-------------------------------------------------------------------*/
+int listen_for_clients(void)
+{
+   struct sockaddr_un ctladdr;
+   int fd, len;
+
+   unlink(GPM_NODE_CTL);
+
+   if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+      gpm_report(GPM_PR_OOPS, GPM_MESS_SOCKET_PROB);
+
+   memset(&ctladdr, 0, sizeof(ctladdr));
+   ctladdr.sun_family = AF_UNIX;
+   strcpy(ctladdr.sun_path, GPM_NODE_CTL);
+   len = sizeof(ctladdr.sun_family) + strlen(GPM_NODE_CTL);
+
+   if (bind(fd, (struct sockaddr *)&ctladdr, len) == -1)
+      gpm_report(GPM_PR_OOPS, GPM_MESS_BIND_PROB, ctladdr.sun_path);
+
+   /* needs to be 0777, so all users can _try_ to access gpm */
+   chmod(GPM_NODE_CTL, 0777);
+   listen(fd, 5);          /* Queue up calls */
+
+   return fd;
+}
+
+/*-------------------------------------------------------------------*/
+struct client_info *accept_client_connection(int fd)
+{
+   struct client_info *info;
+   Gpm_Connect *request;
+   int newfd;
+#if !defined(__GLIBC__)
+   int len;
+#else /* __GLIBC__ */
+   size_t len; /* isn't that generally defined in C ???  -- nico */
+#endif /* __GLIBC__ */
+   struct sockaddr_un addr; /* reuse this each time */
+#ifndef SO_PEERCRED
+   struct stat statbuf;
+   time_t staletime;
+#endif
+   uid_t uid;
+
+   /*....................................... Accept */
+   memset(&addr, 0, sizeof(addr));
+   addr.sun_family = AF_UNIX;
+
+   len = sizeof(addr);
+   if ((newfd = accept(fd, (struct sockaddr *)&addr, &len)) < 0) {
+      gpm_report(GPM_PR_ERR, GPM_MESS_ACCEPT_FAILED, strerror(errno));
+      return NULL;
+   }
+
+   gpm_report(GPM_PR_INFO, GPM_MESS_CONECT_AT, newfd);
+
+   if (!(info = malloc(sizeof(struct client_info))))
+      gpm_report(GPM_PR_OOPS, GPM_MESS_NO_MEM);
+
+   request = &info->data;
+   if (get_data(newfd, request) == -1)
+      goto err;
+
+   if (request->vc > MAX_VC) {
+      gpm_report(GPM_PR_WARN,GPM_MESS_REQUEST_ON, request->vc, MAX_VC);
+      goto err;
+   }
+
+#ifndef SO_PEERCRED
+   if (stat(addr.sun_path, &statbuf) == -1 || !S_ISSOCK(statbuf.st_mode)) {
+      gpm_report(GPM_PR_ERR,GPM_MESS_ADDRES_NSOCKET,addr.sun_path);
+      goto err;
+   }
+
+   unlink(addr.sun_path);   /* delete socket */
+
+   staletime = time(0) - 30;
+   if (statbuf.st_atime < staletime ||
+       statbuf.st_ctime < staletime ||
+       statbuf.st_mtime < staletime) {
+      gpm_report(GPM_PR_ERR, GPM_MESS_SOCKET_OLD);
+      goto err;
+   }
+
+   uid = statbuf.st_uid;      /* owner of socket */
+#else
+   {
+      struct ucred sucred;
+      socklen_t credlen = sizeof(struct ucred);
+
+      if (getsockopt(newfd, SOL_SOCKET, SO_PEERCRED, &sucred, &credlen) == -1) {
+         gpm_report(GPM_PR_ERR,GPM_MESS_GETSOCKOPT, strerror(errno));
+         goto err;
+      }
+      uid = sucred.uid;
+      gpm_report(GPM_PR_DEBUG,GPM_MESS_PEER_SCK_UID, uid);
+   }
+#endif
+
+   if (uid != 0 && !is_console_owner(request->vc, uid)) {
+      gpm_report(GPM_PR_WARN, GPM_MESS_FAILED_CONNECT, uid, request->vc);
+      goto err;
+   }
+
+   /* register the connection information in the right place */
+   info->next = cinfo[request->vc];
+   info->fd = newfd;
+   cinfo[request->vc] = info;
+   gpm_report(GPM_PR_DEBUG, GPM_MESS_LONG_STATUS,
+        request->pid, request->vc, request->eventMask, request->defaultMask,
+        request->minMod, request->maxMod);
+
+   return info;
+
+err:
+   free(info);
+   close(newfd);
+
+   return NULL;
+}
+
+/*-------------------------------------------------------------------*/
+void remove_client(struct client_info *ci, int vc)
+{
+   struct client_info *p, *prev = NULL;
+
+   for (p = cinfo[vc]; p; prev = p, p = p->next) {
+      if (p == ci) {
+         if (!prev)    /* it is on top of the stack */
+            cinfo[vc] = p->next;
+         else
+            prev->next = p->next;
+         break;
+      }
+   }
+   if (p) free(p);
+}
+
+/*-------------------------------------------------------------------*/
+void notify_clients_resize(void)
+{
+   struct client_info *ci;
+   int i;
+
+   for (i = 0; i < MAX_VC + 1; i++)
+      for (ci = cinfo[i]; ci; ci = ci->next)
+         kill(ci->data.pid, SIGWINCH);
+}
+
+/*-------------------------------------------------------------------*/
+/* returns 0 if the event has not been processed, and 1 if it has    */
+int do_client(struct client_info *cinfo, Gpm_Event *event)
+{
+   Gpm_Connect *info = &cinfo->data;
+   /* value to return if event is not used */
+   int res = !(info->defaultMask & event->type);
+
+   /* instead of returning 0, scan the stack of clients */
+   if ((info->minMod & event->modifiers) < info->minMod)
+      goto try_next;
+   if ((info->maxMod & event->modifiers) < event->modifiers)
+      goto try_next;
+
+   /* if not managed, use default mask */
+   if (!(info->eventMask & GPM_BARE_EVENTS(event->type))) {
+      if (res) return res;
+      else goto try_next;
+   }
+
+   /* WARNING */ /* This can generate a SIGPIPE... I'd better catch it */
+   MAGIC_P((write(cinfo->fd, &magic, sizeof(int))));
+   write(cinfo->fd, event, sizeof(Gpm_Event));
+
+   return info->defaultMask & GPM_HARD ? res : 1; /* HARD forces pass-on */
+
+ try_next:
+   if (cinfo->next != 0)
+      return do_client(cinfo->next, event); /* try the next */
+
+   return 0; /* no next, not used */
+}
+
+/*-------------------------------------------------------------------*/
+/* returns 0 if client disconnects, -1 - error, 1 -successs */
+int process_client_request(struct client_info *ci, int vc,
+                           int x, int y, int buttons, int clicks,
+                           int three_button_mouse)
+{
+   int rc;
+   Gpm_Connect conn;
+   static Gpm_Event event;
+
+   gpm_report(GPM_PR_INFO, GPM_MESS_CON_REQUEST, ci->fd, vc);
+   if (vc > MAX_VC) return -1;
+
+   /* itz 10-22-96 this shouldn't happen now */
+   if (vc == -1) gpm_report(GPM_PR_OOPS, GPM_MESS_UNKNOWN_FD);
+
+   rc = get_data(ci->fd, &conn);
+
+   if (rc == 0) { /* no data */
+      gpm_report(GPM_PR_INFO, GPM_MESS_CLOSE);
+      close(ci->fd);
+      return 0;
+   }
+
+   if (rc == -1) return -1; /* too few bytes */
+
+   if (conn.pid != 0) {
+      ci->data = conn;
+      return 1;
+   }
+
+   /* Aha, request for information (so-called snapshot) */
+   switch (conn.vc) {
+      case GPM_REQ_SNAPSHOT:
+         event.vc = get_console_state(&event.modifiers);
+         event.x = x; event.y = y;
+         event.buttons = buttons;
+         event.clicks = clicks;
+         event.dx = console.max_x; event.dy = console.max_y;
+         /* fall through */
+
+      case GPM_REQ_BUTTONS:
+         event.type = (three_button_mouse == 1 ? 3 : 2); /* buttons */
+         write(ci->fd, &event, sizeof(Gpm_Event));
+         break;
+
+      case GPM_REQ_NOPASTE:
+         selection_disable_paste();
+         gpm_report(GPM_PR_INFO, GPM_MESS_DISABLE_PASTE, vc);
+         break;
+   }
+
+   return 1;
+}
+
diff -Nru a/src/gpm.c b/src/gpm.c
--- a/src/gpm.c	2004-08-10 01:17:58 -05:00
+++ b/src/gpm.c	2004-08-10 01:17:58 -05:00
@@ -30,25 +30,20 @@
 #include <time.h>          /* time() */
 #include <sys/fcntl.h>     /* O_RDONLY */
 #include <sys/wait.h>      /* wait()   */
-#include <sys/stat.h>      /* mkdir()  */
 #include <sys/time.h>      /* timeval */
-#include <sys/types.h>     /* socket() */
-#include <sys/socket.h>    /* socket() */
-#include <sys/un.h>        /* struct sockaddr_un */
 
 #include "headers/gpmInt.h"
 #include "headers/message.h"
 #include "headers/console.h"
-
-/* who the f*** runs gpm without glibc? doesn't have dietlibc __socklent_t? */
-#if !defined(__GLIBC__)
-   typedef unsigned int __socklen_t;
-#endif    /* __GLIBC__ */
+#include "headers/client.h"
 
 #ifndef max
 #define max(a,b) ((a)>(b) ? (a) : (b))
 #endif
 
+#define NULL_SET ((fd_set *)NULL)
+#define resetTimeout() (timeout.tv_sec=SELECT_TIME,timeout.tv_usec=0)
+
 extern int errno;
 
 static void gpm_killed(int);
@@ -83,9 +78,14 @@
 struct repeater repeater;
 
 int eventFlag=0;
-Gpm_Cinfo *cinfo[MAX_VC+1];
 fd_set selSet, readySet, connSet;
 
+static struct {
+   int   x, y;
+   int   buttons;
+   int   clicks;
+} state;
+
 /* BRAINDEAD..ok not really, but got to leave anyway... FIXME */
 /* argc and argv for mice initialization */
 static int mouse_argc[3]; /* 0 for default (unused) and two mice */
@@ -130,39 +130,6 @@
    return argv;
 }
 
-/*-------------------------------------------------------------------*/
-/* returns 0 if the event has not been processed, and 1 if it has */
-static inline int do_client(Gpm_Cinfo *cinfo, Gpm_Event *event)
-{
-   Gpm_Connect info=cinfo->data;
-   int fd=cinfo->fd;
-   /* value to return if event is not used */
-   int res = !(info.defaultMask & event->type);
-
-   /* instead of returning 0, scan the stack of clients */
-   if ((info.minMod & event->modifiers) < info.minMod)
-      goto scan;
-   if ((info.maxMod & event->modifiers) < event->modifiers) 
-      goto scan;
-
-   /* if not managed, use default mask */
-   if (!(info.eventMask & GPM_BARE_EVENTS(event->type))) {
-      if (res) return res;
-      else goto scan;
-   }   
-
-   /* WARNING */ /* This can generate a SIGPIPE... I'd better catch it */
-   MAGIC_P((write(fd,&magic, sizeof(int))));
-   write(fd,event, sizeof(Gpm_Event));
-
-   return info.defaultMask & GPM_HARD ? res : 1; /* HARD forces pass-on */
-
-   scan:
-   if (cinfo->next != 0) 
-      return do_client (cinfo->next, event); /* try the next */
-   return 0; /* no next, not used */
-}
-
 /*-------------------------------------------------------------------
  * fetch the actual device data from the mouse device, dependent on
  * what Gpm_Type is being passed.
@@ -223,10 +190,6 @@
    return data;
 }
 
-
-static int statusX,statusY,statusB; /* to return info */
-static int statusC=0; /* clicks */
-
 /*-------------------------------------------------------------------*/
 void handle_console_resize(Gpm_Event *ePtr)
 {
@@ -237,11 +200,11 @@
    old_x = console.max_x; old_y = console.max_y;
    refresh_console_size();
    if (!old_x) { /* first invocation, place the pointer in the middle */
-      statusX = ePtr->x = console.max_x / 2;
-      statusY = ePtr->y = console.max_y / 2;
+      state.x = ePtr->x = console.max_x / 2;
+      state.y = ePtr->y = console.max_y / 2;
    } else { /* keep the pointer in the same position where it was */
-      statusX = ePtr->x = ePtr->x * console.max_x / old_x;
-      statusY = ePtr->y = ePtr->y * console.max_y / old_y;
+      state.x = ePtr->x = ePtr->x * console.max_x / old_x;
+      state.y = ePtr->y = ePtr->y * console.max_y / old_y;
    }
 
    for (i=1; i <= 1+opt_double; i++) {
@@ -402,7 +365,7 @@
 /*....................................... fill missing fields */
 
    event->x += event->dx, event->y += event->dy;
-   statusB=event->buttons;
+   state.buttons = event->buttons;
 
    event->vc = get_console_state(&shift_state);
    if (event->vc != last_active) {
@@ -419,31 +382,32 @@
    switch(event->type) {                /* now provide the cooked bits */
       case GPM_DOWN:
          GET_TIME(tv2);
-         if (tv1.tv_sec && (DIF_TIME(tv1,tv2)<opt_time)) /* check first click */
-            statusC++, statusC%=3; /* 0, 1 or 2 */
+         if (tv1.tv_sec && (DIF_TIME(tv1, tv2) < opt_time)) /* check first click */
+            state.clicks++, state.clicks %= 3; /* 0, 1 or 2 */
          else
-            statusC=0;
-         event->type|=(GPM_SINGLE<<statusC);
+            state.clicks = 0;
+         event->type |= GPM_SINGLE << state.clicks;
          break;
 
       case GPM_UP:
          GET_TIME(tv1);
-         event->buttons^=oldB; /* for button-up, tell which one */
-         event->type|= (oldT&GPM_MFLAG);
-         event->type|=(GPM_SINGLE<<statusC);
+         event->buttons ^= oldB; /* for button-up, tell which one */
+         event->type |= oldT & GPM_MFLAG;
+         event->type |= GPM_SINGLE << state.clicks;
          break;
 
       case GPM_DRAG:
          event->type |= GPM_MFLAG;
-         event->type|=(GPM_SINGLE<<statusC);
+         event->type |= GPM_SINGLE << state.clicks;
          break;
 
       case GPM_MOVE:
-         statusC=0;
+         state.clicks = 0;
+
       default:
          break;
    }
-   event->clicks=statusC;
+   event->clicks = state.clicks;
    
 /* UGLY - FIXME! */
 /* The current policy is to force the following behaviour:
@@ -489,7 +453,7 @@
                                        event->clicks);
 
    /* update the global state */
-   statusX=event->x; statusY=event->y;
+   state.x = event->x; state.y = event->y;
 
    if (opt_special && event->type & GPM_DOWN) 
       return processSpecial(event);
@@ -497,213 +461,6 @@
    return 1;
 }
 
-/*-------------------------------------------------------------------*
- * This  was inline, and incurred in a compiler bug (2.7.0)
- *-------------------------------------------------------------------*/
-static int get_data(Gpm_Connect *where, int whence)
-{
-   static int i;
-
-#ifdef GPM_USE_MAGIC
-   while ((i=read(whence,&check,sizeof(int)))==4 && check!=GPM_MAGIC)
-      gpm_report(GPM_PR_INFO,GPM_MESS_NO_MAGIC);
-
-   if (!i) return 0;
-   if (check!=GPM_MAGIC) {
-     gpm_report(GPM_PR_INFO,GPM_MESS_NOTHING_MORE);
-     return -1;
-   }
-#endif
-
-   if ((i=read(whence, where, sizeof(Gpm_Connect)))!=sizeof(Gpm_Connect)) {
-      return i ? -1 : 0;
-   }
-
-   return 1;
-}
-
-/*-------------------------------------------------------------------*/
-                                  /* returns -1 if closing connection */
-static inline int processRequest(Gpm_Cinfo *ci, int vc) 
-{
-   int i;
-   Gpm_Cinfo *cinfoPtr, *next;
-   Gpm_Connect conn;
-   static Gpm_Event event;
-
-   gpm_report(GPM_PR_INFO,GPM_MESS_CON_REQUEST, ci->fd, vc);
-   if (vc>MAX_VC) return -1;
-
-   /* itz 10-22-96 this shouldn't happen now */
-   if (vc==-1) gpm_report(GPM_PR_OOPS,GPM_MESS_UNKNOWN_FD);
-
-   i=get_data(&conn,ci->fd);
-
-   if (!i) { /* no data */
-      gpm_report(GPM_PR_INFO,GPM_MESS_CLOSE);
-      close(ci->fd);
-      FD_CLR(ci->fd,&connSet);
-      FD_CLR(ci->fd,&readySet);
-      if (cinfo[vc]->fd == ci->fd) { /* it was on top of the stack */
-         cinfoPtr = cinfo[vc];
-         cinfo[vc]=cinfo[vc]->next; /* pop the stack */
-         free(cinfoPtr);
-         return -1;
-      }
-      /* somewhere inside the stack, have to walk it */
-      cinfoPtr = cinfo[vc];
-      while (cinfoPtr && cinfoPtr->next) {
-         if (cinfoPtr->next->fd == ci->fd) {
-            next = cinfoPtr->next;
-            cinfoPtr->next = next->next;
-            free (next);
-            break;
-         }
-         cinfoPtr = cinfoPtr->next;
-      }
-      return -1;
-   } /* not data */
- 
-   if (i == -1) return -1; /* too few bytes */
-
-   if (conn.pid!=0) {
-      ci->data = conn;
-      return 0;
-   }
-
-   /* Aha, request for information (so-called snapshot) */
-   switch(conn.vc) {
-      case GPM_REQ_SNAPSHOT:
-         event.vc = get_console_state(&event.modifiers);
-         event.x=statusX;   event.y=statusY;
-         event.dx = console.max_x; event.dy = console.max_y;
-         event.buttons= statusB;
-         event.clicks=statusC;
-         /* fall through */
-         /* missing break or do you want this ??? */
-
-      case GPM_REQ_BUTTONS:
-         event.type= (opt_three==1 ? 3 : 2); /* buttons */
-         write(ci->fd,&event,sizeof(Gpm_Event));
-         break;
-
-      case GPM_REQ_NOPASTE:
-         selection_disable_paste();
-         gpm_report(GPM_PR_INFO, GPM_MESS_DISABLE_PASTE, vc);
-         break;
-   }
-
-   return 0;
-}
-
-/*-------------------------------------------------------------------*/
-static inline int processConn(int fd) /* returns newfd or -1 */
-{
-   Gpm_Cinfo *info;
-   Gpm_Connect *request;
-   int vc, newfd;
-#if !defined(__GLIBC__)
-   int len;
-#else /* __GLIBC__ */
-   size_t len; /* isn't that generally defined in C ???  -- nico */
-#endif /* __GLIBC__ */
-   struct sockaddr_un addr; /* reuse this each time */
-#ifndef SO_PEERCRED
-   struct stat statbuf;
-   time_t staletime;
-#endif
-   uid_t uid;
-
-/*....................................... Accept */
-
-   bzero((char *)&addr,sizeof(addr));
-   addr.sun_family=AF_UNIX;
-
-   len=sizeof(addr);
-   if ((newfd=accept(fd,(struct sockaddr *)&addr, &len))<0) {
-      gpm_report(GPM_PR_ERR,GPM_MESS_ACCEPT_FAILED,strerror(errno));
-      return -1;
-   }
-
-   gpm_report(GPM_PR_INFO,GPM_MESS_CONECT_AT,newfd);
-
-   info=malloc(sizeof(Gpm_Cinfo));
-   if (!info) gpm_report(GPM_PR_OOPS,GPM_MESS_NO_MEM);
-   request=&(info->data);
-
-   if(get_data(request,newfd)==-1) {
-      free(info);
-      close(newfd);
-      return -1;
-   }
-
-   if ((vc=request->vc)>MAX_VC) {
-      gpm_report(GPM_PR_WARN,GPM_MESS_REQUEST_ON, vc, MAX_VC);
-      free(info);
-      close(newfd);
-      return -1;
-   }
-
-#ifndef SO_PEERCRED
-   if (stat (addr.sun_path, &statbuf) == -1 || !S_ISSOCK(statbuf.st_mode)) {
-      gpm_report(GPM_PR_ERR,GPM_MESS_ADDRES_NSOCKET,addr.sun_path);
-      free(info);         /* itz 10-12-95 verify client's right */
-      close(newfd);
-      return -1;         /* to read requested tty */
-   }
-   
-   unlink(addr.sun_path);   /* delete socket */
-
-   staletime = time(0) - 30;
-   if (statbuf.st_atime < staletime
-    || statbuf.st_ctime < staletime
-    || statbuf.st_mtime < staletime) {
-      gpm_report(GPM_PR_ERR,GPM_MESS_SOCKET_OLD);
-      free (info);
-      close(newfd);
-      return -1;         /* socket is ancient */
-   }
-   
-   uid = statbuf.st_uid;      /* owner of socket */
-#else
-   {
-      struct ucred sucred;
-      socklen_t credlen = sizeof(struct ucred);
-
-      if(getsockopt(newfd, SOL_SOCKET, SO_PEERCRED, &sucred, &credlen) == -1) {
-         gpm_report(GPM_PR_ERR,GPM_MESS_GETSOCKOPT, strerror(errno));
-         free(info);
-         close(newfd);
-         return -1;
-      }
-      uid = sucred.uid;
-      gpm_report(GPM_PR_DEBUG,GPM_MESS_PEER_SCK_UID, uid);
-   }
-#endif
-   if (uid != 0 && !is_console_owner(vc, uid)) {
-      gpm_report(GPM_PR_WARN, GPM_MESS_FAILED_CONNECT, uid, vc); /*SUSPECT!*/
-      free(info);
-      close(newfd);
-      return -1;
-   }
-
-   /* register the connection information in the right place */
-   info->next=cinfo[vc];
-   info->fd=newfd;
-   cinfo[vc]=info;
-   gpm_report(GPM_PR_DEBUG,GPM_MESS_LONG_STATUS,
-        request->pid, request->vc, request->eventMask, request->defaultMask,
-        request->minMod, request->maxMod);
-
-   /* if the client gets motions, give it the current position */
-   if(request->eventMask & GPM_MOVE) {
-      Gpm_Event event={0,0,vc,0,0,statusX,statusY,GPM_MOVE,0,0};
-      do_client(info, &event);
-   }
-
-   return newfd;
-}
-
 /*-------------------------------------------------------------------*/
 static void gpm_killed(int signo)
 {
@@ -720,13 +477,13 @@
 /*-------------------------------------------------------------------*/
 int old_main()
 {
-   int ctlfd, newfd;
-   struct sockaddr_un ctladdr;
-   int i, len, text_mode, fd;
+   int ctlfd;
+   int i, text_mode, fd;
    struct timeval timeout;
-   int maxfd=-1;
+   int maxfd = -1;
    int pending;
    Gpm_Event event;
+   struct client_info *ci;
 
    for (i = 1; i <= 1+opt_double; i++) {
       which_mouse=mouse_table+i; /* used to access options */
@@ -759,43 +516,21 @@
    signal(SIGINT,  gpm_killed);
    signal(SIGUSR1, gpm_killed); /* usr1 is used by a new gpm killing the old */
    signal(SIGWINCH,gpm_killed); /* winch can be sent if console is resized */
-
-/*....................................... create your nodes */
-
-   /* control node */
-
-   if((ctlfd=socket(AF_UNIX,SOCK_STREAM,0))==-1) gpm_report(GPM_PR_OOPS,GPM_MESS_SOCKET_PROB);
-   bzero((char *)&ctladdr,sizeof(ctladdr));
-   ctladdr.sun_family=AF_UNIX;
-   strcpy(ctladdr.sun_path,GPM_NODE_CTL);
-   unlink(GPM_NODE_CTL);
-
-   len=sizeof(ctladdr.sun_family)+strlen(GPM_NODE_CTL);
-   if(bind(ctlfd,(struct sockaddr *)(&ctladdr),len) == -1)
-      gpm_report(GPM_PR_OOPS,GPM_MESS_BIND_PROB,ctladdr.sun_path);
-   maxfd=max(maxfd,ctlfd);
-
-   /* needs to be 0777, so all users can _try_ to access gpm */
-   chmod(GPM_NODE_CTL,0777);
+   signal(SIGPIPE, SIG_IGN);    /* WARN */
 
    handle_console_resize(&event); /* get screen dimensions */
 
-/*....................................... wait for mouse and connections */
-
-   listen(ctlfd, 5);          /* Queue up calls */
-
-#define NULL_SET ((fd_set *)NULL)
-#define resetTimeout() (timeout.tv_sec=SELECT_TIME,timeout.tv_usec=0)
+   ctlfd = listen_for_clients();
 
+   /*....................................... wait for mouse and connections */
    FD_ZERO(&connSet);
-   FD_SET(ctlfd,&connSet);
-
-   if (opt_double) FD_SET(mouse_table[2].fd,&connSet);
+   FD_SET(ctlfd, &connSet);
+   maxfd = max(maxfd, ctlfd);
 
-   readySet=connSet;
-   FD_SET(mouse_table[1].fd,&readySet);
+   if (opt_double) FD_SET(mouse_table[2].fd, &connSet);
 
-   signal(SIGPIPE,SIG_IGN);  /* WARN */
+   readySet = connSet;
+   FD_SET(mouse_table[1].fd, &readySet);
 
 /*--------------------------------------- main loop begins here */
 
@@ -815,16 +550,11 @@
             resetTimeout();
          } /* go on */
 
-      if(opt_resize) { /* did the console resize? */
+      if (opt_resize) { /* did the console resize? */
          handle_console_resize(&event);
          opt_resize--;
-         signal(SIGWINCH,gpm_killed); /* reinstall handler */
-
-         /* and notify clients */
-         for(i=0; i<MAX_VC+1; i++) {
-            Gpm_Cinfo *ci;
-            for (ci = cinfo[i]; ci; ci = ci->next) kill(ci->data.pid,SIGWINCH);
-         }
+         signal(SIGWINCH, gpm_killed); /* reinstall handler */
+         notify_clients_resize();
       }
 
       if (pending < 0) {
@@ -882,53 +612,49 @@
       }
 
       /*..................... got connection, process it */
-
-      if (pending && FD_ISSET(ctlfd,&selSet)) {
-         FD_CLR(ctlfd,&selSet); pending--;
-         newfd=processConn(ctlfd);
-         if (newfd>=0) {
-            FD_SET(newfd,&connSet);
-            FD_SET(newfd,&readySet);
-            maxfd=max(maxfd,newfd);
+      if (pending && FD_ISSET(ctlfd, &selSet)) {
+         FD_CLR(ctlfd, &selSet);
+         pending--;
+         if ((ci = accept_client_connection(ctlfd))) {
+            if (ci->data.eventMask & GPM_MOVE) {
+               Gpm_Event event = { 0, 0, ci->data.vc, 0, 0,
+                                   state.x, state.y, GPM_MOVE, 0, 0 };
+               do_client(ci, &event);
+            }
+            FD_SET(ci->fd, &connSet);
+            FD_SET(ci->fd, &readySet);
+            maxfd = max(maxfd, ci->fd);
          }
       }
 
       /*........................ got request */
-
-     /* itz 10-22-96 check _all_ clients, not just those on top! */
-      for (i=0; pending && (i<=MAX_VC); i++) {
-         Gpm_Cinfo* ci;
+      /* itz 10-22-96 check _all_ clients, not just those on top! */
+      for (i = 0; pending && i <= MAX_VC; i++) {
          for (ci = cinfo[i]; pending && ci; ci = ci->next) {
-            if (FD_ISSET(ci->fd,&selSet)) {
-               FD_CLR(ci->fd,&selSet); pending--;
-           /* itz Sat Sep 12 21:10:22 PDT 1998 */
-           /* this code is clearly incorrect; the next highest
-              descriptor after the one we're closing is not necessarily
-              being used.  Fortunately, it doesn't hurt simply to leave this
-              out. */
-
-#ifdef NOTDEF
-               if ((processRequest(ci,i)==-1) && maxfd==ci->fd) maxfd--;
-#else
-               (void)processRequest(ci,i);
-#endif
+            if (FD_ISSET(ci->fd, &selSet)) {
+               FD_CLR(ci->fd, &selSet);
+               pending--;
+               if (!process_client_request(ci, i, state.x, state.y, state.clicks,
+                                           state.buttons, opt_three)) {
+                  FD_CLR(ci->fd, &connSet);
+                  FD_CLR(ci->fd, &readySet);
+                  remove_client(ci, i);
+               }
             }
          }
       }
 
       /*.................. look for a spare fd */
-
       /* itz 10-22-96 this shouldn't happen now! */
-      for (i=0; pending && i<=maxfd; i++) {
-         if (FD_ISSET(i,&selSet)) {
-            FD_CLR(i,&selSet);
+      for (i = 0; pending && i <= maxfd; i++) {
+         if (FD_ISSET(i, &selSet)) {
+            FD_CLR(i, &selSet);
             pending--;
-            gpm_report(GPM_PR_WARN,GPM_MESS_STRANGE_DATA,i);
+            gpm_report(GPM_PR_WARN, GPM_MESS_STRANGE_DATA,i);
          }
       }
         
       /*................... all done. */
-     
-     if(pending) gpm_report(GPM_PR_OOPS,GPM_MESS_SELECT_PROB);
+      if (pending) gpm_report(GPM_PR_OOPS, GPM_MESS_SELECT_PROB);
    } /* while(1) */
 }
diff -Nru a/src/headers/client.h b/src/headers/client.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/src/headers/client.h	2004-08-10 01:17:58 -05:00
@@ -0,0 +1,57 @@
+/*
+ * client.h - GPM client handling (server side)
+ *
+ * Copyright (C) 2003  Dmitry Torokhov <dtor@mail.ru>
+ *
+ *   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 2 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, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ ********/
+
+#ifndef __GPM_CLIENT_H
+#define __GPM_CLIENT_H_
+
+#ifdef HAVE_LINUX_TTY_H
+#include <linux/tty.h>
+#endif
+
+#include "headers/gpm.h"
+
+/* FIXME: still needed ?? */
+/* How many virtual consoles are managed? */
+#ifndef MAX_NR_CONSOLES
+#  define MAX_NR_CONSOLES 64 /* this is always sure */
+#endif
+
+#define MAX_VC    MAX_NR_CONSOLES  /* doesn't work before 1.3.77 */
+
+struct client_info {
+  Gpm_Connect data;
+  int fd;
+  struct client_info *next;
+};
+
+struct Gpm_Event;
+
+extern struct client_info *cinfo[MAX_VC + 1];
+
+int   listen_for_clients(void);
+struct client_info *accept_client_connection(int fd);
+void  remove_client(struct client_info *ci, int vc);
+void  notify_clients_resize(void);
+int   do_client(struct client_info *cinfo, struct Gpm_Event *event);
+int   process_client_request(struct client_info *ci, int vc,
+                             int x, int y, int buttons, int clicks,
+                             int three_button_mouse);
+
+#endif /* __GPM_CLIENT_H_ */
diff -Nru a/src/headers/gpmInt.h b/src/headers/gpmInt.h
--- a/src/headers/gpmInt.h	2004-08-10 01:17:58 -05:00
+++ b/src/headers/gpmInt.h	2004-08-10 01:17:58 -05:00
@@ -35,18 +35,6 @@
 /* timeout for the select() syscall */
 #define SELECT_TIME 86400 /* one day */
 
-#ifdef HAVE_LINUX_TTY_H
-#include <linux/tty.h>
-#endif
-
-/* FIXME: still needed ?? */
-/* How many virtual consoles are managed? */
-#ifndef MAX_NR_CONSOLES
-#  define MAX_NR_CONSOLES 64 /* this is always sure */
-#endif
-
-#define MAX_VC    MAX_NR_CONSOLES  /* doesn't work before 1.3.77 */
-
 /* How many buttons may the mouse have? */
 /* #define MAX_BUTTONS 3  ===> not used, it is hardwired :-( */
 
@@ -143,13 +131,6 @@
 #define GPM_EXTRA_MAGIC_1 0xAA
 #define GPM_EXTRA_MAGIC_2 0x55
 
-typedef struct Gpm_Cinfo {
-  Gpm_Connect data;
-  int fd;
-  struct Gpm_Cinfo *next;
-}              Gpm_Cinfo;
-
-
 /*....................................... Global variables */
 
 /* this structure is used to hide the dual-mouse stuff */
@@ -192,7 +173,6 @@
 extern int opt_double;
 
 extern Gpm_Type mice[];             /* where the hell are the descriptions...*/
-extern Gpm_Cinfo *cinfo[MAX_VC+1];
 
 /* new variables <CLEAN> */
 
@@ -240,7 +220,6 @@
        /* gpn.c */
 void cmdline(int argc, char **argv);
 int giveInfo(int request, int fd);
-int loadlut(char *charset);
 int usage(char *whofailed);
 struct Gpm_Type *find_mouse_by_name(char *name);
 void check_uniqueness(void);


More information about the gpm mailing list