Added partial lua support

This commit is contained in:
Vysheng 2014-01-12 04:43:29 +04:00
parent 4b92fc1c7f
commit 6b0d354e69
16 changed files with 2842 additions and 21 deletions

View File

@ -1,19 +1,19 @@
srcdir=.
CFLAGS=-g -O2
CFLAGS=-g -O2 -I/usr/include/lua5.2
LDFLAGS=
CPPFLAGS=
DEFS=-DHAVE_CONFIG_H
COMPILE_FLAGS=${CFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Wextra -Werror -Wno-deprecated -fno-strict-aliasing -fno-omit-frame-pointer -ggdb
EXTRA_LIBS= -lreadline -lrt -lconfig
EXTRA_LIBS= -lreadline -lrt -lconfig -llua5.2 -ldl
LOCAL_LDFLAGS=-lm -lcrypto -lz -lssl -rdynamic -ggdb ${EXTRA_LIBS}
LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS}
HEADERS= ${srcdir}/constants.h ${srcdir}/include.h ${srcdir}/interface.h ${srcdir}/LICENSE.h ${srcdir}/loop.h ${srcdir}/mtproto-client.h ${srcdir}/mtproto-common.h ${srcdir}/net.h ${srcdir}/no-preview.h ${srcdir}/queries.h ${srcdir}/structures.h ${srcdir}/telegram.h ${srcdir}/tree.h ${srcdir}/config.h ${srcdir}/binlog.h
HEADERS= ${srcdir}/constants.h ${srcdir}/include.h ${srcdir}/interface.h ${srcdir}/LICENSE.h ${srcdir}/loop.h ${srcdir}/mtproto-client.h ${srcdir}/mtproto-common.h ${srcdir}/net.h ${srcdir}/no-preview.h ${srcdir}/queries.h ${srcdir}/structures.h ${srcdir}/telegram.h ${srcdir}/tree.h ${srcdir}/config.h ${srcdir}/binlog.h ${srcdir}/tools.h ${srcdir}/lua-tg.h
INCLUDE=-I. -I${srcdir}
CC=gcc
OBJECTS=main.o loop.o interface.o net.o mtproto-common.o mtproto-client.o queries.o structures.o binlog.o tools.o
OBJECTS=main.o loop.o interface.o net.o mtproto-common.o mtproto-client.o queries.o structures.o binlog.o tools.o lua-tg.o
.SUFFIXES:

View File

@ -10,10 +10,10 @@ EXTRA_LIBS=@EXTRA_LIBS@
LOCAL_LDFLAGS=-lm -lcrypto -lz -lssl -rdynamic -ggdb ${EXTRA_LIBS}
LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS}
HEADERS= ${srcdir}/constants.h ${srcdir}/include.h ${srcdir}/interface.h ${srcdir}/LICENSE.h ${srcdir}/loop.h ${srcdir}/mtproto-client.h ${srcdir}/mtproto-common.h ${srcdir}/net.h ${srcdir}/no-preview.h ${srcdir}/queries.h ${srcdir}/structures.h ${srcdir}/telegram.h ${srcdir}/tree.h ${srcdir}/config.h ${srcdir}/binlog.h
HEADERS= ${srcdir}/constants.h ${srcdir}/include.h ${srcdir}/interface.h ${srcdir}/LICENSE.h ${srcdir}/loop.h ${srcdir}/mtproto-client.h ${srcdir}/mtproto-common.h ${srcdir}/net.h ${srcdir}/no-preview.h ${srcdir}/queries.h ${srcdir}/structures.h ${srcdir}/telegram.h ${srcdir}/tree.h ${srcdir}/config.h ${srcdir}/binlog.h ${srcdir}/tools.h ${srcdir}/lua-tg.h
INCLUDE=-I. -I${srcdir}
CC=@CC@
OBJECTS=main.o loop.o interface.o net.o mtproto-common.o mtproto-client.o queries.o structures.o binlog.o tools.o
OBJECTS=main.o loop.o interface.o net.o mtproto-common.o mtproto-client.o queries.o structures.o binlog.o tools.o lua-tg.o
.SUFFIXES:

607
ax_lua.m4 Normal file
View File

@ -0,0 +1,607 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_lua.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PROG_LUA[([MINIMUM-VERSION], [TOO-BIG-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
# AX_LUA_HEADERS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
# AX_LUA_LIBS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
# AX_LUA_READLINE[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
#
# DESCRIPTION
#
# Detect a Lua interpreter, optionally specifying a minimum and maximum
# version number. Set up important Lua paths, such as the directories in
# which to install scripts and modules (shared libraries).
#
# Also detect Lua headers and libraries. The Lua version contained in the
# header is checked to match the Lua interpreter version exactly. When
# searching for Lua libraries, the version number is used as a suffix.
# This is done with the goal of supporting multiple Lua installs (5.1 and
# 5.2 side-by-side).
#
# A note on compatibility with previous versions: This file has been
# mostly rewritten for serial 18. Most developers should be able to use
# these macros without needing to modify configure.ac. Care has been taken
# to preserve each macro's behavior, but there are some differences:
#
# 1) AX_WITH_LUA is deprecated; it now expands to the exact same thing as
# AX_PROG_LUA with no arguments.
#
# 2) AX_LUA_HEADERS now checks that the version number defined in lua.h
# matches the interpreter version. AX_LUA_HEADERS_VERSION is therefore
# unnecessary, so it is deprecated and does not expand to anything.
#
# 3) The configure flag --with-lua-suffix no longer exists; the user
# should instead specify the LUA precious variable on the command line.
# See the AX_PROG_LUA description for details.
#
# Please read the macro descriptions below for more information.
#
# This file was inspired by Andrew Dalke's and James Henstridge's
# python.m4 and Tom Payne's, Matthieu Moy's, and Reuben Thomas's ax_lua.m4
# (serial 17). Basically, this file is a mash-up of those two files. I
# like to think it combines the best of the two!
#
# AX_PROG_LUA: Search for the Lua interpreter, and set up important Lua
# paths. Adds precious variable LUA, which may contain the path of the Lua
# interpreter. If LUA is blank, the user's path is searched for an
# suitable interpreter.
#
# If MINIMUM-VERSION is supplied, then only Lua interpreters with a
# version number greater or equal to MINIMUM-VERSION will be accepted. If
# TOO-BIG- VERSION is also supplied, then only Lua interpreters with a
# version number greater or equal to MINIMUM-VERSION and less than
# TOO-BIG-VERSION will be accepted.
#
# Version comparisons require the AX_COMPARE_VERSION macro, which is
# provided by ax_compare_version.m4 from the Autoconf Archive.
#
# The Lua version number, LUA_VERSION, is found from the interpreter, and
# substituted. LUA_PLATFORM is also found, but not currently supported (no
# standard representation).
#
# Finally, the macro finds four paths:
#
# luadir Directory to install Lua scripts.
# pkgluadir $luadir/$PACKAGE
# luaexecdir Directory to install Lua modules.
# pkgluaexecdir $luaexecdir/$PACKAGE
#
# These paths a found based on $prefix, $exec_prefix, Lua's package.path,
# and package.cpath. The first path of package.path beginning with $prefix
# is selected as luadir. The first path of package.cpath beginning with
# $exec_prefix is used as luaexecdir. This should work on all reasonable
# Lua installations. If a path cannot be determined, a default path is
# used. Of course, the user can override these later when invoking make.
#
# luadir Default: $prefix/share/lua/$LUA_VERSION
# luaexecdir Default: $exec_prefix/lib/lua/$LUA_VERSION
#
# These directories can be used by Automake as install destinations. The
# variable name minus 'dir' needs to be used as a prefix to the
# appropriate Automake primary, e.g. lua_SCRIPS or luaexec_LIBRARIES.
#
# If an acceptable Lua interpreter is found, then ACTION-IF-FOUND is
# performed, otherwise ACTION-IF-NOT-FOUND is preformed. If ACTION-IF-NOT-
# FOUND is blank, then it will default to printing an error. To prevent
# the default behavior, give ':' as an action.
#
# AX_LUA_HEADERS: Search for Lua headers. Requires that AX_PROG_LUA be
# expanded before this macro. Adds precious variable LUA_INCLUDE, which
# may contain Lua specific include flags, e.g. -I/usr/include/lua5.1. If
# LUA_INCLUDE is blank, then this macro will attempt to find suitable
# flags.
#
# LUA_INCLUDE can be used by Automake to compile Lua modules or
# executables with embedded interpreters. The *_CPPFLAGS variables should
# be used for this purpose, e.g. myprog_CPPFLAGS = $(LUA_INCLUDE).
#
# This macro searches for the header lua.h (and others). The search is
# performed with a combination of CPPFLAGS, CPATH, etc, and LUA_INCLUDE.
# If the search is unsuccessful, then some common directories are tried.
# If the headers are then found, then LUA_INCLUDE is set accordingly.
#
# The paths automatically searched are:
#
# * /usr/include/luaX.Y
# * /usr/include/lua/X.Y
# * /usr/include/luaXY
# * /usr/local/include/luaX.Y
# * /usr/local/include/lua/X.Y
# * /usr/local/include/luaXY
#
# (Where X.Y is the Lua version number, e.g. 5.1.)
#
# The Lua version number found in the headers is always checked to match
# the Lua interpreter's version number. Lua headers with mismatched
# version numbers are not accepted.
#
# If headers are found, then ACTION-IF-FOUND is performed, otherwise
# ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then
# it will default to printing an error. To prevent the default behavior,
# set the action to ':'.
#
# AX_LUA_LIBS: Search for Lua libraries. Requires that AX_PROG_LUA be
# expanded before this macro. Adds precious variable LUA_LIB, which may
# contain Lua specific linker flags, e.g. -llua5.1. If LUA_LIB is blank,
# then this macro will attempt to find suitable flags.
#
# LUA_LIB can be used by Automake to link Lua modules or executables with
# embedded interpreters. The *_LIBADD and *_LDADD variables should be used
# for this purpose, e.g. mymod_LIBADD = $(LUA_LIB).
#
# This macro searches for the Lua library. More technically, it searches
# for a library containing the function lua_load. The search is performed
# with a combination of LIBS, LIBRARY_PATH, and LUA_LIB.
#
# If the search determines that some linker flags are missing, then those
# flags will be added to LUA_LIB.
#
# If libraries are found, then ACTION-IF-FOUND is performed, otherwise
# ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then
# it will default to printing an error. To prevent the default behavior,
# set the action to ':'.
#
# AX_LUA_READLINE: Search for readline headers and libraries. Requires the
# AX_LIB_READLINE macro, which is provided by ax_lib_readline.m4 from the
# Autoconf Archive.
#
# If a readline compatible library is found, then ACTION-IF-FOUND is
# performed, otherwise ACTION-IF-NOT-FOUND is performed.
#
# LICENSE
#
# Copyright (c) 2013 Tim Perkins <tprk77@gmail.com>
# Copyright (c) 2013 Reuben Thomas <rrt@sc3d.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 3 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, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 20
dnl =========================================================================
dnl AX_PROG_LUA([MINIMUM-VERSION], [TOO-BIG-VERSION],
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl =========================================================================
AC_DEFUN([AX_PROG_LUA],
[
dnl Make LUA a precious variable.
AC_ARG_VAR([LUA], [The Lua interpreter, e.g. /usr/bin/lua5.1])
dnl Find a Lua interpreter.
m4_define_default([_AX_LUA_INTERPRETER_LIST],
[lua lua5.2 lua5.1 lua50])
m4_if([$1], [],
[ dnl No version check is needed. Find any Lua interpreter.
AS_IF([test "x$LUA" = 'x'],
[AC_PATH_PROGS([LUA], [_AX_LUA_INTERPRETER_LIST], [:])])
ax_display_LUA='lua'
dnl At least check if this is a Lua interpreter.
AC_MSG_CHECKING([if $LUA is a Lua interpreter])
_AX_LUA_CHK_IS_INTRP([$LUA],
[AC_MSG_RESULT([yes])],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([not a Lua interpreter])
])
],
[ dnl A version check is needed.
AS_IF([test "x$LUA" != 'x'],
[ dnl Check if this is a Lua interpreter.
AC_MSG_CHECKING([if $LUA is a Lua interpreter])
_AX_LUA_CHK_IS_INTRP([$LUA],
[AC_MSG_RESULT([yes])],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([not a Lua interpreter])
])
dnl Check the version.
m4_if([$2], [],
[_ax_check_text="whether $LUA version >= $1"],
[_ax_check_text="whether $LUA version >= $1, < $2"])
AC_MSG_CHECKING([$_ax_check_text])
_AX_LUA_CHK_VER([$LUA], [$1], [$2],
[AC_MSG_RESULT([yes])],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([version is out of range for specified LUA])])
ax_display_LUA=$LUA
],
[ dnl Try each interpreter until we find one that satisfies VERSION.
m4_if([$2], [],
[_ax_check_text="for a Lua interpreter with version >= $1"],
[_ax_check_text="for a Lua interpreter with version >= $1, < $2"])
AC_CACHE_CHECK([$_ax_check_text],
[ax_cv_pathless_LUA],
[ for ax_cv_pathless_LUA in _AX_LUA_INTERPRETER_LIST none; do
test "x$ax_cv_pathless_LUA" = 'xnone' && break
_AX_LUA_CHK_IS_INTRP([$ax_cv_pathless_LUA], [], [continue])
_AX_LUA_CHK_VER([$ax_cv_pathless_LUA], [$1], [$2], [break])
done
])
dnl Set $LUA to the absolute path of $ax_cv_pathless_LUA.
AS_IF([test "x$ax_cv_pathless_LUA" = 'xnone'],
[LUA=':'],
[AC_PATH_PROG([LUA], [$ax_cv_pathless_LUA])])
ax_display_LUA=$ax_cv_pathless_LUA
])
])
AS_IF([test "x$LUA" = 'x:'],
[ dnl Run any user-specified action, or abort.
m4_default([$4], [AC_MSG_ERROR([cannot find suitable Lua interpreter])])
],
[ dnl Query Lua for its version number.
AC_CACHE_CHECK([for $ax_display_LUA version], [ax_cv_lua_version],
[ ax_cv_lua_version=`$LUA -e "print(_VERSION)" | \
sed "s|^Lua \(.*\)|\1|" | \
grep -o "^@<:@0-9@:>@\+\\.@<:@0-9@:>@\+"`
])
AS_IF([test "x$ax_cv_lua_version" = 'x'],
[AC_MSG_ERROR([invalid Lua version number])])
AC_SUBST([LUA_VERSION], [$ax_cv_lua_version])
AC_SUBST([LUA_SHORT_VERSION], [`echo "$LUA_VERSION" | sed 's|\.||'`])
dnl The following check is not supported:
dnl At times (like when building shared libraries) you may want to know
dnl which OS platform Lua thinks this is.
AC_CACHE_CHECK([for $ax_display_LUA platform], [ax_cv_lua_platform],
[ax_cv_lua_platform=`$LUA -e "print('unknown')"`])
AC_SUBST([LUA_PLATFORM], [$ax_cv_lua_platform])
dnl Use the values of $prefix and $exec_prefix for the corresponding
dnl values of LUA_PREFIX and LUA_EXEC_PREFIX. These are made distinct
dnl variables so they can be overridden if need be. However, the general
dnl consensus is that you shouldn't need this ability.
AC_SUBST([LUA_PREFIX], ['${prefix}'])
AC_SUBST([LUA_EXEC_PREFIX], ['${exec_prefix}'])
dnl Lua provides no way to query the script directory, and instead
dnl provides LUA_PATH. However, we should be able to make a safe educated
dnl guess. If the built-in search path contains a directory which is
dnl prefixed by $prefix, then we can store scripts there. The first
dnl matching path will be used.
AC_CACHE_CHECK([for $ax_display_LUA script directory],
[ax_cv_lua_luadir],
[ AS_IF([test "x$prefix" = 'xNONE'],
[ax_lua_prefix=$ac_default_prefix],
[ax_lua_prefix=$prefix])
dnl Initialize to the default path.
ax_cv_lua_luadir="$LUA_PREFIX/share/lua/$LUA_VERSION"
dnl Try to find a path with the prefix.
_AX_LUA_FND_PRFX_PTH([$LUA], [$ax_lua_prefix], [package.path])
AS_IF([test "x$ax_lua_prefixed_path" != 'x'],
[ dnl Fix the prefix.
_ax_strip_prefix=`echo "$ax_lua_prefix" | sed 's|.|.|g'`
ax_cv_lua_luadir=`echo "$ax_lua_prefixed_path" | \
sed "s,^$_ax_strip_prefix,$LUA_PREFIX,"`
])
])
AC_SUBST([luadir], [$ax_cv_lua_luadir])
AC_SUBST([pkgluadir], [\${luadir}/$PACKAGE])
dnl Lua provides no way to query the module directory, and instead
dnl provides LUA_PATH. However, we should be able to make a safe educated
dnl guess. If the built-in search path contains a directory which is
dnl prefixed by $exec_prefix, then we can store modules there. The first
dnl matching path will be used.
AC_CACHE_CHECK([for $ax_display_LUA module directory],
[ax_cv_lua_luaexecdir],
[ AS_IF([test "x$exec_prefix" = 'xNONE'],
[ax_lua_exec_prefix=$ax_lua_prefix],
[ax_lua_exec_prefix=$exec_prefix])
dnl Initialize to the default path.
ax_cv_lua_luaexecdir="$LUA_EXEC_PREFIX/lib/lua/$LUA_VERSION"
dnl Try to find a path with the prefix.
_AX_LUA_FND_PRFX_PTH([$LUA],
[$ax_lua_exec_prefix], [package.cpathd])
AS_IF([test "x$ax_lua_prefixed_path" != 'x'],
[ dnl Fix the prefix.
_ax_strip_prefix=`echo "$ax_lua_exec_prefix" | sed 's|.|.|g'`
ax_cv_lua_luaexecdir=`echo "$ax_lua_prefixed_path" | \
sed "s,^$_ax_strip_prefix,$LUA_EXEC_PREFIX,"`
])
])
AC_SUBST([luaexecdir], [$ax_cv_lua_luaexecdir])
AC_SUBST([pkgluaexecdir], [\${luaexecdir}/$PACKAGE])
dnl Run any user specified action.
$3
])
])
dnl AX_WITH_LUA is now the same thing as AX_PROG_LUA.
AC_DEFUN([AX_WITH_LUA],
[
AC_MSG_WARN([[$0 is deprecated, please use AX_PROG_LUA]])
AX_PROG_LUA
])
dnl =========================================================================
dnl _AX_LUA_CHK_IS_INTRP(PROG, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
dnl =========================================================================
AC_DEFUN([_AX_LUA_CHK_IS_INTRP],
[
dnl Just print _VERSION because all Lua interpreters have this global.
AS_IF([$1 -e "print('Hello ' .. _VERSION .. '!')" &>/dev/null],
[$2], [$3])
])
dnl =========================================================================
dnl _AX_LUA_CHK_VER(PROG, MINIMUM-VERSION, [TOO-BIG-VERSION],
dnl [ACTION-IF-TRUE], [ACTION-IF-FALSE])
dnl =========================================================================
AC_DEFUN([_AX_LUA_CHK_VER],
[
_ax_test_ver=`$1 -e "print(_VERSION)" 2>/dev/null | \
sed "s|^Lua \(.*\)|\1|" | grep -o "^@<:@0-9@:>@\+\\.@<:@0-9@:>@\+"`
AS_IF([test "x$_ax_test_ver" = 'x'],
[_ax_test_ver='0'])
AX_COMPARE_VERSION([$_ax_test_ver], [ge], [$2])
m4_if([$3], [], [],
[ AS_IF([$ax_compare_version],
[AX_COMPARE_VERSION([$_ax_test_ver], [lt], [$3])])
])
AS_IF([$ax_compare_version], [$4], [$5])
])
dnl =========================================================================
dnl _AX_LUA_FND_PRFX_PTH(PROG, PREFIX, LUA-PATH-VARIABLE)
dnl =========================================================================
AC_DEFUN([_AX_LUA_FND_PRFX_PTH],
[
dnl Invokes the Lua interpreter PROG to print the path variable
dnl LUA-PATH-VARIABLE, usually package.path or package.cpath. Paths are
dnl then matched against PREFIX. The first path to begin with PREFIX is set
dnl to ax_lua_prefixed_path.
ax_lua_prefixed_path=''
_ax_package_paths=`$1 -e 'print($3)' 2>/dev/null | sed 's|;|\n|g'`
dnl Try the paths in order, looking for the prefix.
for _ax_package_path in $_ax_package_paths; do
dnl Copy the path, up to the use of a Lua wildcard.
_ax_path_parts=`echo "$_ax_package_path" | sed 's|/|\n|g'`
_ax_reassembled=''
for _ax_path_part in $_ax_path_parts; do
echo "$_ax_path_part" | grep '\?' >/dev/null && break
_ax_reassembled="$_ax_reassembled/$_ax_path_part"
done
dnl Check the path against the prefix.
_ax_package_path=$_ax_reassembled
if echo "$_ax_package_path" | grep "^$2" >/dev/null; then
dnl Found it.
ax_lua_prefixed_path=$_ax_package_path
break
fi
done
])
dnl =========================================================================
dnl AX_LUA_HEADERS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl =========================================================================
AC_DEFUN([AX_LUA_HEADERS],
[
dnl Check for LUA_VERSION.
AC_MSG_CHECKING([if LUA_VERSION is defined])
AS_IF([test "x$LUA_VERSION" != 'x'],
[AC_MSG_RESULT([yes])],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([cannot check Lua headers without knowing LUA_VERSION])
])
dnl Make LUA_INCLUDE a precious variable.
AC_ARG_VAR([LUA_INCLUDE], [The Lua includes, e.g. -I/usr/include/lua5.1])
dnl Some default directories to search.
LUA_SHORT_VERSION=`echo "$LUA_VERSION" | sed 's|\.||'`
m4_define_default([_AX_LUA_INCLUDE_LIST],
[ /usr/include/lua$LUA_VERSION \
/usr/include/lua/$LUA_VERSION \
/usr/include/lua$LUA_SHORT_VERSION \
/usr/local/include/lua$LUA_VERSION \
/usr/local/include/lua/$LUA_VERSION \
/usr/local/include/lua$LUA_SHORT_VERSION \
])
dnl Try to find the headers.
_ax_lua_saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h])
CPPFLAGS=$_ax_lua_saved_cppflags
dnl Try some other directories if LUA_INCLUDE was not set.
AS_IF([test "x$LUA_INCLUDE" = 'x' &&
test "x$ac_cv_header_lua_h" != 'xyes'],
[ dnl Try some common include paths.
for _ax_include_path in _AX_LUA_INCLUDE_LIST; do
test ! -d "$_ax_include_path" && continue
AC_MSG_CHECKING([for Lua headers in])
AC_MSG_RESULT([$_ax_include_path])
AS_UNSET([ac_cv_header_lua_h])
AS_UNSET([ac_cv_header_lualib_h])
AS_UNSET([ac_cv_header_lauxlib_h])
AS_UNSET([ac_cv_header_luaconf_h])
_ax_lua_saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS -I$_ax_include_path"
AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h])
CPPFLAGS=$_ax_lua_saved_cppflags
AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'],
[ LUA_INCLUDE="-I$_ax_include_path"
break
])
done
])
AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'],
[ dnl Make a program to print LUA_VERSION defined in the header.
dnl TODO This probably shouldn't be a runtime test.
AC_CACHE_CHECK([for Lua header version],
[ax_cv_lua_header_version],
[ _ax_lua_saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
AC_RUN_IFELSE(
[ AC_LANG_SOURCE([[
#include <lua.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
if(argc > 1) printf("%s", LUA_VERSION);
exit(EXIT_SUCCESS);
}
]])
],
[ ax_cv_lua_header_version=`./conftest$EXEEXT p | \
sed "s|^Lua \(.*\)|\1|" | \
grep -o "^@<:@0-9@:>@\+\\.@<:@0-9@:>@\+"`
],
[ax_cv_lua_header_version='unknown'])
CPPFLAGS=$_ax_lua_saved_cppflags
])
dnl Compare this to the previously found LUA_VERSION.
AC_MSG_CHECKING([if Lua header version matches $LUA_VERSION])
AS_IF([test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"],
[ AC_MSG_RESULT([yes])
ax_header_version_match='yes'
],
[ AC_MSG_RESULT([no])
ax_header_version_match='no'
])
])
dnl Was LUA_INCLUDE specified?
AS_IF([test "x$ax_header_version_match" != 'xyes' &&
test "x$LUA_INCLUDE" != 'x'],
[AC_MSG_ERROR([cannot find headers for specified LUA_INCLUDE])])
dnl Test the final result and run user code.
AS_IF([test "x$ax_header_version_match" = 'xyes'], [$1],
[m4_default([$2], [AC_MSG_ERROR([cannot find Lua includes])])])
])
dnl AX_LUA_HEADERS_VERSION no longer exists, use AX_LUA_HEADERS.
AC_DEFUN([AX_LUA_HEADERS_VERSION],
[
AC_MSG_WARN([[$0 is deprecated, please use AX_LUA_HEADERS]])
])
dnl =========================================================================
dnl AX_LUA_LIBS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl =========================================================================
AC_DEFUN([AX_LUA_LIBS],
[
dnl TODO Should this macro also check various -L flags?
dnl Check for LUA_VERSION.
AC_MSG_CHECKING([if LUA_VERSION is defined])
AS_IF([test "x$LUA_VERSION" != 'x'],
[AC_MSG_RESULT([yes])],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([cannot check Lua libs without knowing LUA_VERSION])
])
dnl Make LUA_LIB a precious variable.
AC_ARG_VAR([LUA_LIB], [The Lua library, e.g. -llua5.1])
AS_IF([test "x$LUA_LIB" != 'x'],
[ dnl Check that LUA_LIBS works.
_ax_lua_saved_libs=$LIBS
LIBS="$LIBS $LUA_LIB"
AC_SEARCH_LIBS([lua_load], [],
[_ax_found_lua_libs='yes'],
[_ax_found_lua_libs='no'])
LIBS=$_ax_lua_saved_libs
dnl Check the result.
AS_IF([test "x$_ax_found_lua_libs" != 'xyes'],
[AC_MSG_ERROR([cannot find libs for specified LUA_LIB])])
],
[ dnl First search for extra libs.
_ax_lua_extra_libs=''
_ax_lua_saved_libs=$LIBS
LIBS="$LIBS $LUA_LIB"
AC_SEARCH_LIBS([exp], [m])
AC_SEARCH_LIBS([dlopen], [dl])
LIBS=$_ax_lua_saved_libs
AS_IF([test "x$ac_cv_search_exp" != 'xno' &&
test "x$ac_cv_search_exp" != 'xnone required'],
[_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_exp"])
AS_IF([test "x$ac_cv_search_dlopen" != 'xno' &&
test "x$ac_cv_search_dlopen" != 'xnone required'],
[_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_dlopen"])
dnl Try to find the Lua libs.
_ax_lua_saved_libs=$LIBS
LIBS="$LIBS $LUA_LIB"
AC_SEARCH_LIBS([lua_load], [lua$LUA_VERSION lua$LUA_SHORT_VERSION lua],
[_ax_found_lua_libs='yes'],
[_ax_found_lua_libs='no'],
[$_ax_lua_extra_libs])
LIBS=$_ax_lua_saved_libs
AS_IF([test "x$ac_cv_search_lua_load" != 'xno' &&
test "x$ac_cv_search_lua_load" != 'xnone required'],
[LUA_LIB="$ac_cv_search_lua_load $_ax_lua_extra_libs"])
])
dnl Test the result and run user code.
AS_IF([test "x$_ax_found_lua_libs" = 'xyes'], [$1],
[m4_default([$2], [AC_MSG_ERROR([cannot find Lua libs])])])
])
dnl =========================================================================
dnl AX_LUA_READLINE([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl =========================================================================
AC_DEFUN([AX_LUA_READLINE],
[
AX_LIB_READLINE
AS_IF([test "x$ac_cv_header_readline_readline_h" != 'x' &&
test "x$ac_cv_header_readline_history_h" != 'x'],
[ LUA_LIBS_CFLAGS="-DLUA_USE_READLINE $LUA_LIBS_CFLAGS"
$1
],
[$2])
])

View File

@ -16,6 +16,10 @@
Copyright Vitaly Valtman 2013
*/
#include "config.h"
#ifdef USE_LUA
# include "lua-tg.h"
#endif
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
@ -126,6 +130,9 @@ void replay_log_event (void) {
rptr ++;
{
our_id = *(rptr ++);
#ifdef USE_LUA
lua_our_id (our_id);
#endif
}
break;
case LOG_DC_SIGNED:
@ -280,6 +287,9 @@ void replay_log_event (void) {
struct secret_chat *U = (void *)user_chat_get (id);
assert (U);
U->state = sc_ok;
#ifdef USE_LUA
lua_secret_chat_created (U);
#endif
}
break;
case CODE_binlog_new_user:
@ -307,6 +317,10 @@ void replay_log_event (void) {
if (fetch_int ()) {
U->flags |= FLAG_USER_CONTACT;
}
#ifdef USE_LUA
lua_user_update (U);
#endif
}
rptr = in_ptr;
break;
@ -337,6 +351,10 @@ void replay_log_event (void) {
assert (U);
if (U->user.phone) { tfree_str (U->user.phone); }
U->user.phone = fetch_str_dup ();
#ifdef USE_LUA
lua_user_update (&U->user);
#endif
}
rptr = in_ptr;
break;
@ -383,6 +401,10 @@ void replay_log_event (void) {
if (U->user.real_last_name) { tfree_str (U->user.real_last_name); }
U->user.real_first_name = fetch_str_dup ();
U->user.real_last_name = fetch_str_dup ();
#ifdef USE_LUA
lua_user_update (&U->user);
#endif
}
rptr = in_ptr;
break;
@ -519,7 +541,6 @@ void replay_log_event (void) {
memcpy (encr_prime, rptr, 256);
rptr += 64;
encr_param_version = *(rptr ++);
}
break;
case CODE_binlog_encr_chat_init:
@ -579,6 +600,10 @@ void replay_log_event (void) {
C->version = fetch_int ();
fetch_data (&C->photo_big, sizeof (struct file_location));
fetch_data (&C->photo_small, sizeof (struct file_location));
#ifdef USE_LUA
lua_chat_update (C);
#endif
};
rptr = in_ptr;
break;
@ -600,6 +625,9 @@ void replay_log_event (void) {
if (C->title) { tfree_str (C->title); }
C->title = fetch_str_dup ();
C->print_title = create_print_name (C->id, C->title, 0, 0, 0);
#ifdef USE_LUA
lua_chat_update (C);
#endif
};
rptr = in_ptr;
break;
@ -619,6 +647,9 @@ void replay_log_event (void) {
peer_t *C = user_chat_get (MK_CHAT (*(rptr ++)));
assert (C && (C->flags & FLAG_CREATED));
C->chat.date = *(rptr ++);
#ifdef USE_LUA
lua_chat_update (&C->chat);
#endif
};
break;
case CODE_binlog_set_chat_version:
@ -628,6 +659,9 @@ void replay_log_event (void) {
assert (C && (C->flags & FLAG_CREATED));
C->chat.version = *(rptr ++);
C->chat.users_num = *(rptr ++);
#ifdef USE_LUA
lua_chat_update (&C->chat);
#endif
};
break;
case CODE_binlog_set_chat_admin:
@ -636,6 +670,9 @@ void replay_log_event (void) {
peer_t *C = user_chat_get (MK_CHAT (*(rptr ++)));
assert (C && (C->flags & FLAG_CREATED));
C->chat.admin_id = *(rptr ++);
#ifdef USE_LUA
lua_chat_update (&C->chat);
#endif
};
break;
case CODE_binlog_set_chat_participants:
@ -649,6 +686,9 @@ void replay_log_event (void) {
C->chat.user_list = talloc (12 * C->chat.user_list_size);
memcpy (C->chat.user_list, rptr, 12 * C->chat.user_list_size);
rptr += 3 * C->chat.user_list_size;
#ifdef USE_LUA
lua_chat_update (&C->chat);
#endif
};
break;
case CODE_binlog_chat_full_photo:
@ -688,6 +728,9 @@ void replay_log_event (void) {
C->user_list[C->user_list_size - 1].inviter_id = inviter;
C->user_list[C->user_list_size - 1].date = date;
C->user_list_version = version;
#ifdef USE_LUA
lua_chat_update (C);
#endif
}
break;
case CODE_binlog_del_chat_participant:
@ -715,6 +758,9 @@ void replay_log_event (void) {
C->user_list_size --;
C->user_list = trealloc (C->user_list, 12 * C->user_list_size + 12, 12 * C->user_list_size);
C->user_list_version = version;
#ifdef USE_LUA
lua_chat_update (C);
#endif
}
break;
case CODE_binlog_create_message_text:
@ -764,6 +810,10 @@ void replay_log_event (void) {
message_insert_unsent (M);
M->flags |= FLAG_PENDING;
}
#ifdef USE_LUA
lua_new_msg (M);
#endif
}
rptr = in_ptr;
break;
@ -799,6 +849,9 @@ void replay_log_event (void) {
M->out = get_peer_id (M->from_id) == our_id;
message_insert (M);
#ifdef USE_LUA
lua_new_msg (M);
#endif
}
rptr = in_ptr;
break;
@ -832,6 +885,9 @@ void replay_log_event (void) {
M->out = get_peer_id (M->from_id) == our_id;
message_insert (M);
#ifdef USE_LUA
lua_new_msg (M);
#endif
}
rptr = in_ptr;
break;
@ -867,6 +923,9 @@ void replay_log_event (void) {
M->out = get_peer_id (M->from_id) == our_id;
message_insert (M);
#ifdef USE_LUA
lua_new_msg (M);
#endif
}
rptr = in_ptr;
break;
@ -902,6 +961,9 @@ void replay_log_event (void) {
M->out = get_peer_id (M->from_id) == our_id;
message_insert (M);
#ifdef USE_LUA
lua_new_msg (M);
#endif
}
rptr = in_ptr;
break;
@ -930,6 +992,9 @@ void replay_log_event (void) {
M->service = 1;
message_insert (M);
#ifdef USE_LUA
lua_new_msg (M);
#endif
}
rptr = in_ptr;
break;
@ -959,6 +1024,9 @@ void replay_log_event (void) {
M->service = 1;
message_insert (M);
#ifdef USE_LUA
lua_new_msg (M);
#endif
}
rptr = in_ptr;
break;
@ -988,6 +1056,9 @@ void replay_log_event (void) {
M->service = 1;
message_insert (M);
#ifdef USE_LUA
lua_new_msg (M);
#endif
}
rptr = in_ptr;
break;
@ -1043,6 +1114,7 @@ void replay_log_event (void) {
}
message_remove_tree (M);
message_del_peer (M);
message_del_use (M);
free_message (M);
tfree (M, sizeof (*M));
}

View File

@ -10,6 +10,9 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <lauxlib.h> header file. */
#define HAVE_LAUXLIB_H 1
/* Define to 1 if you have the `crypto' library (-lcrypto). */
#define HAVE_LIBCRYPTO 1
@ -22,6 +25,15 @@
/* Define to 1 if you have the `m' library (-lm). */
#define HAVE_LIBM 1
/* Define to 1 if you have the <luaconf.h> header file. */
#define HAVE_LUACONF_H 1
/* Define to 1 if you have the <lualib.h> header file. */
#define HAVE_LUALIB_H 1
/* Define to 1 if you have the <lua.h> header file. */
#define HAVE_LUA_H 1
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#define HAVE_MALLOC 1
@ -99,6 +111,9 @@
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* use lua */
#define USE_LUA 1
/* Define to rpl_malloc if the replacement function should be used. */
/* #undef malloc */

View File

@ -9,6 +9,9 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <lauxlib.h> header file. */
#undef HAVE_LAUXLIB_H
/* Define to 1 if you have the `crypto' library (-lcrypto). */
#undef HAVE_LIBCRYPTO
@ -21,6 +24,15 @@
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM
/* Define to 1 if you have the <luaconf.h> header file. */
#undef HAVE_LUACONF_H
/* Define to 1 if you have the <lualib.h> header file. */
#undef HAVE_LUALIB_H
/* Define to 1 if you have the <lua.h> header file. */
#undef HAVE_LUA_H
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC
@ -98,6 +110,9 @@
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* use lua */
#undef USE_LUA
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc

1578
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,8 @@ AC_INIT([telegram], [0.1])
AC_CONFIG_SRCDIR([config.h.in])
AC_CONFIG_HEADERS([config.h])
m4_include([ax_lua.m4])
# Checks for programs.
AC_PROG_CC
@ -46,7 +48,7 @@ AC_CHECK_LIB([rt], [clock_gettime],
]
)
AC_MSG_CHECKING([Checking for libconfig])
AC_MSG_CHECKING([for libconfig])
AC_ARG_ENABLE(libconfig,[--enable-libconfig/--disable-libconfig],
[
if test "x$enableval" = "xno" ; then
@ -62,6 +64,40 @@ AC_ARG_ENABLE(libconfig,[--enable-libconfig/--disable-libconfig],
[EXTRA_LIBS="${EXTRA_LIBS} -lconfig" ; ]
])
AC_MSG_CHECKING([for liblua])
AC_ARG_ENABLE(liblua,[--enable-liblua/--disable-liblua],
[
if test "x$enableval" = "xno" ; then
AC_MSG_RESULT([disabled])
else
AC_MSG_RESULT([enabled])
AX_PROG_LUA([],[],
[
AX_LUA_HEADERS([],[AC_MSG_ERROR([No lua headers found. Try --disable-liblua])])
AX_LUA_LIBS([],[AC_MSG_ERROR([No lua libs found. Try --disable-liblua])])
[EXTRA_LIBS="${EXTRA_LIBS} ${LUA_LIB}" ; ]
[CFLAGS="${CFLAGS} ${LUA_INCLUDE}" ; ]
AC_DEFINE(USE_LUA,1,[use lua])
],
[
AC_MSG_ERROR([No lua found. Try --disable-liblua])
])
fi
],[
AC_MSG_RESULT([enabled])
AX_PROG_LUA([],[],
[
AX_LUA_HEADERS([],[AC_MSG_ERROR([No lua headers found. Try --disable-liblua])])
AX_LUA_LIBS([],[AC_MSG_ERROR([No lua libs found. Try --disable-liblua])])
[EXTRA_LIBS="${EXTRA_LIBS} ${LUA_LIB}" ; ]
[CFLAGS="${CFLAGS} ${LUA_INCLUDE}" ; ]
AC_DEFINE(USE_LUA,1,[use lua])
],
[
AC_MSG_ERROR([No lua found. Try --disable-liblua])
])
])
# Checks for header files.
AC_CHECK_HEADERS([fcntl.h malloc.h stdlib.h string.h sys/socket.h unistd.h])

11
loop.c
View File

@ -48,6 +48,7 @@
#include "telegram.h"
#include "loop.h"
#include "binlog.h"
#include "lua-tg.h"
extern char *default_username;
extern char *auth_token;
@ -95,6 +96,9 @@ void net_loop (int flags, int (*is_end)(void)) {
}
}
connections_poll_result (fds + cc, x - cc);
#ifdef USE_LUA
lua_do_all ();
#endif
if (safe_quit && !queries_num) {
printf ("All done. Exit\n");
rl_callback_handler_remove ();
@ -448,6 +452,9 @@ int loop (void) {
replay_log ();
logprintf ("replay log end in %lf seconds\n", get_double_time () - t);
write_binlog ();
#ifdef USE_LUA
lua_binlog_end ();
#endif
} else {
read_auth_file ();
}
@ -580,8 +587,12 @@ int loop (void) {
do_get_difference ();
net_loop (0, dgot);
#ifdef USE_LUA
lua_diff_end ();
#endif
send_all_unsent ();
do_get_dialog_list ();
return main_loop ();

445
lua-tg.c Normal file
View File

@ -0,0 +1,445 @@
#include "config.h"
#ifdef USE_LUA
#include "lua-tg.h"
#include "include.h"
#include <string.h>
#include <stdlib.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
lua_State *luaState;
#include "structures.h"
#include "interface.h"
#include "constants.h"
#include "tools.h"
#include "queries.h"
extern int verbosity;
static int have_file;
#define my_lua_checkstack(L,x) assert (lua_checkstack (L, x))
void push_user (peer_t *P UU);
void push_peer (peer_id_t id, peer_t *P);
void lua_add_string_field (const char *name, const char *value) {
assert (name && strlen (name));
if (!value || !strlen (value)) { return; }
my_lua_checkstack (luaState, 3);
lua_pushstring (luaState, name);
lua_pushstring (luaState, value);
lua_settable (luaState, -3);
}
void lua_add_num_field (const char *name, double value) {
assert (name && strlen (name));
my_lua_checkstack (luaState, 3);
lua_pushstring (luaState, name);
lua_pushnumber (luaState, value);
lua_settable (luaState, -3);
}
void push_peer_type (int x) {
switch (x) {
case PEER_USER:
lua_pushstring (luaState, "user");
break;
case PEER_CHAT:
lua_pushstring (luaState, "chat");
break;
case PEER_ENCR_CHAT:
lua_pushstring (luaState, "encr_chat");
break;
default:
assert (0);
}
}
void push_user (peer_t *P UU) {
my_lua_checkstack (luaState, 4);
lua_add_string_field ("first_name", P->user.first_name);
lua_add_string_field ("last_name", P->user.last_name);
lua_add_string_field ("real_first_name", P->user.real_first_name);
lua_add_string_field ("real_last_name", P->user.real_last_name);
lua_add_string_field ("phone", P->user.phone);
}
void push_chat (peer_t *P) {
my_lua_checkstack (luaState, 4);
assert (P->chat.title);
lua_add_string_field ("title", P->chat.title);
lua_add_num_field ("members_num", P->chat.users_num);
}
void push_encr_chat (peer_t *P) {
my_lua_checkstack (luaState, 4);
lua_pushstring (luaState, "user");
push_peer (MK_USER (P->encr_chat.user_id), user_chat_get (MK_USER (P->encr_chat.user_id)));
lua_settable (luaState, -3);
}
void push_peer (peer_id_t id, peer_t *P) {
lua_newtable (luaState);
lua_add_num_field ("id", get_peer_id (id));
lua_pushstring (luaState, "type");
push_peer_type (get_peer_type (id));
lua_settable (luaState, -3);
if (!P || !(P->flags & FLAG_CREATED)) {
lua_pushstring (luaState, "print_name");
static char s[100];
switch (get_peer_type (id)) {
case PEER_USER:
sprintf (s, "user#%d", get_peer_id (id));
break;
case PEER_CHAT:
sprintf (s, "chat#%d", get_peer_id (id));
break;
case PEER_ENCR_CHAT:
sprintf (s, "encr_chat#%d", get_peer_id (id));
break;
default:
assert (0);
}
lua_pushstring (luaState, s);
lua_settable (luaState, -3); // flags
return;
}
lua_add_string_field ("print_name", P->print_name);
lua_add_num_field ("flags", P->flags);
switch (get_peer_type (id)) {
case PEER_USER:
push_user (P);
break;
case PEER_CHAT:
push_chat (P);
break;
case PEER_ENCR_CHAT:
push_encr_chat (P);
break;
default:
assert (0);
}
}
void push_media (struct message_media *M) {
my_lua_checkstack (luaState, 4);
switch (M->type) {
case CODE_message_media_photo:
case CODE_decrypted_message_media_photo:
lua_pushstring (luaState, "photo");
break;
case CODE_message_media_video:
case CODE_decrypted_message_media_video:
lua_pushstring (luaState, "video");
break;
case CODE_message_media_audio:
case CODE_decrypted_message_media_audio:
lua_pushstring (luaState, "audio");
break;
case CODE_message_media_document:
case CODE_decrypted_message_media_document:
lua_pushstring (luaState, "document");
break;
case CODE_message_media_unsupported:
lua_pushstring (luaState, "unsupported");
break;
case CODE_message_media_geo:
lua_newtable (luaState);
lua_add_num_field ("longitude", M->geo.longitude);
lua_add_num_field ("latitude", M->geo.latitude);
break;
case CODE_message_media_contact:
case CODE_decrypted_message_media_contact:
lua_newtable (luaState);
lua_add_string_field ("phone", M->phone);
lua_add_string_field ("first_name", M->first_name);
lua_add_string_field ("last_name", M->last_name);
lua_add_num_field ("user_id", M->user_id);
break;
default:
lua_pushstring (luaState, "???");
}
}
void push_message (struct message *M) {
assert (M);
my_lua_checkstack (luaState, 10);
lua_newtable (luaState);
static char s[30];
tsnprintf (s, 30, "%lld", M->id);
lua_add_string_field ("id", s);
lua_add_num_field ("flags", M->flags);
if (get_peer_type (M->fwd_from_id)) {
lua_pushstring (luaState, "fwd_from");
push_peer (M->fwd_from_id, user_chat_get (M->fwd_from_id));
lua_settable (luaState, -3); // fwd_from
lua_add_num_field ("fwd_date", M->fwd_date);
}
lua_pushstring (luaState, "from");
push_peer (M->from_id, user_chat_get (M->from_id));
lua_settable (luaState, -3);
lua_pushstring (luaState, "to");
push_peer (M->to_id, user_chat_get (M->to_id));
lua_settable (luaState, -3);
lua_pushstring (luaState, "out");
lua_pushboolean (luaState, M->out);
lua_settable (luaState, -3);
lua_pushstring (luaState, "unread");
lua_pushboolean (luaState, M->unread);
lua_settable (luaState, -3);
lua_pushstring (luaState, "date");
lua_pushnumber (luaState, M->date);
lua_settable (luaState, -3);
lua_pushstring (luaState, "service");
lua_pushboolean (luaState, M->service);
lua_settable (luaState, -3);
if (!M->service) {
if (M->message_len && M->message) {
lua_pushstring (luaState, "text");
lua_pushlstring (luaState, M->message, M->message_len);
lua_settable (luaState, -3);
}
if (M->media.type && M->media.type != CODE_message_media_empty && M->media.type != CODE_decrypted_message_media_empty) {
lua_pushstring (luaState, "media");
push_media (&M->media);
lua_settable (luaState, -3);
}
}
}
void lua_binlog_end (void) {
if (!have_file) { return; }
lua_settop (luaState, 0);
//lua_checkstack (luaState, 20);
my_lua_checkstack (luaState, 20);
lua_getglobal (luaState, "on_binlog_replay_end");
assert (lua_gettop (luaState) == 1);
int r = lua_pcall (luaState, 0, 0, 0);
if (r) {
logprintf ("lua: %s\n", lua_tostring (luaState, -1));
}
}
void lua_diff_end (void) {
if (!have_file) { return; }
lua_settop (luaState, 0);
//lua_checkstack (luaState, 20);
my_lua_checkstack (luaState, 20);
lua_getglobal (luaState, "on_get_difference_end");
assert (lua_gettop (luaState) == 1);
int r = lua_pcall (luaState, 0, 0, 0);
if (r) {
logprintf ("lua: %s\n", lua_tostring (luaState, -1));
}
}
void lua_our_id (int id) {
if (!have_file) { return; }
lua_settop (luaState, 0);
//lua_checkstack (luaState, 20);
my_lua_checkstack (luaState, 20);
lua_getglobal (luaState, "on_our_id");
lua_pushnumber (luaState, id);
assert (lua_gettop (luaState) == 2);
int r = lua_pcall (luaState, 1, 0, 0);
if (r) {
logprintf ("lua: %s\n", lua_tostring (luaState, -1));
}
}
void lua_new_msg (struct message *M UU) {
if (!have_file) { return; }
lua_settop (luaState, 0);
//lua_checkstack (luaState, 20);
my_lua_checkstack (luaState, 20);
lua_getglobal (luaState, "on_msg_receive");
push_message (M);
assert (lua_gettop (luaState) == 2);
int r = lua_pcall (luaState, 1, 0, 0);
if (r) {
logprintf ("lua: %s\n", lua_tostring (luaState, -1));
}
}
void lua_secret_chat_created (struct secret_chat *C) {
if (!have_file) { return; }
lua_settop (luaState, 0);
//lua_checkstack (luaState, 20);
my_lua_checkstack (luaState, 20);
lua_getglobal (luaState, "on_secret_chat_created");
push_peer (C->id, (void *)C);
assert (lua_gettop (luaState) == 2);
int r = lua_pcall (luaState, 1, 0, 0);
if (r) {
logprintf ("lua: %s\n", lua_tostring (luaState, -1));
}
}
void lua_user_update (struct user *U) {
if (!have_file) { return; }
lua_settop (luaState, 0);
//lua_checkstack (luaState, 20);
my_lua_checkstack (luaState, 20);
lua_getglobal (luaState, "on_user_update");
push_peer (U->id, (void *)U);
assert (lua_gettop (luaState) == 2);
int r = lua_pcall (luaState, 1, 0, 0);
if (r) {
logprintf ("lua: %s\n", lua_tostring (luaState, -1));
}
}
void lua_chat_update (struct chat *C) {
if (!have_file) { return; }
lua_settop (luaState, 0);
//lua_checkstack (luaState, 20);
my_lua_checkstack (luaState, 20);
lua_getglobal (luaState, "on_chat_update");
push_peer (C->id, (void *)C);
assert (lua_gettop (luaState) == 2);
int r = lua_pcall (luaState, 1, 0, 0);
if (r) {
logprintf ("lua: %s\n", lua_tostring (luaState, -1));
}
}
extern peer_t *Peers[];
extern int peer_num;
#define MAX_LUA_COMMANDS 1000
void *lua_ptr[MAX_LUA_COMMANDS];
static int pos;
static peer_t *get_peer (const char *s) {
int index = 0;
while (index < peer_num && Peers[index]->print_name && strcmp (Peers[index]->print_name, s)) {
index ++;
}
return index == peer_num ? 0 : Peers[index];
}
void lua_do_all (void) {
int p = 0;
while (p < pos) {
int l = (long)lua_ptr[p ++];
assert (p + l + 1 <= pos);
int f = (long)lua_ptr[p ++];
switch (f) {
case 0:
do_send_message (((peer_t *)lua_ptr[p])->id, lua_ptr[p + 1], strlen (lua_ptr[p + 1]));
tfree_str (lua_ptr[p + 1]);
p += 2;
break;
case 1:
do_forward_message (((peer_t *)lua_ptr[p])->id, (long)lua_ptr[p + 1]);
p += 2;
break;
default:
assert (0);
}
}
pos = 0;
}
static int send_msg_from_lua (lua_State *L) {
if (MAX_LUA_COMMANDS - pos < 4) {
lua_pushboolean (L, 0);
return 1;
}
int n = lua_gettop (L);
if (n != 2) {
lua_pushboolean (L, 0);
return 1;
}
const char *s = lua_tostring (L, -2);
const char *msg = lua_tostring (L, -1);
peer_t *P = get_peer (s);
if (!P) {
lua_pushboolean (L, 0);
return 1;
}
lua_ptr[pos ++] = (void *)2l;
lua_ptr[pos ++] = (void *)0l;
lua_ptr[pos ++] = P;
lua_ptr[pos ++] = tstrdup (msg);
logprintf ("msg = %s\n", msg);
lua_pushboolean (L, 1);
return 1;
}
static int fwd_msg_from_lua (lua_State *L) {
if (MAX_LUA_COMMANDS - pos < 4) {
lua_pushboolean (L, 0);
return 1;
}
int n = lua_gettop (L);
if (n != 2) {
lua_pushboolean (L, 0);
return 1;
}
const char *s = lua_tostring (L, -2);
long long num = atoll (lua_tostring (L, -1));
peer_t *P = get_peer (s);
if (!P) {
lua_pushboolean (L, 0);
return 1;
}
lua_ptr[pos ++] = (void *)2l;
lua_ptr[pos ++] = (void *)1l;
lua_ptr[pos ++] = P;
lua_ptr[pos ++] = (void *)(long)num;
lua_pushboolean (L, 1);
return 1;
}
void lua_init (const char *file) {
if (!file) { return; }
have_file = 1;
luaState = luaL_newstate ();
luaL_openlibs (luaState);
lua_register (luaState, "send_msg", send_msg_from_lua);
lua_register (luaState, "fwd_msg", fwd_msg_from_lua);
int ret = luaL_dofile (luaState, file);
if (ret) {
logprintf ("lua: %s\n", lua_tostring (luaState, -1));
exit (1);
}
}
#endif

16
lua-tg.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef __LUA_TG_H__
#define __LUA_TG_H__
#include <string.h>
#include "structures.h"
void lua_init (const char *file);
void lua_new_msg (struct message *M);
void lua_our_id (int id);
void lua_secret_chat_created (struct secret_chat *U);
void lua_user_update (struct user *U);
void lua_chat_update (struct chat *C);
void lua_binlog_end (void);
void lua_diff_end (void);
void lua_do_all (void);
#endif

19
main.c
View File

@ -47,6 +47,10 @@
#include "interface.h"
#include "tools.h"
#ifdef USE_LUA
# include "lua-tg.h"
#endif
#define PROGNAME "telegram-client"
#define VERSION "0.01"
@ -349,9 +353,12 @@ FILE *log_net_f;
int register_mode;
int disable_auto_accept;
char *lua_file;
void args_parse (int argc, char **argv) {
int opt = 0;
while ((opt = getopt (argc, argv, "u:hk:vn:Nc:p:l:RfBL:E")) != -1) {
while ((opt = getopt (argc, argv, "u:hk:vn:Nc:p:l:RfBL:Es:")) != -1) {
switch (opt) {
case 'u':
set_default_username (optarg);
@ -398,6 +405,9 @@ void args_parse (int argc, char **argv) {
case 'w':
allow_weak_random = 1;
break;
case 's':
lua_file = tstrdup (optarg);
break;
case 'h':
default:
usage ();
@ -410,13 +420,13 @@ void print_backtrace (void) {
void *buffer[255];
const int calls = backtrace (buffer, sizeof (buffer) / sizeof (void *));
backtrace_symbols_fd (buffer, calls, 1);
exit(EXIT_FAILURE);
}
void sig_handler (int signum) {
set_terminal_attributes ();
printf ("Signal %d received\n", signum);
print_backtrace ();
exit(EXIT_FAILURE);
}
@ -439,6 +449,11 @@ int main (int argc, char **argv) {
get_terminal_attributes ();
#ifdef USE_LUA
if (lua_file) {
lua_init (lua_file);
}
#endif
inner_main ();

View File

@ -306,10 +306,15 @@ static inline char *fetch_str (int len) {
static inline char *fetch_str_dup (void) {
int l = prefetch_strlen ();
assert (l >= 0);
char *s = talloc (l + 1);
memcpy (s, fetch_str (l), l);
s[l] = 0;
return s;
int i;
char *s = fetch_str (l);
for (i = 0; i < l; i++) {
if (!s[i]) { break; }
}
char *r = talloc (i + 1);
memcpy (r, s, i);
r[i] = 0;
return r;
}
static inline int fetch_update_str (char **s) {
@ -361,6 +366,7 @@ static inline int set_update_int (int *value, int new_value) {
static inline void fetch_skip (int n) {
in_ptr += n;
assert (in_ptr <= in_end);
}
static inline void fetch_skip_str (void) {
@ -382,6 +388,7 @@ static inline long have_prefetch_ints (void) {
int fetch_bignum (BIGNUM *x);
static inline int fetch_int (void) {
assert (in_ptr + 1 <= in_end);
if (verbosity > 6) {
logprintf ("fetch_int: 0x%08x (%d)\n", *in_ptr, *in_ptr);
}
@ -392,37 +399,44 @@ static inline int fetch_bool (void) {
if (verbosity > 6) {
logprintf ("fetch_bool: 0x%08x (%d)\n", *in_ptr, *in_ptr);
}
assert (in_ptr + 1 <= in_end);
assert (*(in_ptr) == (int)CODE_bool_true || *(in_ptr) == (int)CODE_bool_false);
return *(in_ptr ++) == (int)CODE_bool_true;
}
static inline int prefetch_int (void) {
assert (in_ptr < in_end);
return *(in_ptr);
}
static inline void prefetch_data (void *data, int size) {
assert (in_ptr + (size >> 2) <= in_end);
memcpy (data, in_ptr, size);
}
static inline void fetch_data (void *data, int size) {
assert (in_ptr + (size >> 2) <= in_end);
memcpy (data, in_ptr, size);
assert (!(size & 3));
in_ptr += (size >> 2);
}
static inline long long fetch_long (void) {
assert (in_ptr + 2 <= in_end);
long long r = *(long long *)in_ptr;
in_ptr += 2;
return r;
}
static inline double fetch_double (void) {
assert (in_ptr + 2 <= in_end);
double r = *(double *)in_ptr;
in_ptr += 2;
return r;
}
static inline void fetch_ints (void *data, int count) {
assert (in_ptr + count <= in_end);
memcpy (data, in_ptr, 4 * count);
in_ptr += count;
}

View File

@ -904,7 +904,9 @@ void do_send_message (peer_id_t id, const char *msg, int len) {
return;
}
}
long long t = -lrand48 () * (1ll << 32) - lrand48 ();
long long t;
secure_random (&t, 8);
logprintf ("t = %lld, len = %d\n", t, len);
bl_do_send_message_text (t, our_id, get_peer_type (id), get_peer_id (id), time (0), len, msg);
struct message *M = message_get (t);
assert (M);

View File

@ -78,6 +78,9 @@ void tfree (void *ptr, int size __attribute__ ((unused))) {
#ifdef DEBUG
total_allocated_bytes -= size;
ptr -= RES_PRE;
if (size != (int)((*(int *)ptr) ^ 0xbedabeda)) {
logprintf ("size = %d, ptr = %d\n", size, (*(int *)ptr) ^ 0xbedabeda);
}
assert (*(int *)ptr == (int)((size) ^ 0xbedabeda));
assert (*(int *)(ptr + RES_PRE + size) == (int)((size) ^ 0x7bed7bed));
assert (*(int *)(ptr + 4) == size);

4
tree.h
View File

@ -24,6 +24,7 @@
#include <tools.h>
#include <assert.h>
#pragma pack(push,4)
#define DEFINE_TREE(X_NAME, X_TYPE, X_CMP, X_UNSET) \
struct tree_ ## X_NAME { \
struct tree_ ## X_NAME *left, *right;\
@ -58,6 +59,7 @@ void tree_split_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, struct tree_ ##
}\
}\
\
struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) __attribute__ ((warn_unused_result));\
struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) {\
if (!T) {\
return new_tree_node_ ## X_NAME (x, y);\
@ -93,6 +95,7 @@ struct tree_ ## X_NAME *tree_merge_ ## X_NAME (struct tree_ ## X_NAME *L, struct
}\
}\
\
struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) __attribute__ ((warn_unused_result));\
struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\
assert (T);\
int c = X_CMP (x, T->x);\
@ -150,4 +153,5 @@ void tree_check_ ## X_NAME (struct tree_ ## X_NAME *T) { \
}\
#define int_cmp(a,b) ((a) - (b))
#pragma pack(pop)
#endif