import gpm from unix.schottelius.org

Signed-off-by: Nico Schottelius <nico@ikn.schottelius.org>
This commit is contained in:
Nico Schottelius 2009-10-08 22:52:35 +02:00
commit 95a46c5577
5930 changed files with 755263 additions and 0 deletions

View file

@ -0,0 +1,125 @@
/*
* general purpose mouse support for Linux
*
* *several tools only needed by the server*
*
* Copyright (c) 2002-2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
*
* 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 "headers/gpmInt.h"
#include "headers/message.h"
#include "headers/daemon.h"
#include <stdlib.h> /* malloc() */
/* DESCR: add this to the list of mice. initialization follows later */
/* RETURN: - */
/* COMMENT: does error handling and exiting itself */
void add_mouse(int type, char *value)
{
struct micetab *tmp = option.micelist;
/* PREAMBLE for all work: */
/* -m /dev/misc/psaux -t ps2 [ -o options ] */
switch(type) {
/*---------------------------------------------------------------------*/
/********************** -m mousedevice *********************************/
/*---------------------------------------------------------------------*/
case GPM_ADD_DEVICE:
/* first invocation */
if(option.micelist == NULL) {
gpm_report(GPM_PR_DEBUG,"adding mouse device: %s",value);
option.micelist = (struct micetab *) malloc(sizeof(struct micetab));
if(!option.micelist) gpm_report(GPM_PR_OOPS,GPM_MESS_NO_MEM);
option.micelist->next = NULL;
option.micelist->device = value;
option.micelist->protocol = NULL;
option.micelist->options = NULL;
return;
}
/* find actual mouse */
while(tmp->device != NULL && tmp->protocol != NULL && tmp->next !=NULL)
tmp = tmp->next;
gpm_report(GPM_PR_DEBUG,"finished searching");
/* found end of micelist, add new mouse */
if(tmp->next == NULL && tmp->protocol != NULL) {
gpm_report(GPM_PR_DEBUG,"next mouse making");
tmp->next = (struct micetab *) malloc(sizeof(struct micetab));
if(!tmp) gpm_report(GPM_PR_OOPS,GPM_MESS_NO_MEM);
tmp->next = NULL;
tmp->device = value;
tmp->protocol = NULL;
tmp->options = NULL;
return;
} else gpm_report(GPM_PR_OOPS,GPM_MESS_FIRST_DEV);
//} else if(tmp->device != NULL && tmp->protocol == NULL)
// gpm_report(GPM_PR_OOPS,GPM_MESS_FIRST_DEV); /* -m -m */
break;
/*---------------------------------------------------------------------*/
/************************* -t type / protocol **************************/
/*---------------------------------------------------------------------*/
case GPM_ADD_TYPE:
if(option.micelist == NULL) gpm_report(GPM_PR_OOPS,GPM_MESS_FIRST_DEV);
/* skip to next mouse, where either device or protocol is missing */
while(tmp->device != NULL && tmp->protocol != NULL && tmp->next !=NULL)
tmp = tmp->next;
/* check whether device (-m) is there, if so, write protocol */
if(tmp->device == NULL) gpm_report(GPM_PR_OOPS,GPM_MESS_FIRST_DEV);
else {
gpm_report(GPM_PR_DEBUG,"adding mouse type: %s",value);
tmp->protocol = value;
option.no_mice++; /* finally we got our mouse */
}
break;
/*---------------------------------------------------------------------*/
/*************************** -o options ********************************/
/*---------------------------------------------------------------------*/
case GPM_ADD_OPTIONS:
if(option.micelist == NULL) gpm_report(GPM_PR_OOPS,GPM_MESS_FIRST_DEV);
/* look for the last mouse */
tmp = option.micelist;
while(tmp->next != NULL) tmp = tmp->next;
/* if -m or -t are missing exit */
if(tmp->device == NULL || tmp->protocol == NULL)
gpm_report(GPM_PR_OOPS,GPM_MESS_FIRST_DEV);
else {
gpm_report(GPM_PR_DEBUG,"adding mouse options: %s",value);
tmp->options = value;
}
break;
}
}

View file

@ -0,0 +1,58 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <string.h> /* str* */
#include <stdlib.h> /* calloc */
#include "headers/message.h" /* messaging in gpm */
/* build_argv is used for mouse initialization routines */
char **build_argv(char *argv0, char *str, int *argcptr, char sep)
{
int argc = 1;
char **argv;
char *s;
/* argv0 is never NULL, but the extra string may well be */
if (str)
for (s=str; sep && (s = strchr(s, sep)); argc++) s++;
argv = calloc(argc+2, sizeof(char **));
if (!argv) gpm_report(GPM_PR_OOPS,GPM_MESS_ALLOC_FAILED);
argv[0] = argv0;
if (!str) {
*argcptr = argc; /* 1 */
return argv;
}
/* else, add arguments */
s = argv[1] = strdup(str);
argc = 2; /* first to fill */
/* ok, now split: the first one is in place, and s is the whole string */
for ( ; sep && (s = strchr(s, sep)) ; argc++) {
*s = '\0';
s++;
argv[argc] = s;
}
*argcptr = argc;
return argv;
}

View file

@ -0,0 +1,59 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <signal.h> /* kill */
#include <unistd.h> /* unlink */
#include <stdlib.h> /* exit */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
/* itz Sat Sep 12 10:55:51 PDT 1998 Added this as replacement for the
unwanted functionality in check_uniqueness. */
void check_kill(void)
{
int old_pid;
FILE* fp = fopen(GPM_NODE_PID, "r");
/* if we cannot find the old pid file, leave */
if (fp == NULL) gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN, GPM_NODE_PID);
/* else read the pid */
if (fscanf(fp,"%d",&old_pid) != 1)
gpm_report(GPM_PR_OOPS,GPM_MESS_READ_PROB,GPM_NODE_PID);
fclose(fp);
gpm_report(GPM_PR_DEBUG,GPM_MESS_KILLING,old_pid);
/* first check if we run */
if (kill(old_pid,0) == -1) {
gpm_report(GPM_PR_INFO,GPM_MESS_STALE_PID, GPM_NODE_PID);
unlink(GPM_NODE_PID);
}
/* then kill us (not directly, but the other instance ... ) */
if (kill(old_pid,SIGTERM) == -1)
gpm_report(GPM_PR_OOPS,GPM_MESS_CANT_KILL, old_pid);
gpm_report(GPM_PR_INFO,GPM_MESS_KILLED,old_pid);
exit(0);
}

View file

@ -0,0 +1,53 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <signal.h> /* kill */
#include <unistd.h> /* kill, getpid */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
/* itz Sat Sep 12 10:30:05 PDT 1998 this function used to mix two
completely different things; opening a socket to a running daemon
and checking that a running daemon existed. Ugly. */
/* rewritten mostly on 20th of February 2002 - nico */
void check_uniqueness(void)
{
FILE *fp = 0;
int old_pid = -1;
if((fp = fopen(GPM_NODE_PID, "r")) != NULL) {
fscanf(fp, "%d", &old_pid);
if (kill(old_pid,0) == -1) {
gpm_report(GPM_PR_INFO,GPM_MESS_STALE_PID, GPM_NODE_PID);
unlink(GPM_NODE_PID);
} else /* we are really running, exit asap! */
gpm_report(GPM_PR_OOPS,GPM_MESS_ALREADY_RUN, old_pid);
}
/* now try to sign ourself */
if ((fp = fopen(GPM_NODE_PID,"w")) != NULL) {
fprintf(fp,"%d\n",getpid());
fclose(fp);
} else {
gpm_report(GPM_PR_OOPS,GPM_MESS_NOTWRITE,GPM_NODE_PID);
}
}

View file

@ -0,0 +1,90 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <stdlib.h> /* atoi */
#include <unistd.h> /* getopt */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
/*****************************************************************************
* Check the command line and / or set the appropriate variables
* Can't believe it, today cmdline() really does what the name tries to say
*****************************************************************************/
void cmdline(int argc, char **argv)
{
extern struct options option;
char options[]="a:A::b:B:c:d:Dg:hi:kl:m:Mo:pr:R::s:S:t:Tuv23";
int opt;
/* initialize for the dual mouse */
mouse_table[2]=mouse_table[1]=mouse_table[0]; /* copy defaults */
which_mouse = mouse_table+1; /* use the first */
while ((opt = getopt(argc, argv, options)) != -1) {
switch (opt) {
case 'a': (which_mouse->opt_accel) = atoi(optarg); break;
case 'A': opt_aged++;
if (optarg)
opt_age_limit = atoi(optarg); break;
case 'b': (which_mouse->opt_baud) = atoi(optarg); break;
case 'B': (which_mouse->opt_sequence) = optarg; break;
case 'c': (which_mouse->opt_calib) = optarg; break;
case 'd': (which_mouse->opt_delta) = atoi(optarg); break;
case 'D': option.run_status = GPM_RUN_DEBUG; break;
case 'g': (which_mouse->opt_glidepoint_tap)=atoi(optarg); break;
case 'h': exit(usage(NULL));
case 'i': (which_mouse->opt_time)=atoi(optarg); break;
case 'k': check_kill(); break;
case 'l': opt_lut = optarg; break;
case 'm': add_mouse(GPM_ADD_DEVICE,optarg);
(which_mouse->opt_dev) = optarg; break; /* GO AWAY!*/
case 'M': opt_double++; option.repeater++;
if (option.repeater_type == 0)
option.repeater_type = "msc";
which_mouse=mouse_table+2; break;
case 'o': add_mouse(GPM_ADD_OPTIONS,optarg);
gpm_report(GPM_PR_DEBUG,"options: %s",optarg);
(which_mouse->opt_options) = optarg; break; /* GO AWAY */
case 'p': opt_ptrdrag = 0; break;
case 'r':
/* being called responsiveness, I must take the inverse */
(which_mouse->opt_scale)=atoi(optarg);
if(!(which_mouse->opt_scale) || (which_mouse->opt_scale) > 100) (which_mouse->opt_scale)=100; /* the maximum */
else (which_mouse->opt_scale)=100/(which_mouse->opt_scale); break;
case 'R':
option.repeater++;
if (optarg) option.repeater_type = optarg;
else option.repeater_type = "msc"; break;
case 's': (which_mouse->opt_sample) = atoi(optarg); break;
case 'S': if (optarg) opt_special = optarg;
else opt_special=""; break;
case 't': add_mouse(GPM_ADD_TYPE,optarg);
(which_mouse->opt_type) = optarg; break; /* GO AWAY */
case 'u': option.autodetect = 1; break;
case 'T': opt_test++; break;
case 'v': printf(GPM_MESS_VERSION "\n"); exit(0);
case '2': (which_mouse->opt_three) = -1; break;
case '3': (which_mouse->opt_three) = 1; break;
default: exit(usage("commandline"));
}
}
}

View file

@ -0,0 +1,30 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
void disable_paste(int vc)
{
opt_aged++;
gpm_report(GPM_PR_INFO,GPM_MESS_DISABLE_PASTE,vc);
}

View file

@ -0,0 +1,60 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <unistd.h> /* write */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
#include "headers/gpmInt.h" /* daemon internals */
/*-------------------------------------------------------------------*/
/* returns 0 if the event has not been processed, and 1 if it has */
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 */
}

View file

@ -0,0 +1,76 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
#include "headers/gpmInt.h" /* daemon internals */
/*-------------------------------------------------------------------*/
int do_selection(Gpm_Event *event) /* returns 0, always */
{
static int x1=1, y1=1, x2, y2;
#define UNPOINTER() 0
x2=event->x; y2=event->y;
switch(GPM_BARE_EVENTS(event->type)) {
case GPM_MOVE:
if (x2<1) x2++; else if (x2>maxx) x2--;
if (y2<1) y2++; else if (y2>maxy) y2--;
selection_copy(x2,y2,x2,y2,3); /* just highlight pointer */
return 0;
case GPM_DRAG:
if (event->buttons==GPM_B_LEFT) {
if (event->margin) /* fix margins */
switch(event->margin) {
case GPM_TOP: x2=1; y2++; break;
case GPM_BOT: x2=maxx; y2--; break;
case GPM_RGT: x2--; break;
case GPM_LFT: y2<=y1 ? x2++ : (x2=maxx, y2--); break;
}
selection_copy(x1,y1,x2,y2,event->clicks);
if (event->clicks>=opt_ptrdrag && !event->margin) /* pointer */
selection_copy(x2,y2,x2,y2,3);
} /* if */
return 0;
case GPM_DOWN:
switch (event->buttons) {
case GPM_B_LEFT:
x1=x2; y1=y2;
selection_copy(x1,y1,x2,y2,event->clicks); /* start selection */
return 0;
case GPM_B_MIDDLE:
selection_paste();
return 0;
case GPM_B_RIGHT:
if ((which_mouse->opt_three)==1)
selection_copy(x1,y1,x2,y2,event->clicks);
else
selection_paste();
return 0;
}
} /* switch above */
return 0;
}

View file

@ -0,0 +1,49 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <string.h> /* str* */
#include <ctype.h> /* isspace */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
/*****************************************************************************
* the function returns a valid type pointer or NULL if not found
*****************************************************************************/
struct Gpm_Type *find_mouse_by_name(char *name)
{
Gpm_Type *type;
char *s;
int len = strlen(name);
for (type=mice; type->fun; type++) {
if (!strcasecmp(name, type->name)) break;
/* otherwise, look in the synonym list */
for (s = type->synonyms; s; s = strchr(s, ' ')) {
while (*s && isspace(*s)) s++; /* skip spaces */
if(!strncasecmp(name, s, len) && !isprint(*(s + len))) break;/*found*/
}
if(s) break; /* found a synonym */
}
if (!type->fun) return NULL;
return type;
}

View file

@ -0,0 +1,65 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <unistd.h> /* close */
#include <fcntl.h> /* open */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
#include "headers/gpmInt.h" /* daemon internals */
void get_console_size(Gpm_Event *ePtr)
{
int i, prevmaxx, prevmaxy;
struct mouse_features *which_mouse; /* local */
/* before asking the new console size, save the previous values */
prevmaxx = maxx; prevmaxy = maxy;
i=open_console(O_RDONLY);
ioctl(i, TIOCGWINSZ, &win);
close(i);
if (!win.ws_col || !win.ws_row) {
gpm_report(GPM_PR_DEBUG,GPM_MESS_ZERO_SCREEN_DIM);
win.ws_col=80; win.ws_row=25;
}
maxx=win.ws_col; maxy=win.ws_row;
gpm_report(GPM_PR_DEBUG,GPM_MESS_SCREEN_SIZE,maxx,maxy);
if (!prevmaxx) { /* first invocation, place the pointer in the middle */
statusX = ePtr->x = maxx/2;
statusY = ePtr->y = maxy/2;
} else { /* keep the pointer in the same position where it was */
statusX = ePtr->x = ePtr->x * maxx / prevmaxx;
statusY = ePtr->y = ePtr->y * maxy / prevmaxy;
}
for (i=1; i <= 1+opt_double; i++) {
which_mouse=mouse_table+i; /* used to access options */
/*
* the following operation is based on the observation that 80x50
* has square cells. (An author-centric observation ;-)
*/
(which_mouse->opt_scaley)=(which_mouse->opt_scale)*50*maxx/80/maxy;
gpm_report(GPM_PR_DEBUG,GPM_MESS_X_Y_VAL,(which_mouse->opt_scale),(which_mouse->opt_scaley));
}
}

View file

@ -0,0 +1,52 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <unistd.h> /* read */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
#include "headers/gpmInt.h" /* daemon internals */
/*-------------------------------------------------------------------*
* This was inline, and incurred in a compiler bug (2.7.0)
*-------------------------------------------------------------------*/
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;
}

View file

@ -0,0 +1,92 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <errno.h> /* guess what */
#include <unistd.h> /* read */
#include <stdlib.h> /* exit */
#include <string.h> /* strerror */
#include <linux/kd.h> /* KD* */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
#include "headers/gpmInt.h" /* daemon internals */
#include "mice.h" /* GPM MAGIC */
/*-------------------------------------------------------------------
* fetch the actual device data from the mouse device, dependent on
* what Gpm_Type is being passed.
*-------------------------------------------------------------------*/
char *getMouseData(int fd, Gpm_Type *type, int kd_mode)
{
static unsigned char data[32]; /* quite a big margin :) */
char *edata=data+type->packetlen;
int howmany=type->howmany;
int i,j;
/*....................................... read and identify one byte */
if (read(fd, data, howmany)!=howmany) {
if (opt_test) exit(0);
gpm_report(GPM_PR_ERR,GPM_MESS_READ_FIRST, strerror(errno));
return NULL;
}
if (kd_mode!=KD_TEXT && fifofd != -1 && opt_rawrep)
write(fifofd, data, howmany);
if ((data[0]&((which_mouse->m_type)->proto)[0]) != ((which_mouse->m_type)->proto)[1]) {
if ((which_mouse->m_type)->getextra == 1) {
data[1]=GPM_EXTRA_MAGIC_1; data[2]=GPM_EXTRA_MAGIC_2;
gpm_report(GPM_PR_DEBUG,GPM_EXTRA_DATA,data[0]);
return data;
}
gpm_report(GPM_PR_DEBUG,GPM_MESS_PROT_ERR);
return NULL;
}
/*....................................... read the rest */
/*
* well, this seems to work almost right with ps2 mice. However, I've never
* tried ps2 with the original selection package, which called usleep()
*/
if((i=(which_mouse->m_type)->packetlen-howmany)) /* still to get */
do {
j = read(fd,edata-i,i); /* edata is pointer just after data */
if (kd_mode!=KD_TEXT && fifofd != -1 && opt_rawrep && j > 0)
write(fifofd, edata-i, j);
i -= j;
} while (i && j);
if (i) {
gpm_report(GPM_PR_ERR,GPM_MESS_READ_REST, strerror(errno));
return NULL;
}
if ((data[1]&((which_mouse->m_type)->proto)[2]) != ((which_mouse->m_type)->proto)[3]) {
gpm_report(GPM_PR_INFO,GPM_MESS_SKIP_DATA);
return NULL;
}
gpm_report(GPM_PR_DEBUG, GPM_MESS_DATA_4, data[0], data[1], data[2], data[3]);
return data;
}

View file

@ -0,0 +1,43 @@
/*
* general purpose mouse support
*
* 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-2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <signal.h> /* SIG* */
#include <stdlib.h> /* exit() */
#include <unistd.h> /* getpid() */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
void gpm_killed(int signo)
{
if(signo == SIGWINCH) {
gpm_report(GPM_PR_WARN, GPM_MESS_RESIZING, option.progname, getpid());
opt_resize++;
return;
}
if(signo==SIGUSR1) {
gpm_report(GPM_PR_WARN,GPM_MESS_KILLED_BY, option.progname, getpid(), option.progname);
}
exit(0);
}

View file

@ -0,0 +1,116 @@
/*
* general purpose mouse support
*
* 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-2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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/param.h>
#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 <linux/vt.h> /* VT_GETSTATE */
#include <linux/serial.h> /* for serial console check */
#include <sys/kd.h> /* KDGETMODE */
#include <termios.h> /* winsize */
#include "headers/gpmInt.h" /* old daemon header */
#include "headers/message.h"
#include "headers/daemon.h" /* clean daemon header */
/* who the f*** runs gpm without glibc? doesn't have dietlibc __socklent_t? */
#if !defined(__GLIBC__)
typedef unsigned int __socklen_t;
#endif /* __GLIBC__ */
/* global variables that are in daemon.h */
struct options option; /* one should be enough for us */
Gpm_Type *repeated_type = 0;
/* FIXME: BRAINDEAD..ok not really, but got to leave anyway... */
/* argc and argv for mice initialization */
int mouse_argc[3]; /* 0 for default (unused) and two mice */
char **mouse_argv[3]; /* 0 for default (unused) and two mice */
int opt_aged = 0;
int statusX,statusY,statusB; /* to return info */
/*
* all the values duplicated for dual-mouse operation are
* now in this structure (see gpmInt.h)
* mouse_table[0] is single mouse, mouse_table[1] and mouse_table[2]
* are copied data from mouse_table[0] for dual mouse operation.
*/
struct mouse_features mouse_table[3] = {
{
DEF_TYPE, DEF_DEV, DEF_SEQUENCE, DEF_CALIB,
DEF_BAUD, DEF_SAMPLE, DEF_DELTA, DEF_ACCEL, DEF_SCALE, 0 /* scaley */,
DEF_TIME, DEF_CLUSTER, DEF_THREE, DEF_GLIDEPOINT_TAP,
DEF_DMINX, DEF_DMAXX, DEF_DMINY, DEF_DMAXY,
DEF_OMINX, DEF_OMAXX, DEF_OMINY, DEF_OMAXY,
(char *)NULL /* extra */,
(Gpm_Type *)NULL,
-1
}
};
struct mouse_features *which_mouse;
/* These are only the 'global' options */
char *opt_lut=DEF_LUT;
int opt_test=DEF_TEST;
int opt_ptrdrag=DEF_PTRDRAG;
int opt_double=0;
char *opt_special=NULL; /* special commands, like reboot or such */
int opt_rawrep=0;
struct winsize win;
int maxx, maxy;
int fifofd=-1;
int eventFlag=0;
Gpm_Cinfo *cinfo[MAX_VC+1];
time_t last_selection_time;
time_t opt_age_limit = 0;
int opt_resize=0; /* not really an option */
int statusC = 0; /* clicks */
void get_console_size(Gpm_Event *ePtr);
/* in daemon.h */
fd_set selSet, readySet, connSet;

View file

@ -0,0 +1,34 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <unistd.h> /* unlink,geteuid */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
/* what todo atexit */
void gpm_exited(void)
{
gpm_report(GPM_PR_DEBUG,GPM_MESS_REMOVE_FILES, GPM_NODE_PID, GPM_NODE_CTL);
unlink(GPM_NODE_PID);
unlink(GPM_NODE_CTL);
}

View file

@ -0,0 +1,48 @@
/*
* general purpose mouse support for Linux
*
* *several tools only needed by the server*
*
* Copyright (c) 2002-2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
*
* 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 "headers/gpmInt.h"
#include "headers/message.h"
#include "headers/daemon.h"
#include <stdlib.h> /* malloc() */
/* DESCR: mice initialization. currently print mice. */
/* RETURN: 0 - failed to init one or more devices
1 - init was fine */
/* COMMENT: does error handling and exiting itself */
int init_mice(struct micetab *micelist)
{
struct micetab *tmp = micelist;
while(tmp != NULL) { /* there are still mice to init */
gpm_report(GPM_PR_DEBUG,"initialize %s with proto %s",tmp->device,tmp->protocol);
if(tmp->options != NULL) {
gpm_report(GPM_PR_DEBUG,"and options %s",tmp->options);
}
tmp = tmp->next;
}
gpm_report(GPM_PR_DEBUG,"finished initialization");
return 1;
}

View file

@ -0,0 +1,83 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <stdint.h> /* datatypes */
#include <fcntl.h> /* open */
#include <stdlib.h> /* malloc */
#include <string.h> /* str* */
#include <errno.h> /* errno.h */
#include <unistd.h> /* getuid */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
#include "headers/gpmInt.h" /* GPM_SYS_CONSOLE */
int loadlut(char *charset)
{
int i, c, fd;
unsigned char this, next;
static uint32_t long_array[9]={
0x05050505, /* ugly, but preserves alignment */
0x00000000, /* control chars */
0x00000000, /* digits */
0x00000000, /* uppercase and '_' */
0x00000000, /* lowercase */
0x00000000, /* Latin-1 control */
0x00000000, /* Latin-1 misc */
0x00000000, /* Latin-1 uppercase */
0x00000000 /* Latin-1 lowercase */
};
#define inwordLut (long_array+1)
for (i=0; charset[i]; ) {
i += getsym(charset+i, &this);
if (charset[i] == '-' && charset[i + 1] != '\0')
i += getsym(charset+i+1, &next) + 1;
else
next = this;
for (c = this; c <= next; c++)
inwordLut[c>>5] |= 1 << (c&0x1F);
}
if ((fd=open(option.consolename, O_WRONLY)) < 0) {
/* try /dev/console, if /dev/tty0 failed -- is that really senseful ??? */
free(option.consolename); /* allocated by main */
if((option.consolename=malloc(strlen(GPM_SYS_CONSOLE)+1)) == NULL)
gpm_report(GPM_PR_OOPS,GPM_MESS_NO_MEM);
/* FIXME: remove hardcoded device names */
strcpy(option.consolename,GPM_SYS_CONSOLE);
if ((fd=open(option.consolename, O_WRONLY)) < 0) gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN_CON);
}
if (ioctl(fd, TIOCLINUX, &long_array) < 0) { /* fd <0 is checked */
if (errno==EPERM && getuid())
gpm_report(GPM_PR_WARN,GPM_MESS_ROOT); /* why do we still continue?*/
else if (errno==EINVAL)
gpm_report(GPM_PR_OOPS,GPM_MESS_CSELECT);
}
close(fd);
return 0;
}

View file

@ -0,0 +1,35 @@
/*
* general purpose mouse support for Linux
*
* *main.c*
*
* Copyright (c) 2002 Nico Schottelius <nico@schottelius.org>
*
* small main routine
*
* isn't that a nice clean function ?
*
* 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 "gpmInt.h"
int main(int argc, char **argv)
{
startup(argc,argv); /* setup configurations */
old_main(); /* LATER: exit(daemon()); */
return 0; /* if we didn't exit before, just give back success */
}

View file

@ -0,0 +1,255 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <sys/socket.h> /* UNIX */
#include <sys/un.h> /* SOCKET */
#include <fcntl.h> /* open */
#include <signal.h> /* guess again */
#include <errno.h> /* guess again */
#include <unistd.h> /* unlink */
#include <sys/stat.h> /* chmod */
#include <linux/kd.h> /* linux hd* */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
#include "headers/gpmInt.h" /* daemon internals */
#ifndef max
#define max(a,b) ((a)>(b) ? (a) : (b))
#endif
int realposx=-1;
int realposy=-1;
int old_main()
{
int ctlfd, newfd;
struct sockaddr_un ctladdr;
int i, len, kd_mode, fd;
struct timeval timeout;
int maxfd=-1;
int pending;
Gpm_Event event;
for (i = 1; i <= 1+opt_double; i++) {
which_mouse=mouse_table+i; /* used to access options */
if (!(which_mouse->opt_dev)) gpm_report(GPM_PR_OOPS,GPM_MESS_NEED_MDEV);
if(!strcmp((which_mouse->opt_dev),"-")) fd=0; /* use stdin */
else if( (fd=open((which_mouse->opt_dev),O_RDWR | O_NDELAY)) < 0)
gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN,(which_mouse->opt_dev));
/* and then reset the flag */
fcntl(fd,F_SETFL,fcntl(fd,F_GETFL) & ~O_NDELAY);
/* create argc and argv for this device */
mouse_argv[i] = build_argv((which_mouse->opt_type), (which_mouse->opt_options), &mouse_argc[i], ',');
/* init the device, and use the return value as new mouse type */
if ((which_mouse->m_type)->init)
(which_mouse->m_type)=((which_mouse->m_type)->init)(fd, (which_mouse->m_type)->flags, (which_mouse->m_type), mouse_argc[i],
mouse_argv[i]);
if (!(which_mouse->m_type)) gpm_report(GPM_PR_OOPS,GPM_MESS_MOUSE_INIT);
which_mouse->fd=fd;
maxfd=max(fd, maxfd);
}
/*....................................... catch interesting signals */
signal(SIGTERM, gpm_killed);
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);
get_console_size(&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)
FD_ZERO(&connSet);
FD_SET(ctlfd,&connSet);
if (opt_double) FD_SET(mouse_table[2].fd,&connSet);
readySet=connSet;
FD_SET(mouse_table[1].fd,&readySet);
signal(SIGPIPE,SIG_IGN); /* WARN */
/*--------------------------------------- main loop begins here */
while(1) {
selSet=readySet;
resetTimeout();
if (opt_test) timeout.tv_sec=0;
if (eventFlag) { /* an event left over by clustering */
pending=1;
FD_ZERO(&selSet);
FD_SET(mouse_table[eventFlag].fd,&selSet);
}
else
while((pending=select(maxfd+1,&selSet,NULL_SET,NULL_SET,&timeout))==0){
selSet=readySet;
resetTimeout();
} /* go on */
if(opt_resize) { /* did the console resize? */
get_console_size(&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);
}
}
if (pending < 0) {
if (errno==EBADF) gpm_report(GPM_PR_OOPS,GPM_MESS_SELECT_PROB);
gpm_report(GPM_PR_ERR,GPM_MESS_SELECT_STRING,strerror(errno));
selSet=readySet;
resetTimeout();
continue;
}
gpm_report(GPM_PR_DEBUG,GPM_MESS_SELECT_TIMES,pending);
/*....................................... manage graphic mode */
/*
* Be sure to be in text mode. This used to be before select,
* but actually it only matters if you have events.
*/
{
int fd = open_console(O_RDONLY);
if (ioctl(fd, KDGETMODE, &kd_mode) < 0)
gpm_report(GPM_PR_OOPS,GPM_MESS_IOCTL_KDGETMODE);
close(fd);
if(kd_mode != KD_TEXT && !option.repeater) {
wait_text(&mouse_table[1].fd);
maxfd=max(maxfd,mouse_table[1].fd);
readySet=connSet;
FD_SET(mouse_table[1].fd,&readySet);
continue; /* reselect */
}
}
/*....................................... got mouse, process event */
/*
* Well, actually, run a loop to maintain inlining of functions without
* lenghtening the file. This is not too clean a code, but it works....
*/
for (i=1; i <= 1+opt_double; i++) {
which_mouse=mouse_table+i; /* used to access options */
if (FD_ISSET(which_mouse->fd,&selSet)) {
FD_CLR(which_mouse->fd,&selSet); pending--;
if (processMouse(which_mouse->fd, &event, (which_mouse->m_type), kd_mode))
/* pass it to the client, if any
* or to the default handler, if any
* or to the selection handler
*/ /* FIXME -- check event.vc */
/* can't we please rewrite the following a bit nicer?*/
(cinfo[event.vc] && do_client(cinfo[event.vc], &event))
|| (cinfo[0] && do_client(cinfo[0], &event))
|| do_selection(&event);
}
}
/*..................... 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);
}
}
/*........................ 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;
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
}
}
}
/*.................. 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);
pending--;
gpm_report(GPM_PR_WARN,GPM_MESS_STRANGE_DATA,i);
}
}
/*................... all done. */
if(pending) gpm_report(GPM_PR_OOPS,GPM_MESS_SELECT_PROB);
} /* while(1) */
}

View file

@ -0,0 +1,56 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <fcntl.h> /* open and co. */
#include <sys/stat.h> /* stat() */
#include <stropts.h> /* ioctl */
/* Linux specific (to be outsourced in gpm2 */
#include <linux/serial.h> /* for serial console check */
#include <asm/ioctls.h> /* for serial console check */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
int open_console(const int mode)
{
int fd;
int maj;
int twelve = 12;
struct serial_struct si;
struct stat sb;
fd = open(option.consolename, mode);
if (fd != -1) {
fstat(fd, &sb);
maj = major(sb.st_rdev);
if (maj != 4 && (maj < 136 || maj > 143)) {
if (ioctl(fd, TIOCLINUX, &twelve) < 0) {
if (si.line > 0) {
gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN_SERIALCON);
}
}
}
return fd;
} else
gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN_CON);
}

View file

@ -0,0 +1,156 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <sys/socket.h> /* accept */
#include <stdlib.h> /* malloc */
#include <unistd.h> /* close */
#include <sys/un.h> /* unix socket */
#include <sys/stat.h> /* stat */
#include <string.h> /* str* */
#include <errno.h> /* errno.h */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
int processConn(int fd) /* returns newfd or -1 */
{
Gpm_Cinfo *info;
Gpm_Connect *request;
Gpm_Cinfo *next;
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 */
struct stat statbuf;
uid_t uid;
char *tty = NULL;
/*....................................... 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) {
if(( tty =
malloc(strlen(option.consolename)+Gpm_cnt_digits(vc) + sizeof(char))) == NULL)
gpm_report(GPM_PR_OOPS,GPM_MESS_NO_MEM);
strncpy(tty,option.consolename,strlen(option.consolename)-1);
sprintf(&tty[strlen(option.consolename)-1],"%d",vc);
if(stat(tty, &statbuf) == -1) {
gpm_report(GPM_PR_ERR,GPM_MESS_STAT_FAILS,tty);
free(info);
free(tty);
close(newfd);
return -1;
}
if (uid != statbuf.st_uid) {
gpm_report(GPM_PR_WARN,GPM_MESS_FAILED_CONNECT, uid, tty); /*SUSPECT!*/
free(info);
free(tty);
close(newfd);
return -1;
}
free(tty); /* at least here it's not needed anymore */
}
/* register the connection information in the right place */
info->next=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;
}

View file

@ -0,0 +1,369 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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.
*
* call getMouseData to get hardware device data, call mouse device's fun()
* to retrieve the hardware independent event data, then optionally repeat
* the data via repeat_fun() to the repeater device
*
********/
#include <sys/stat.h> /* stat */
#include <linux/kd.h> /* KD */
#include <linux/vt.h> /* vt */
#include <fcntl.h> /* open */
#include <unistd.h> /* close */
#include <time.h> /* time */
#include <sys/time.h> /* gettimeofday */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
#define abs(value) ((value) < 0 ? -(value) : (value))
#define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *)NULL))
#define DIF_TIME(t1,t2) ((t2.tv_sec -t1.tv_sec) *1000 + \
(t2.tv_usec-t1.tv_usec)/1000)
int processMouse(int fd, Gpm_Event *event, Gpm_Type *type, int kd_mode)
{
char *data;
static int fine_dx,
fine_dy,
i, j, m,
newB=0, /* old buttons and Type to chain events */
oldB=0,
oldT=0;
static Gpm_Event nEvent;
static struct vt_stat stat;
static struct timeval tv1={0,0}, tv2; /* tv1==0: first click is single */
static struct timeval timeout={0,0};
fd_set fdSet;
int tempx, tempy;
static int oldx, oldy;
oldT = event->type;
if(eventFlag) {
eventFlag=0;
if((which_mouse->m_type)->absolute) { /* a pen or other absolute device */
event->x=nEvent.x;
event->y=nEvent.y;
}
event->dx=nEvent.dx;
event->dy=nEvent.dy;
event->buttons=nEvent.buttons;
} else {
event->dx=event->dy = 0;
event->wdx=event->wdy = 0;
nEvent.modifiers = 0; /* some mice set them */
i = 0;
FD_ZERO(&fdSet);
FD_SET(fd,&fdSet);
/* use uncalibrated values as base values */
if((which_mouse->opt_calib!=NULL)&&(which_mouse->m_type->absolute)){
nEvent.x = oldx;
nEvent.y = oldy;
}
do { /* cluster loop */
if(((data=getMouseData(fd, (which_mouse->m_type), kd_mode)) == NULL)
|| ((*((which_mouse->m_type)->fun))(&nEvent,data)==-1) ) {
if (!i) {
return 0;
} else {
break;
}
}
event->modifiers = nEvent.modifiers; /* propagate modifiers */
/* propagate buttons */
nEvent.buttons = ((which_mouse->opt_sequence)[nEvent.buttons&7]&7) |
(nEvent.buttons & ~7); /* change the order */
oldB=newB; newB=nEvent.buttons;
if (!i) event->buttons=nEvent.buttons;
if (oldB != newB) {
eventFlag = (i!=0)*(which_mouse-mouse_table); /* 1 or 2 */
break;
}
/* propagate movement */
if (!((which_mouse->m_type)->absolute)) { /* mouse */
if (abs(nEvent.dx)+abs(nEvent.dy) > (which_mouse->opt_delta))
nEvent.dx*=(which_mouse->opt_accel), nEvent.dy*=(which_mouse->opt_accel);
/* increment the reported dx,dy */
event->dx+=nEvent.dx;
event->dy+=nEvent.dy;
} else { /* a pen */
/* get dx,dy to check if there has been movement */
event->dx = (nEvent.x) - (event->x);
event->dy = (nEvent.y) - (event->y);
}
/* propagate wheel */
event->wdx += nEvent.wdx;
event->wdy += nEvent.wdy;
select(fd+1,&fdSet,(fd_set *)NULL,(fd_set *)NULL,&timeout/* zero */);
} while (i++ <(which_mouse->opt_cluster) && nEvent.buttons==oldB && FD_ISSET(fd,&fdSet));
/* apply calibration */
if((which_mouse->opt_calib!=NULL)&&(which_mouse->m_type->absolute)){
/* save uncalibrated values for use next time around */
oldx = nEvent.x;
oldy = nEvent.y;
/* do calculations in a larger variable */
tempx = nEvent.x;
tempy = nEvent.y;
tempx -= which_mouse->opt_dminx;
tempx *= ( which_mouse->opt_omaxx - which_mouse->opt_ominx );
tempx /= ( which_mouse->opt_dmaxx - which_mouse->opt_dminx );
tempx += which_mouse->opt_ominx;
tempy -= which_mouse->opt_dminy;
tempy *= ( which_mouse->opt_omaxy - which_mouse->opt_ominy );
tempy /= ( which_mouse->opt_dmaxy - which_mouse->opt_dminy );
tempy += which_mouse->opt_ominy;
nEvent.x = tempx;
nEvent.y = tempy;
event->dx = (nEvent.x) - (event->x);
event->dy = (nEvent.y) - (event->y);
}
} /* if(eventFlag) */
/*....................................... update the button number */
if ((event->buttons&GPM_B_MIDDLE) && !(which_mouse->opt_three)) (which_mouse->opt_three)++;
/*....................................... we're a repeater, aren't we? */
if (kd_mode!=KD_TEXT) {
if (fifofd != -1 && ! opt_rawrep) {
if ((which_mouse->m_type)->absolute) { /* hof Wed Feb 3 21:43:28 MET 1999 */
/* prepare the values from a absolute device for repeater mode */
static struct timeval rept1,rept2;
gettimeofday(&rept2, (struct timezone *)NULL);
if (((rept2.tv_sec -rept1.tv_sec)
*1000+(rept2.tv_usec-rept1.tv_usec)/1000)>250) {
event->dx=0;
event->dy=0;
}
rept1=rept2;
/* if the values are calibrated, this is not necessary */
if(which_mouse->opt_calib==NULL)
event->dy=event->dy*((win.ws_col/win.ws_row)+1);
event->x=nEvent.x;
event->y=nEvent.y;
}
/* not all relative repeaters can handle big changes,
so repackage into several smaller updates */
if (!repeated_type->absolute) {
int remx, remy;
remx = event->dx;
remy = event->dy;
do {
if (remx<0) {
if (remx>=-127) {
event->dx = remx;
remx = 0;
} else {
event->dx = -127;
remx += 127;
}
}
if (remx>0) {
if (remx<=127) {
event->dx = remx;
remx = 0;
} else {
event->dx = 127;
remx -= 127;
}
}
if (remy<0) {
if (remy>=-127) {
event->dy = remy;
remy = 0;
} else {
event->dy = -127;
remy += 127;
}
}
if (remy>0) {
if (remy<=127) {
event->dy = remy;
remy = 0;
} else {
event->dy = 127;
remy -= 127;
}
}
repeated_type->repeat_fun(event, fifofd);
} while((remx!= 0)||(remy!=0));
}
else
repeated_type->repeat_fun(event, fifofd); /* itz Jan 11 1999 */
}
return 0; /* no events nor information for clients */
} /* first if of these three */
/*....................................... no, we arent a repeater, go on */
/* use fine delta values now, if delta is the information */
if (!((which_mouse->m_type))->absolute) {
fine_dx+=event->dx; fine_dy+=event->dy;
event->dx=fine_dx/(which_mouse->opt_scale); event->dy=fine_dy/(which_mouse->opt_scaley);
fine_dx %= (which_mouse->opt_scale); fine_dy %= (which_mouse->opt_scaley);
}
/* up and down, up and down, ... who does a do..while(0) loop ???
and then makes a break into it... argh ! */
/* rodney 13/mar/2008 wheel movement similar to mouse movement
* must also be excluded from time (click) processing */
if (!event->dx && !event->dy
&& !event->wdx && !event->wdy
&& (event->buttons==oldB) )
do { /* so to break */
static long awaketime;
/*
* Ret information also if never happens, but enough time has elapsed.
* Note: return 1 will segfault due to missing event->vc; FIXME!
*/
if (time(NULL)<=awaketime) return 0;
awaketime=time(NULL)+1;
break;
} while (0);
/*....................................... fill missing fields */
event->x+=event->dx, event->y+=event->dy;
statusB=event->buttons;
i=open_console(O_RDONLY);
/* modifiers */
j = event->modifiers; /* save them */
event->modifiers=6; /* code for the ioctl */
if (ioctl(i,TIOCLINUX,&(event->modifiers))<0)
gpm_report(GPM_PR_OOPS,GPM_MESS_GET_SHIFT_STATE);
event->modifiers |= j; /* add mouse-specific bits */
/* status */
j = stat.v_active;
if (ioctl(i,VT_GETSTATE,&stat)<0) gpm_report(GPM_PR_OOPS,GPM_MESS_GET_CONSOLE_STAT);
/*
* if we changed console, request the current console size,
* as different consoles can be of different size
*/
if (stat.v_active != j)
get_console_size(event);
close(i);
event->vc = stat.v_active;
if (oldB==event->buttons)
event->type = (event->buttons ? GPM_DRAG : GPM_MOVE);
else
event->type = (event->buttons > oldB ? GPM_DOWN : GPM_UP);
switch(event->type) { /* now provide the cooked bits */
case GPM_DOWN:
GET_TIME(tv2);
if (tv1.tv_sec && (DIF_TIME(tv1,tv2)<(which_mouse->opt_time))) /* check first click */
statusC++, statusC%=3; /* 0, 1 or 2 */
else
statusC=0;
event->type|=(GPM_SINGLE<<statusC);
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);
break;
case GPM_DRAG:
event->type |= GPM_MFLAG;
event->type|=(GPM_SINGLE<<statusC);
break;
case GPM_MOVE:
statusC=0;
default:
break;
}
event->clicks=statusC;
/* UGLY - FIXME! */
/* The current policy is to force the following behaviour:
* - At buttons up, must fit inside the screen, though flags are set.
* - At button down, allow going outside by one single step
*/
/* selection used 1-based coordinates, so do I */
/*
* 1.05: only one margin is current. Y takes priority over X.
* The i variable is how much margin is allowed. "m" is which one is there.
*/
m = 0;
i = ((event->type&(GPM_DRAG|GPM_UP))!=0); /* i is boolean */
if (event->y>win.ws_row) {event->y=win.ws_row+1-!i; i=0; m = GPM_BOT;}
else if (event->y<=0) {event->y=1-i; i=0; m = GPM_TOP;}
if (event->x>win.ws_col) {event->x=win.ws_col+1-!i; if (!m) m = GPM_RGT;}
else if (event->x<=0) {event->x=1-i; if (!m) m = GPM_LFT;}
event->margin=m;
gpm_report(GPM_PR_DEBUG,"dx: %3i dy: %3i x: %3i y: %3i butt: %i vc: %i clicks: %i",
event->dx,event->dy,
event->x,event->y,
event->buttons, event->vc,
event->clicks);
/* update the global state */
statusX=event->x;
statusY=event->y;
if (opt_special && event->type & GPM_DOWN)
return processSpecial(event);
return 1;
}

View file

@ -0,0 +1,113 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <unistd.h> /* close */
#include <fcntl.h> /* open */
#include <stdlib.h> /* free */
#include <linux/vt.h> /* vt */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
int processRequest(Gpm_Cinfo *ci, int vc)
{
int i;
Gpm_Cinfo *cinfoPtr;
Gpm_Cinfo *next;
Gpm_Connect conn;
static Gpm_Event event;
static struct vt_stat stat;
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:
i = open_console(O_RDONLY);
ioctl(i,VT_GETSTATE,&stat);
event.modifiers=6; /* code for the ioctl */
if (ioctl(i,TIOCLINUX,&(event.modifiers))<0)
gpm_report(GPM_PR_OOPS,GPM_MESS_GET_SHIFT_STATE);
close(i);
event.vc = stat.v_active;
event.x=statusX; event.y=statusY;
event.dx=maxx; event.dy=maxy;
event.buttons= statusB;
event.clicks=statusC;
/* fall through */
/* missing break or do you want this ??? */
case GPM_REQ_BUTTONS:
event.type= ((which_mouse->opt_three)==1 ? 3 : 2); /* buttons */
write(ci->fd,&event,sizeof(Gpm_Event));
break;
case GPM_REQ_NOPASTE:
disable_paste(vc);
break;
}
return 0;
}
/*-------------------------------------------------------------------*/

View file

@ -0,0 +1,169 @@
/*
* special commands support for gpm
*
* Copyright 1996 Alessandro Rubini <rubini@linux.it>
* Copyright 1998 Ian Zimmerman <itz@rahul.net>
* Copyright 2001-2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* Based on an idea by KARSTEN@piobelix.physik.uni-karlsruhe.de
* (Karsten Ballueder)
*
* 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.
********/
/* This file is compiled conditionally, see the Makefile */
#include <linux/limits.h> /* for OPEN_MAX */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#include <sys/param.h>
#include "headers/gpmInt.h"
#include "headers/daemon.h" /* daemon internals */
/*
* This function is only called at button press, to avoid unnecessary
* overhead due to function call at every mouse event
*/
static int special_status = 0; /* turns on when active */
static int did_parse = 0;
/*
* The actions are described by these strings. The default is:
* left: kill -2 init
* middle: shutdown -h now
* right: shutdown -r now
*
* such a default can be overridden by the argument of the "-S" command.
* This arg is a colon-separated list of commands. An empty command
* is used to make gpm kill init
*/
static char *commandL=NULL; /* kill init */
static char *commandM="shutdown -h now";
static char *commandR="shutdown -r now";
/*
* The return value is 0 if the event has been eaten,
* 1 if the event is passed on
*/
int processSpecial(Gpm_Event *event)
{
char *command=NULL; int i;
FILE *consolef;
if ((event->type & GPM_TRIPLE)
&& (event->buttons == (GPM_B_LEFT|GPM_B_RIGHT))) /* trigger */
special_status=time(NULL);
if (!special_status) /* not triggered: return */
return 1;
/* devfs change */
consolef=fopen(option.consolename,"w");
if (!consolef) consolef=stderr;
if (event->type & GPM_TRIPLE) /* just triggered: make noise and return */
{
if (!did_parse)
{
did_parse++;
if (opt_special && opt_special[0]) /* not empty */
{
commandL = opt_special;
commandM = strchr(opt_special, ':');
if (commandM)
{
*commandM='\0'; commandM++;
commandR = strchr(commandM, ':');
if (commandR)
{ *commandR='\0'; commandR++; }
}
}
}
fprintf(consolef,"\n%s: release all the mouse buttons and press "
"one of them\n\twithin three seconds in order to invoke "
"a special command\a\a\a\n", option.progname);
#ifdef DEBUG
fprintf(consolef,"gpm special: the commands are \"%s\", \"%s\", \"%s\"\n",
commandL, commandM, commandR);
#endif
if (consolef!=stderr) fclose(consolef);
return 0; /* eaten */
}
if (time(NULL) > special_status+3)
{
fprintf(consolef,"\n%s: timeout: no special command taken\n", option.progname);
if (consolef!=stderr) fclose(consolef);
special_status=0;
return 0; /* eaten -- don't paste or such on this event */
}
special_status=0; /* run now, prevent running next time */
#ifdef DEBUG
fprintf(consolef,"going to run: buttons is %i\n",event->buttons);
#endif
switch(event->buttons)
{
case GPM_B_LEFT: command=commandL; break;
case GPM_B_MIDDLE: command=commandM; break;
case GPM_B_RIGHT: command=commandR; break;
default:
fprintf(consolef,"\n%s: more than one button: "
"special command discarded\n",option.progname);
if (consolef!=stderr) fclose(consolef);
return 0; /* eaten */
}
fprintf(consolef,"\n%s: executing ", option.progname);
if (!command || !command[0])
{
fprintf(consolef,"hard reboot (by signalling init)\n");
if (consolef!=stderr) fclose(consolef);
kill(1,2); /* kill init: shutdown now */
return 0;
}
fprintf(consolef,"\"%s\"\n",command);
if (consolef!=stderr) fclose(consolef);
switch(fork())
{
case -1: /* error */
fprintf(stderr,"%s: fork(): %s\n", option.progname, strerror(errno));
return 0; /* Hmmm.... error */
case 0: /* child */
close(0); close(1); close(2);
open(GPM_NULL_DEV,O_RDONLY); /* stdin */
open(option.consolename,O_WRONLY); /* stdout */
dup(1); /* stderr */
int open_max = sysconf(_SC_OPEN_MAX);
if (open_max == -1) open_max = 1024;
for (i=3;i<open_max; i++) close(i);
execl("/bin/sh","sh","-c",command,(char *)NULL);
exit(1); /* shouldn't happen */
default: /* parent */
return 0;
}
}

View file

@ -0,0 +1,55 @@
/*
* general purpose mouse support for Linux
*
* *several tools only needed by the server*
*
* Copyright (c) 2002-2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
*
* 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 "headers/gpmInt.h"
#include "headers/message.h"
#include "headers/daemon.h"
#include <stdlib.h> /* malloc() */
/* DESCR: when leaving, we should reset mice to their normal state */
/* RETURN: 0 - failed to reset one or more devices
1 - reset was fine */
/* COMMENT: does error handling and exiting itself */
int reset_mice(struct micetab *micelist)
{
struct micetab *tmp = micelist;
struct micetab *end = tmp;
while(tmp != NULL) { /* FIXME! I never get NULL, as free()d before */
end = tmp;
while(tmp->next != NULL) { /* set end to the last mouse */
end = tmp;
tmp = tmp->next;
}
gpm_report(GPM_PR_DEBUG,"reset: %s with proto %s",end->device,end->protocol);
if(tmp->options != NULL) {
gpm_report(GPM_PR_DEBUG,"and options %s",end->options);
}
free(end); /* be clean() */
tmp = micelist; /* reset to the first mice again */
}
return 1;
}

View file

@ -0,0 +1,61 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <fcntl.h> /* open */
#include <unistd.h> /* close */
#include <time.h> /* time */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
void selection_copy(int x1, int y1, int x2, int y2, int mode)
{
/*
* The approach in "selection" causes a bus error when run under SunOS 4.1
* due to alignment problems...
*/
unsigned char buf[6*sizeof(short)];
unsigned short *arg = (unsigned short *)buf + 1;
int fd;
buf[sizeof(short)-1] = 2; /* set selection */
arg[0]=(unsigned short)x1;
arg[1]=(unsigned short)y1;
arg[2]=(unsigned short)x2;
arg[3]=(unsigned short)y2;
arg[4]=(unsigned short)mode;
if ((fd=open_console(O_WRONLY))<0)
gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN_CON);
/* FIXME: should be replaced with string constant (headers/message.h) */
gpm_report(GPM_PR_DEBUG,"ctl %i, mode %i",(int)*buf, arg[4]);
if (ioctl(fd, TIOCLINUX, buf+sizeof(short)-1) < 0)
gpm_report(GPM_PR_OOPS,GPM_MESS_IOCTL_TIOCLINUX);
close(fd);
if (mode < 3) {
opt_aged = 0;
last_selection_time = time(0);
}
}

View file

@ -0,0 +1,49 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <time.h> /* time */
#include <fcntl.h> /* open */
#include <unistd.h> /* close */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
void selection_paste(void)
{
char c=3;
int fd;
if (!opt_aged && (0 != opt_age_limit) &&
(last_selection_time + opt_age_limit < time(0))) {
opt_aged = 1;
}
if (opt_aged) {
gpm_report(GPM_PR_DEBUG,GPM_MESS_SKIP_PASTE);
return;
}
fd=open_console(O_WRONLY);
if(ioctl(fd, TIOCLINUX, &c) < 0)
gpm_report(GPM_PR_OOPS,GPM_MESS_IOCTL_TIOCLINUX);
close(fd);
}

View file

@ -0,0 +1,166 @@
/*
* general purpose mouse support for Linux
*
* *Startup and Daemon functions*
*
* Copyright (c) 2002-2008 Nico Schottelius <nico@schottelius.org>
*
* 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 <stdlib.h> /* atexit() */
#include <string.h> /* strlen() */
#include <errno.h> /* errno */
#include <unistd.h> /* unlink,geteuid */
#include <sys/types.h> /* geteuid, mknod */
#include <sys/stat.h> /* mknod */
#include <fcntl.h> /* mknod */
#include "headers/gpmInt.h"
#include "headers/message.h"
#include "headers/daemon.h"
void startup(int argc, char **argv)
{
int i, opt;
FILE* calib_file;
static struct {
char *in;
char *out;
} seq[] = {
{"123","01234567"},
{"132","02134657"},
{"213","01452367"}, /* warning: these must be readable as integers... */
{"231","02461357"},
{"312","04152637"},
{"321","04261537"},
{NULL,NULL}
};
/* basic settings */
option.run_status = GPM_RUN_STARTUP; /* 10,9,8,... let's go */
option.autodetect = 0; /* no mouse autodection */
option.progname = argv[0]; /* who we are */
option.consolename = Gpm_get_console(); /* get consolename */
/* basic2: are not necessary for oops()ing, if not root */
option.no_mice = 0; /* counts -m + -t */
option.micelist = NULL; /* no mice found yet */
option.repeater = 0; /* repeat data */
option.repeater_type = NULL; /* type of */
cmdline(argc, argv); /* parse command line */
if (geteuid() != 0) gpm_report(GPM_PR_OOPS,GPM_MESS_ROOT); /* root or exit */
/* Planned for gpm-1.30, but only with devfs */
/* if(option.autodetect) autodetect(); */
/****************** OLD CODE from gpn.c ***********************/
openlog(option.progname, LOG_PID,
option.run_status != GPM_RUN_DEBUG ? LOG_DAEMON : LOG_USER);
loadlut(opt_lut);
if (option.repeater) {
if(mkfifo(GPM_NODE_FIFO,0666) && errno!=EEXIST)
gpm_report(GPM_PR_OOPS,GPM_MESS_CREATE_FIFO,GPM_NODE_FIFO);
if((fifofd=open(GPM_NODE_FIFO, O_RDWR|O_NONBLOCK)) < 0)
gpm_report(GPM_PR_OOPS, GPM_MESS_OPEN, GPM_NODE_FIFO);
}
/* duplicate initialization */
for (i=1; i <= 1+opt_double; i++) {
which_mouse=mouse_table+i; /* used to access options */
if ((which_mouse->opt_accel) < 1) exit(usage("acceleration"));
if ((which_mouse->opt_delta) < 2) exit(usage("delta"));
if (strlen((which_mouse->opt_sequence)) != 3 || atoi((which_mouse->opt_sequence))<100)
exit(usage("sequence"));
if ((which_mouse->opt_glidepoint_tap) > 3) exit(usage("glidepoint tap button"));
if ((which_mouse->opt_glidepoint_tap))
(which_mouse->opt_glidepoint_tap)=GPM_B_LEFT >> ((which_mouse->opt_glidepoint_tap)-1);
/* choose the sequence */
for (opt=0; seq[opt].in && strcmp(seq[opt].in,(which_mouse->opt_sequence)); opt++) ;
if(!seq[opt].in) exit(usage("button sequence"));
(which_mouse->opt_sequence)=strdup(seq[opt].out); /* I can rewrite on it */
/* look for the mouse type */
(which_mouse->m_type) = find_mouse_by_name((which_mouse->opt_type));
if (!(which_mouse->m_type)) /* not found */
exit(M_listTypes());
if (which_mouse->opt_calib!=NULL) {
calib_file = fopen(which_mouse->opt_calib,"r");
if (calib_file) {
if (fscanf(calib_file, "%i %i %i %i %i %i %i %i",
&which_mouse->opt_dminx, &which_mouse->opt_dmaxx, &which_mouse->opt_dminy, &which_mouse->opt_dmaxy,
&which_mouse->opt_ominx, &which_mouse->opt_omaxx, &which_mouse->opt_ominy, &which_mouse->opt_omaxy)!= 8)
which_mouse->opt_calib = NULL;
if ((which_mouse->opt_dminx>=which_mouse->opt_dmaxx)||
(which_mouse->opt_dminy>=which_mouse->opt_dmaxy)||
(which_mouse->opt_ominx>=which_mouse->opt_omaxx)||
(which_mouse->opt_ominy>=which_mouse->opt_omaxy))
which_mouse->opt_calib = NULL;
}
fclose(calib_file);
}
}
/* Check repeater status */
if (option.repeater) {
if (strcmp(option.repeater_type,"raw") == 0)
opt_rawrep = 1;
else {
/* look for the type */
repeated_type = find_mouse_by_name(option.repeater_type);
if(!repeated_type) exit(M_listTypes()); /* not found */
if (!(repeated_type->repeat_fun)) /* unsupported translation */
gpm_report(GPM_PR_OOPS,GPM_MESS_NO_REPEAT,option.repeater_type);
}
}
if(option.run_status == GPM_RUN_STARTUP ) { /* else is debugging */
/* goto background and become a session leader (Stefan Giessler) */
switch(fork()) {
case -1: gpm_report(GPM_PR_OOPS,GPM_MESS_FORK_FAILED); /* error */
case 0: option.run_status = GPM_RUN_DAEMON; break; /* child */
default: _exit(0); /* parent */
}
if (setsid() < 0) gpm_report(GPM_PR_OOPS,GPM_MESS_SETSID_FAILED);
}
/* damon init: check whether we run or not, display message */
check_uniqueness();
gpm_report(GPM_PR_INFO,GPM_MESS_STARTED);
/* is changing to root needed, because of relative paths ? or can we just
* remove and ignore it ?? FIXME */
if (chdir("/") < 0) gpm_report(GPM_PR_OOPS,GPM_MESS_CHDIR_FAILED);
//return mouse_table[1].fd; /* the second is handled in the main() */
/****************** OLD CODE from gpn.c END ***********************/
init_mice(option.micelist); /* reads option.micelist */
atexit(gpm_exited); /* call gpm_exited at the end */
}

View file

@ -0,0 +1,35 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
int usage(char *whofailed)
{
if (whofailed) {
gpm_report(GPM_PR_ERR,GPM_MESS_SPEC_ERR,whofailed,option.progname);
return 1;
}
printf(GPM_MESS_USAGE,option.progname, DEF_ACCEL, DEF_BAUD, DEF_SEQUENCE,
DEF_DELTA, DEF_TIME, DEF_LUT,DEF_SCALE, DEF_SAMPLE, DEF_TYPE);
return 1;
}

View file

@ -0,0 +1,52 @@
/*
* general purpose mouse (gpm)
*
* Copyright (c) 2008 Nico Schottelius <nico-gpm2008 at schottelius.org>
*
* 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 <unistd.h> /* sleep() */
#include <fcntl.h> /* open */
#include <linux/kd.h> /* KDGETMODE */
#include "headers/message.h" /* messaging in gpm */
#include "headers/daemon.h" /* daemon internals */
#include "headers/gpmInt.h" /* evil old headers */
int wait_text(int *fdptr)
{
int fd;
int kd_mode;
close(*fdptr);
do
{
sleep(2);
fd = open_console(O_RDONLY);
if (ioctl(fd, KDGETMODE, &kd_mode)<0)
gpm_report(GPM_PR_OOPS,GPM_MESS_IOCTL_KDGETMODE);
close(fd);
} while (kd_mode != KD_TEXT);
/* reopen, reinit (the function is only used if we have one mouse device) */
if ((*fdptr=open((which_mouse->opt_dev),O_RDWR))<0)
gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN,(which_mouse->opt_dev));
if ((which_mouse->m_type)->init)
(which_mouse->m_type)=((which_mouse->m_type)->init)(*fdptr, (which_mouse->m_type)->flags, (which_mouse->m_type), mouse_argc[1],
mouse_argv[1]);
return (1);
}