Repository: vysheng/tg Branch: master Commit: 6547c0b21b97 Files: 69 Total size: 748.8 KB Directory structure: gitextract_jznprqyy/ ├── .gitignore ├── .gitmodules ├── .travis.yml ├── CHANGELOG ├── LICENSE ├── LICENSE.h ├── Makefile.in ├── Makefile.tgl ├── Makefile.tl-parser ├── README-Cygwin.md ├── README-LUA ├── README-PY.md ├── README.es ├── README.md ├── ax_lua.m4 ├── ax_python.m4 ├── bootstrap ├── config.h.in ├── config.sample ├── configure ├── configure.ac ├── debian/ │ ├── changelog │ ├── clean │ ├── compat │ ├── control │ ├── copyright │ ├── docs │ ├── install │ ├── rules │ ├── source/ │ │ └── format │ ├── telegram-cli.8 │ ├── telegram-cli.logrotate │ ├── telegram-cli.manpages │ ├── telegram-cli.postinst.debhelper │ ├── telegram-cli.preinst │ ├── telegram-cli.preinst.debhelper │ ├── telegram-cli.prerm │ ├── telegram-cli.prerm.debhelper │ ├── telegram-cli.upstart │ └── watch ├── event-old.h ├── gentoo/ │ └── net-im/ │ └── telegram-cli/ │ ├── Manifest │ └── telegram-cli-9999.ebuild ├── interface.c ├── interface.h ├── json-tg.c ├── json-tg.h ├── loop.c ├── loop.h ├── lua-tg.c ├── lua-tg.h ├── m4-ax_gcc_builtin.m4 ├── m4_ax_check_openssl.m4 ├── m4_ax_check_zlib.m4 ├── main.c ├── python-tg.c ├── python-tg.h ├── python-types.c ├── python-types.h ├── rpm/ │ └── telegram-cli-Beta-2.fc20.x86_64.rpm ├── server.pub ├── start-telegram-daemon ├── telegram-cli-cygwin.patch ├── telegram-cli.spec ├── telegram-daemon ├── telegram.h ├── test.lua ├── tg-server.pub └── tg-test.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ telegram *.o Makefile aclocal.m4 autom4te.cache config.h config.log config.status .idea/ nbproject/ bin/ objs/ dep/ auto/ libs/ debian/telegram-cli.[a-z] debian/files debian/telegram-cli/* debian/telegram-cli.debhelper.log debian/telegram-cli.substvars __pycache__ ================================================ FILE: .gitmodules ================================================ [submodule "tgl"] path = tgl url = https://github.com/vysheng/tgl.git ================================================ FILE: .travis.yml ================================================ language: c compiler: - gcc - clang install: - sudo apt-get update - sudo apt-get install libconfig8-dev - sudo apt-get install libreadline6-dev - sudo apt-get install libssl-dev - sudo apt-get install liblua5.2-dev lua5.2 - sudo apt-get install python-dev python - sudo apt-get install libevent-dev - sudo apt-get install libjansson-dev script: - git submodule update --init --recursive - ./configure - make ================================================ FILE: CHANGELOG ================================================ 1.3.3 * support for sending custom keyboard * fixed contact_search * TGL-2.0.3 1.3.2 * use TGL-2.0.2 * add block/unblock user methods * support for autocomplete for bot's commands 1.3.1 * added error codes 1.3.0 * layer 28 support (passwords, replies, webpages, other changes) * output in json format * support for lua functions in CLI mode (register_interface_function) * bugfixes * output error codes to socket * allow [reply=], [disable_preview] and [enable_preview] prefixes to query 1.2.1 * fixed registration/login problem * added extension to downloads 1.2.0 * layer 22 support * new authorization code * fixed time-related problems * fixed crash after hibernation 1.0.6 * layer 18 support 1.0.5 * listening socket (tcp and unix) for commands 1.0.4 * changed create_group_chat format * changed search query * rewritten interface code. Support for escaped characters in quotes 1.0.3 * options to help to run telegram-cli as daemon 1.0.2 * Bug fixes 1.0.1 * Added pfs support. To use it you should add 'pfs_enabled=true' line to config. * Added export_card/import_card methods ================================================ FILE: LICENSE ================================================ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. ================================================ FILE: LICENSE.h ================================================ " GNU GENERAL PUBLIC LICENSE\n" " Version 2, June 1991\n" "\n" " Copyright (C) 1989, 1991 Free Software Foundation, Inc.,\n" " 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" " Everyone is permitted to copy and distribute verbatim copies\n" " of this license document, but changing it is not allowed.\n" "\n" " Preamble\n" "\n" " The licenses for most software are designed to take away your\n" "freedom to share and change it. By contrast, the GNU General Public\n" "License is intended to guarantee your freedom to share and change free\n" "software--to make sure the software is free for all its users. This\n" "General Public License applies to most of the Free Software\n" "Foundation's software and to any other program whose authors commit to\n" "using it. (Some other Free Software Foundation software is covered by\n" "the GNU Lesser General Public License instead.) You can apply it to\n" "your programs, too.\n" "\n" " When we speak of free software, we are referring to freedom, not\n" "price. Our General Public Licenses are designed to make sure that you\n" "have the freedom to distribute copies of free software (and charge for\n" "this service if you wish), that you receive source code or can get it\n" "if you want it, that you can change the software or use pieces of it\n" "in new free programs; and that you know you can do these things.\n" "\n" " To protect your rights, we need to make restrictions that forbid\n" "anyone to deny you these rights or to ask you to surrender the rights.\n" "These restrictions translate to certain responsibilities for you if you\n" "distribute copies of the software, or if you modify it.\n" "\n" " For example, if you distribute copies of such a program, whether\n" "gratis or for a fee, you must give the recipients all the rights that\n" "you have. You must make sure that they, too, receive or can get the\n" "source code. And you must show them these terms so they know their\n" "rights.\n" "\n" " We protect your rights with two steps: (1) copyright the software, and\n" "(2) offer you this license which gives you legal permission to copy,\n" "distribute and/or modify the software.\n" "\n" " Also, for each author's protection and ours, we want to make certain\n" "that everyone understands that there is no warranty for this free\n" "software. If the software is modified by someone else and passed on, we\n" "want its recipients to know that what they have is not the original, so\n" "that any problems introduced by others will not reflect on the original\n" "authors' reputations.\n" "\n" " Finally, any free program is threatened constantly by software\n" "patents. We wish to avoid the danger that redistributors of a free\n" "program will individually obtain patent licenses, in effect making the\n" "program proprietary. To prevent this, we have made it clear that any\n" "patent must be licensed for everyone's free use or not licensed at all.\n" "\n" " The precise terms and conditions for copying, distribution and\n" "modification follow.\n" "\n" " GNU GENERAL PUBLIC LICENSE\n" " TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n" "\n" " 0. This License applies to any program or other work which contains\n" "a notice placed by the copyright holder saying it may be distributed\n" "under the terms of this General Public License. The \"Program\", below,\n" "refers to any such program or work, and a \"work based on the Program\"\n" "means either the Program or any derivative work under copyright law:\n" "that is to say, a work containing the Program or a portion of it,\n" "either verbatim or with modifications and/or translated into another\n" "language. (Hereinafter, translation is included without limitation in\n" "the term \"modification\".) Each licensee is addressed as \"you\".\n" "\n" "Activities other than copying, distribution and modification are not\n" "covered by this License; they are outside its scope. The act of\n" "running the Program is not restricted, and the output from the Program\n" "is covered only if its contents constitute a work based on the\n" "Program (independent of having been made by running the Program).\n" "Whether that is true depends on what the Program does.\n" "\n" " 1. You may copy and distribute verbatim copies of the Program's\n" "source code as you receive it, in any medium, provided that you\n" "conspicuously and appropriately publish on each copy an appropriate\n" "copyright notice and disclaimer of warranty; keep intact all the\n" "notices that refer to this License and to the absence of any warranty;\n" "and give any other recipients of the Program a copy of this License\n" "along with the Program.\n" "\n" "You may charge a fee for the physical act of transferring a copy, and\n" "you may at your option offer warranty protection in exchange for a fee.\n" "\n" " 2. You may modify your copy or copies of the Program or any portion\n" "of it, thus forming a work based on the Program, and copy and\n" "distribute such modifications or work under the terms of Section 1\n" "above, provided that you also meet all of these conditions:\n" "\n" " a) You must cause the modified files to carry prominent notices\n" " stating that you changed the files and the date of any change.\n" "\n" " b) You must cause any work that you distribute or publish, that in\n" " whole or in part contains or is derived from the Program or any\n" " part thereof, to be licensed as a whole at no charge to all third\n" " parties under the terms of this License.\n" "\n" " c) If the modified program normally reads commands interactively\n" " when run, you must cause it, when started running for such\n" " interactive use in the most ordinary way, to print or display an\n" " announcement including an appropriate copyright notice and a\n" " notice that there is no warranty (or else, saying that you provide\n" " a warranty) and that users may redistribute the program under\n" " these conditions, and telling the user how to view a copy of this\n" " License. (Exception: if the Program itself is interactive but\n" " does not normally print such an announcement, your work based on\n" " the Program is not required to print an announcement.)\n" "\n" "These requirements apply to the modified work as a whole. If\n" "identifiable sections of that work are not derived from the Program,\n" "and can be reasonably considered independent and separate works in\n" "themselves, then this License, and its terms, do not apply to those\n" "sections when you distribute them as separate works. But when you\n" "distribute the same sections as part of a whole which is a work based\n" "on the Program, the distribution of the whole must be on the terms of\n" "this License, whose permissions for other licensees extend to the\n" "entire whole, and thus to each and every part regardless of who wrote it.\n" "\n" "Thus, it is not the intent of this section to claim rights or contest\n" "your rights to work written entirely by you; rather, the intent is to\n" "exercise the right to control the distribution of derivative or\n" "collective works based on the Program.\n" "\n" "In addition, mere aggregation of another work not based on the Program\n" "with the Program (or with a work based on the Program) on a volume of\n" "a storage or distribution medium does not bring the other work under\n" "the scope of this License.\n" "\n" " 3. You may copy and distribute the Program (or a work based on it,\n" "under Section 2) in object code or executable form under the terms of\n" "Sections 1 and 2 above provided that you also do one of the following:\n" "\n" " a) Accompany it with the complete corresponding machine-readable\n" " source code, which must be distributed under the terms of Sections\n" " 1 and 2 above on a medium customarily used for software interchange; or,\n" "\n" " b) Accompany it with a written offer, valid for at least three\n" " years, to give any third party, for a charge no more than your\n" " cost of physically performing source distribution, a complete\n" " machine-readable copy of the corresponding source code, to be\n" " distributed under the terms of Sections 1 and 2 above on a medium\n" " customarily used for software interchange; or,\n" "\n" " c) Accompany it with the information you received as to the offer\n" " to distribute corresponding source code. (This alternative is\n" " allowed only for noncommercial distribution and only if you\n" " received the program in object code or executable form with such\n" " an offer, in accord with Subsection b above.)\n" "\n" "The source code for a work means the preferred form of the work for\n" "making modifications to it. For an executable work, complete source\n" "code means all the source code for all modules it contains, plus any\n" "associated interface definition files, plus the scripts used to\n" "control compilation and installation of the executable. However, as a\n" "special exception, the source code distributed need not include\n" "anything that is normally distributed (in either source or binary\n" "form) with the major components (compiler, kernel, and so on) of the\n" "operating system on which the executable runs, unless that component\n" "itself accompanies the executable.\n" "\n" "If distribution of executable or object code is made by offering\n" "access to copy from a designated place, then offering equivalent\n" "access to copy the source code from the same place counts as\n" "distribution of the source code, even though third parties are not\n" "compelled to copy the source along with the object code.\n" "\n" " 4. You may not copy, modify, sublicense, or distribute the Program\n" "except as expressly provided under this License. Any attempt\n" "otherwise to copy, modify, sublicense or distribute the Program is\n" "void, and will automatically terminate your rights under this License.\n" "However, parties who have received copies, or rights, from you under\n" "this License will not have their licenses terminated so long as such\n" "parties remain in full compliance.\n" "\n" " 5. You are not required to accept this License, since you have not\n" "signed it. However, nothing else grants you permission to modify or\n" "distribute the Program or its derivative works. These actions are\n" "prohibited by law if you do not accept this License. Therefore, by\n" "modifying or distributing the Program (or any work based on the\n" "Program), you indicate your acceptance of this License to do so, and\n" "all its terms and conditions for copying, distributing or modifying\n" "the Program or works based on it.\n" "\n" " 6. Each time you redistribute the Program (or any work based on the\n" "Program), the recipient automatically receives a license from the\n" "original licensor to copy, distribute or modify the Program subject to\n" "these terms and conditions. You may not impose any further\n" "restrictions on the recipients' exercise of the rights granted herein.\n" "You are not responsible for enforcing compliance by third parties to\n" "this License.\n" "\n" " 7. If, as a consequence of a court judgment or allegation of patent\n" "infringement or for any other reason (not limited to patent issues),\n" "conditions are imposed on you (whether by court order, agreement or\n" "otherwise) that contradict the conditions of this License, they do not\n" "excuse you from the conditions of this License. If you cannot\n" "distribute so as to satisfy simultaneously your obligations under this\n" "License and any other pertinent obligations, then as a consequence you\n" "may not distribute the Program at all. For example, if a patent\n" "license would not permit royalty-free redistribution of the Program by\n" "all those who receive copies directly or indirectly through you, then\n" "the only way you could satisfy both it and this License would be to\n" "refrain entirely from distribution of the Program.\n" "\n" "If any portion of this section is held invalid or unenforceable under\n" "any particular circumstance, the balance of the section is intended to\n" "apply and the section as a whole is intended to apply in other\n" "circumstances.\n" "\n" "It is not the purpose of this section to induce you to infringe any\n" "patents or other property right claims or to contest validity of any\n" "such claims; this section has the sole purpose of protecting the\n" "integrity of the free software distribution system, which is\n" "implemented by public license practices. Many people have made\n" "generous contributions to the wide range of software distributed\n" "through that system in reliance on consistent application of that\n" "system; it is up to the author/donor to decide if he or she is willing\n" "to distribute software through any other system and a licensee cannot\n" "impose that choice.\n" "\n" "This section is intended to make thoroughly clear what is believed to\n" "be a consequence of the rest of this License.\n" "\n" " 8. If the distribution and/or use of the Program is restricted in\n" "certain countries either by patents or by copyrighted interfaces, the\n" "original copyright holder who places the Program under this License\n" "may add an explicit geographical distribution limitation excluding\n" "those countries, so that distribution is permitted only in or among\n" "countries not thus excluded. In such case, this License incorporates\n" "the limitation as if written in the body of this License.\n" "\n" " 9. The Free Software Foundation may publish revised and/or new versions\n" "of the General Public License from time to time. Such new versions will\n" "be similar in spirit to the present version, but may differ in detail to\n" "address new problems or concerns.\n" "\n" "Each version is given a distinguishing version number. If the Program\n" "specifies a version number of this License which applies to it and \"any\n" "later version\", you have the option of following the terms and conditions\n" "either of that version or of any later version published by the Free\n" "Software Foundation. If the Program does not specify a version number of\n" "this License, you may choose any version ever published by the Free Software\n" "Foundation.\n" "\n" " 10. If you wish to incorporate parts of the Program into other free\n" "programs whose distribution conditions are different, write to the author\n" "to ask for permission. For software which is copyrighted by the Free\n" "Software Foundation, write to the Free Software Foundation; we sometimes\n" "make exceptions for this. Our decision will be guided by the two goals\n" "of preserving the free status of all derivatives of our free software and\n" "of promoting the sharing and reuse of software generally.\n" "\n" " NO WARRANTY\n" "\n" " 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n" "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n" "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n" "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n" "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n" "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n" "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n" "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n" "REPAIR OR CORRECTION.\n" "\n" " 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n" "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n" "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n" "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n" "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n" "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n" "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n" "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n" "POSSIBILITY OF SUCH DAMAGES.\n" "\n" " END OF TERMS AND CONDITIONS\n" "\n" " How to Apply These Terms to Your New Programs\n" "\n" " If you develop a new program, and you want it to be of the greatest\n" "possible use to the public, the best way to achieve this is to make it\n" "free software which everyone can redistribute and change under these terms.\n" "\n" " To do so, attach the following notices to the program. It is safest\n" "to attach them to the start of each source file to most effectively\n" "convey the exclusion of warranty; and each file should have at least\n" "the \"copyright\" line and a pointer to where the full notice is found.\n" "\n" " \n" " Copyright (C) \n" "\n" " This program is free software; you can redistribute it and/or modify\n" " it under the terms of the GNU General Public License as published by\n" " the Free Software Foundation; either version 2 of the License, or\n" " (at your option) any later version.\n" "\n" " This program is distributed in the hope that it will be useful,\n" " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" " GNU General Public License for more details.\n" "\n" " You should have received a copy of the GNU General Public License along\n" " with this program; if not, write to the Free Software Foundation, Inc.,\n" " 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" "\n" "Also add information on how to contact you by electronic and paper mail.\n" "\n" "If the program is interactive, make it output a short notice like this\n" "when it starts in an interactive mode:\n" "\n" " Gnomovision version 69, Copyright (C) year name of author\n" " Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n" " This is free software, and you are welcome to redistribute it\n" " under certain conditions; type `show c' for details.\n" "\n" "The hypothetical commands `show w' and `show c' should show the appropriate\n" "parts of the General Public License. Of course, the commands you use may\n" "be called something other than `show w' and `show c'; they could even be\n" "mouse-clicks or menu items--whatever suits your program.\n" "\n" "You should also get your employer (if you work as a programmer) or your\n" "school, if any, to sign a \"copyright disclaimer\" for the program, if\n" "necessary. Here is a sample; alter the names:\n" "\n" " Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n" " `Gnomovision' (which makes passes at compilers) written by James Hacker.\n" "\n" " , 1 April 1989\n" " Ty Coon, President of Vice\n" "\n" "This General Public License does not permit incorporating your program into\n" "proprietary programs. If your program is a subroutine library, you may\n" "consider it more useful to permit linking proprietary applications with the\n" "library. If this is what you want to do, use the GNU Lesser General\n" "Public License instead of this License.\n" ================================================ FILE: Makefile.in ================================================ srcdir=@srcdir@ CFLAGS=@CFLAGS@ LDFLAGS=@LDFLAGS@ @OPENSSL_LDFLAGS@ CPPFLAGS=@CPPFLAGS@ @OPENSSL_INCLUDES@ DEFS=@DEFS@ COMPILE_FLAGS=${CFLAGS} ${CPFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Werror -Wextra -Wno-missing-field-initializers -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb -Wno-unused-parameter -fPIC EXTRA_LIBS=@LIBS@ @EXTRA_LIBS@ @OPENSSL_LIBS@ LOCAL_LDFLAGS=-rdynamic -ggdb -levent ${EXTRA_LIBS} -ldl -lpthread -lutil LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS} DEP=dep AUTO=auto EXE=bin OBJ=objs LIB=libs DIR_LIST=${DEP} ${AUTO} ${EXE} ${OBJ} ${LIB} ${DEP}/auto ${OBJ}/auto ${OBJ}/crypto ${DEP}/crypto EXE_LIST=${EXE}/telegram-cli TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/lua-tg.o ${OBJ}/json-tg.o ${OBJ}/python-tg.o ${OBJ}/python-types.o INCLUDE=-I. -I${srcdir} -I${srcdir}/tgl CC=@CC@ .SUFFIXES: .SUFFIXES: .c .h .o all: ${EXE_LIST} ${DIR_LIST} create_dirs_and_headers: ${DIR_LIST} ${AUTO}/auto-skip.h ${AUTO}/auto-fetch.h ${AUTO}/auto-store.h ${AUTO}/auto-autocomplete.h ${AUTO}/auto-types.h ${AUTO}/constants.h ${AUTO}/constants.h ${AUTO}/auto-skip.h ${AUTO}/auto-fetch.h ${AUTO}/auto-store.h ${AUTO}/auto-autocomplete.h ${AUTO}/auto-types.h ${AUTO}/auto-fetch-ds.h ${AUTO}/auto-free-ds.h ${AUTO}/auto-store-ds.h ${AUTO}/auto-print-ds.h create_dirs: ${DIR_LIST} dump-tl: ${EXE}/dump-tl-file include ${srcdir}/Makefile.tl-parser include ${srcdir}/Makefile.tgl ${DIR_LIST}: @test -d $@ || mkdir -p $@ OBJ_LIST=${TG_OBJECTS} ${TGL_OBJECTS} ${TGL_COMMON_OBJECTS} ${GENERATE_OBJECTS} ${TL_PARSER_OBJECTS} ${TGL_OBJECTS_AUTO} DEPENDENCE=$(subst ${OBJ}/,${DEP}/,$(patsubst %.o,%.d,${OBJ_LIST})) DEPENDENCE_LIST=${DEPENDENCE} -include ${DEPENDENCE_LIST} ${TG_OBJECTS}: ${OBJ}/%.o: ${srcdir}/%.c | create_dirs_and_headers ${CC} ${INCLUDE} ${COMPILE_FLAGS} -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $< ${EXE}/telegram-cli: ${TG_OBJECTS} ${LIB}/libtgl.a ${CC} $^ ${LINK_FLAGS} -o $@ clean: rm -rf ${DIR_LIST} distclean: rm -rf ${DIR_LIST} config.h config.log config.status ================================================ FILE: Makefile.tgl ================================================ TGL_OBJECTS=${OBJ}/mtproto-common.o ${OBJ}/mtproto-client.o ${OBJ}/mtproto-key.o ${OBJ}/queries.o ${OBJ}/structures.o ${OBJ}/binlog.o ${OBJ}/tgl.o ${OBJ}/updates.o ${OBJ}/tgl-net.o ${OBJ}/tgl-timers.o ${OBJ}/tg-mime-types.o ${OBJ}/mtproto-utils.o ${OBJ}/crypto/bn_openssl.o ${OBJ}/crypto/bn_altern.o ${OBJ}/crypto/rsa_pem_openssl.o ${OBJ}/crypto/rsa_pem_altern.o ${OBJ}/crypto/md5_openssl.o ${OBJ}/crypto/md5_altern.o ${OBJ}/crypto/sha_openssl.o ${OBJ}/crypto/sha_altern.o ${OBJ}/crypto/aes_openssl.o ${OBJ}/crypto/aes_altern.o TGL_OBJECTS_AUTO=${OBJ}/auto/auto-skip.o ${OBJ}/auto/auto-fetch.o ${OBJ}/auto/auto-store.o ${OBJ}/auto/auto-autocomplete.o ${OBJ}/auto/auto-types.o ${OBJ}/auto/auto-fetch-ds.o ${OBJ}/auto/auto-free-ds.o ${OBJ}/auto/auto-store-ds.o ${OBJ}/auto/auto-print-ds.o TLD_OBJECTS=${OBJ}/dump-tl-file.o GENERATE_OBJECTS=${OBJ}/generate.o TGL_COMMON_OBJECTS=${OBJ}/tools.o ${OBJ}/crypto/rand_openssl.o ${OBJ}/crypto/rand_altern.o ${OBJ}/crypto/err_openssl.o ${OBJ}/crypto/err_altern.o TGL_OBJ_C=${GENERATE_OBJECTS} ${TGL_COMMON_OBJECTS} ${TGL_OBJECTS} ${TLD_OBJECTS} .SUFFIXES: .SUFFIXES: .c .h .o dump-tl: ${EXE}/dump-tl-file ${TGL_OBJECTS}: ${AUTO}/constants.h ${AUTO}/auto-skip.h ${AUTO}/auto-fetch.h ${AUTO}/auto-store.h ${AUTO}/auto-autocomplete.h ${AUTO}/auto-types.h ${AUTO}/auto-fetch-ds.h ${AUTO}/auto-free-ds.h ${AUTO}/auto-store-ds.h ${AUTO}/auto-print-ds.h ${TGL_OBJ_C}: ${OBJ}/%.o: ${srcdir}/tgl/%.c | create_dirs ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $< ${TGL_OBJECTS_AUTO}: ${OBJ}/auto/%.o: ${AUTO}/%.c | create_dirs ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $< #${OBJ}/auto/auto.o: ${AUTO}/auto.c # ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl -c -MP -MD -MF ${DEP}/auto/auto.d -MQ ${OBJ}/auto/auto.o -o $@ $< ${LIB}/libtgl.a: ${TGL_OBJECTS} ${TGL_COMMON_OBJECTS} ${TGL_OBJECTS_AUTO} rm -f $@ && ar ruv $@ $^ ${EXE}/generate: ${GENERATE_OBJECTS} ${TGL_COMMON_OBJECTS} ${CC} ${GENERATE_OBJECTS} ${TGL_COMMON_OBJECTS} ${LINK_FLAGS} -o $@ ${AUTO}/scheme.tlo: ${AUTO}/scheme.tl ${EXE}/tl-parser ${EXE}/tl-parser -e $@ ${AUTO}/scheme.tl ${AUTO}/scheme.tl: ${srcdir}/tgl/scheme.tl ${srcdir}/tgl/encrypted_scheme.tl ${srcdir}/tgl/binlog.tl ${srcdir}/tgl/append.tl ${srcdir}/tgl/mtproto.tl | ${AUTO} cat $^ > $@ ${AUTO}/scheme2.tl: ${AUTO}/scheme.tl ${EXE}/tl-parser ${EXE}/tl-parser -E ${AUTO}/scheme.tl 2> $@ || ( cat $@ && rm $@ && false ) ${AUTO}/auto-%.c: ${AUTO}/scheme.tlo ${EXE}/generate auto/constants.h ${AUTO}/auto-%.h | create_dirs_and_headers ${EXE}/generate -g $(patsubst ${AUTO}/auto-%.c,%,$@) ${AUTO}/scheme.tlo > $@ || ( rm $@ && false ) ${AUTO}/auto-%.h: ${AUTO}/scheme.tlo ${EXE}/generate ${EXE}/generate -g $(patsubst ${AUTO}/auto-%.h,%-header,$@) ${AUTO}/scheme.tlo > $@ || ( rm $@ && false ) ${AUTO}/constants.h: ${AUTO}/scheme2.tl ${srcdir}/tgl/gen_constants_h.awk awk -f ${srcdir}/tgl/gen_constants_h.awk < $< > $@ ${EXE}/dump-tl-file: ${OBJ}/auto/auto.o ${TLD_OBJECTS} ${CC} ${OBJ}/auto/auto.o ${TLD_OBJECTS} ${LINK_FLAGS} -o $@ ================================================ FILE: Makefile.tl-parser ================================================ TL_PARSER_OBJECTS=${OBJ}/tl-parser.o ${OBJ}/tlc.o ${TL_PARSER_OBJECTS}: ${OBJ}/%.o: ${srcdir}/tgl/tl-parser/%.c | create_dirs ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl/tl-parser -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $< ${EXE}/tl-parser: ${TL_PARSER_OBJECTS} ${CC} $^ ${LINK_FLAGS} -o $@ ================================================ FILE: README-Cygwin.md ================================================ ### Installation on Windows To use telegram-cli in Windows, you should compile with Cygwin which has POSIX API functionality. Install [Cygwin](https://www.cygwin.com/) and cygwin's package manager, [apt-cyg](https://github.com/transcode-open/apt-cyg). In Cygwin Terminal, install compiler and tools : apt-cyg install cygwin32-gcc-core cygwin32-gcc-g++ gcc-core gcc-g++ make wget patch diffutils grep tar gzip Now you have a compiler, but no libraries. You need readline, openssl, libconfig, liblua, python and libjansson to use telegram-cli's full functionality. Then Clone GitHub Repository in Cygwin Terminal git clone --recursive https://github.com/vysheng/tg.git In Cygwin Terminal, type: apt-cyg install libevent-devel openssl-devel libreadline-devel lua-devel python3 (Install package 'python' to use Python 2.7, or install package 'python3' to use Python 3) libconfig and libjansson is not in cygwin's package, so you should compile yourself. Compile libconfig wget http://www.hyperrealm.com/libconfig/libconfig-1.5.tar.gz tar xvf libconfig-1.5.tar.gz && cd libconfig-1.5 ./configure make && make install && cd .. Compile libjansson wget http://www.digip.org/jansson/releases/jansson-2.7.tar.gz tar xvf jansson-2.7.tar.gz && cd jansson-2.7 ./configure make && make install && cd .. Then, go to tg directory then generate Makefile. cd tg ./configure We need to patch Makefile and loop.c to compile in cygwin. Download this [patch](https://gist.github.com/ied206/d774a445f36004d263ab) then untar. Then, patch in tg directory. patch -p1 < telegram-cli-cygwin.patch Then make After compile is done, **telegram-cli.exe** will be generated in **bin** directory. To run telegram-cli, type bin/telegram-cli -k tg-server.pub **Caution**: A binary compiled with Cygwin should be run in Cygwin Terminal. ================================================ FILE: README-LUA ================================================ To use lua with client you should write lua script. You can specify it from config ("lua_script" option) or from command_line [-s]. It should have several functions: on_binlog_replay_end() - it is called when replay of old events end. Any updates prior this call were already received by this client some time ago. on_get_difference_end() - it is called after first get_difference call. So we received all updates after last client execute. on_our_id(our_id) - Informs about id of currently logged in user. on_msg_receive(msg) - it is called when we receive new msg (!! may be called before on_binlog_replay_end, than it is old msg). on_user_update(user,what_changed) - updated info about user. what_changed is array of strings. on_chat_update(user,what_changed) - updated info about user. what_changed is array of strings. on_secret_chat_update(user,what_changed) - updated info about user. what_changed is array of strings. Also, you can call several functions. Each this function last two arguments, are cb_function and cb_extra. These functions may return false immidiately if something is bad with args, or return true and call cb_function in future. cb_function would have two or three arguments: first cb_extra, second success (1 or 0), third result (if applicable). If you want to pass msg to function, you should pass it's id. If you want to pass peer to function, you should pass it's print_name. Or, you can pass string user#id chat#id and secret_chat#id as peer. It is in some cases better. For example if you want to postpone and you are afraid, that print_name would be changed in the meantime. Function_list (arguments are listed aside from cb_function and cb_extra, : get_contact_list () get_dialog_list () rename_chat (chat, new_name) chat_set_photo (chat, file) send_typing (peer) send_typing_abort (peer) send_msg (peer, text) fwd_msg (peer, msg) send_photo (peer, file) send_video (peer, file) send_audio (peer, file) send_document (peer, file) send_text (peer, file) load_photo(msg) load_video(msg) load_video_thumb(msg) load_audio(msg) load_document(msg) load_document_thumb(msg) chat_info (chat) channel_info (channel) user_info (user) get_history (peer, limit) chat_add_user (chat, user) chat_del_user (chat, user) add_contact (phone, first_name, last_name) rename_contact (phone, first_name, last_name) msg_search (peer, text) msg_global_search (text) mark_read (peer) set_profile_photo (file) create_secret_chat (user) create_group_chat (user, name) delete_msg (msg) restore_msg (number) status_online () status_offline () send_location (peer, latitude, longitude) Also, you have function postpone (cb_function, cb_extra, timeout). It will call your cb_function in specified number of seconds (number of seconds may be double). register_interface_function (name, cb_function, cb_arg, description, arg1_type, arg2_type, ...) adds function to CLI interface ================================================ FILE: README-PY.md ================================================ Python Bindings ==================== All of the functions and methods are executed in the network loop of tg, ***NOT IMMEDIATELY***. What this means is all calls should be considered async, and so there is an optional callback parameter for every function/method as the last parameter. For many uses, you won't care about the return value, so you can leave out the callback. Note there are a few cases where the callback is considered mandatory when the function is considered an information query and has no functionality without returned data. These will explicitly have the callback in the parameter list and will be noted in the description. You can specify the python script from config ("python_script" option) or from command_line [-Z]. Version Notes ===================== The python integration is written with Python 2/3 in mind, however, there is a bias to Python 3. Because of this, there are a few caveats: - I am only testing against Python 2.7, and have no intention to support/test < 2.7 but am more than happy to accept PRs for fixes as long as it does not break 2.7/3 - repr/print of native types is dumbed down for < 2.7.9, I highly recommend using this version or newer. (This is due to a [bug](http://bugs.python.org/issue22023) in python) TGL Callbacks ============= Assign python fuctions to the following tgl attributes to set callbacks from TG. | Callback | Description | |--------- | ---------------------| |`tgl.on_binlog_replay_end()` | This is called when replay of old events end. Any updates prior this call were already received by this client some time ago.| |`tgl.on_get_difference_end()`| This is called after first get_difference call. So we received all updates after last client execute.| |`tgl.on_our_id(our_id)`|Informs about id of currently logged in user.| |`tgl.on_msg_receive(msg)`| This is called when we receive new `tgl.Msg` object (*may be called before on_binlog_replay_end, than it is old msg*).| |`tgl.on_user_update(peer, what_changed)`|updated info about user. peer is a `tgl.Peer` object representing the user, and what_changed is array of strings.| |`tgl.on_chat_update(peer, what_changed)`|updated info about chat. peer is a `tgl.Peer` object representing the chat, and what_changed is array of strings.| |`tgl.on_secret_chat_update(peer, what_changed)`|updated info about secret chat. peer is a `tgl.Peer` object representing the secret chat, and what_changed is array of strings.| Python Callback Signatures ========================= As mentioned, all methods and functions have callbacks. The following are the different signatures that may be required (*The description of the method will mention which is used*) | Type | Signature | Description | |----- | ------------------ | ------------| |empty_cb|`(success)`|This just indicated the success of the call. All other callback types have this as well.| |contact_list_cb|`(success, peer_list)`|`peer_list` is a list of `tgl.Peer` objects| |dialog_list_cb|`(success, dialog_list)`|`dialog_list` is a list of dicts, with keys: 'peer': `tgl.Peer`, 'message': `tgl.Msg`| |msg_cb|`(success, msg)`|`msg` is a `tgl.Msg`| |msg_list_cb|`(success, msg_list)`|`msg_list` is a list of `tgl.Msg` objects| |file_cb|`(success, file_path)`|`file_path` is a string with an absolute path| |chat_cb|`(success, peer)`|`peer` is a `tgl.Peer` that will have the type of `tgl.PEER_CHAT`| |peer_cb|`(success, peer)`|`peer` is a `tgl.Peer`| |secret_chat_cb|`(success, peer)`|`peer` is a `tgl.Peer` that will have the type of `tgl.PEER_ENCR_CHAT`| |user_cb|`(success, peer)`|`peer` is a `tgl.Peer` that will have the type of `tgl.PEER_USER`| |str_cb|`(success, string)`|`string` is a simple string| TGL Module Level Fuctions ========================= All of these functions are accessed by importing the `tgl` module. | Function | Description | Callback Type | |--------- | ---------------------| ------------- | |`tgl.get_contact_list (callback)`|Retrieve peers stored in the contact list. *requires callback*|`contact_list_cb`| |`tgl.get_dialog_list (callback)`|Get a list of current conversations with the `tgl.Peer` and the most recent `tgl.Msg`. *requires callback*|`dialog_list_cb`| |`tgl.add_contact (phone, first_name, last_name)`|Adds contact to contact list, last name is optional|`contact_list_cb`| |`tgl.del_contact (peer)`|Removes contact from contact list|`empty_cb`| |`tgl.rename_contact (phone, first_name, last_name) `|Renaming a contact means sending the first/last name with the same phone number of an existing contact|`contact_list_cb`| |`tgl.msg_global_search (text, callback)`|Get all messages that match the search text. *requires callback*|`msg_list_cb`| |`tgl.set_profile_photo (file_path)`|Sets avatar to image found at `file_path`, no checking on the file.|`empty_cb`| |`tgl.create_secret_chat (user)`|Creates secret chat with user, callback recommended to get new peer for the secret chat.|`secret_chat_cb`| |`tgl.create_group_chat (peer_list, name)`|`peer_list` contains users to create group with, must be more than 1 peer.|`empty_cb`| |`tgl.restore_msg (msg_id)`|Restore a deleted message by message id.|`empty_cb`| |`tgl.status_online ()`|Sets status as online|`empty_cb`| |`tgl.status_offline ()`|Sets status as offline|`empty_cb`| |`tgl.import_chat_link (link)`|Join channel using the `link`.|`empty_cb`| |`tgl.safe_exit (exit_status)`|Exception to the rule about callbacks, no callback parameter is accepted. Causes the bot to quit after cleaning up. `exit_status` is an optional parameter with the exit status (On glibc, this must be 0-255)|NONE| Peer ==== ## Attributes | Attribute | Type | Description | |---------- | ---- | ----------------------| |`id`|`int`|Telegram peer id| |`type`|`int`|Peer type, you can compare this with `tgl.PEER_CHAT`, `tgl.PEER_USER`, or `tgl.PEER_ENCR_CHAT`| |`type_name`|`string`|Text representation of the type of the peer, `'chat'`, `'user'`, or `'secret_chat'`| |`name`|`string`|Returns the tg print version of the name. Usually `FirstName_LastName` for user, and the chatname with spaces replaced with `_`| |`user_id`|`int`|Used in secret chats, since a secret chat has it's own id, this is the id of the user at the endpoint.| |`user_list`|`peer_list`|Only used in `tgl.PEER_CHAT` peers, contains list of users. This currently does not work, it is not populating properly.| |`user_status`|`dict`|Only used in `tgl.PEER_USER` peers. Dictionary with the current status, keys: 'online': `bool`, 'when': `datetime`| |`phone`|`string`|Only used in `tgl.PEER_USER` peers. Phone number, only available if user is on contact list.| |`username`|`string`|Only used in `tgl.PEER_USER` peers. Will be `None` if username is not set.| |`first_name`|`string`|Only used in `tgl.PEER_USER` peers.| |`last_name`|`string`|Only used in `tgl.PEER_USER` peers.| ## Methods | Method | Description | Callback Type | |------- | ---------------------| ------------- | |`peer.rename_chat (new_name)`||`empty_cb`| |`peer.chat_set_photo (file)`|Sets avatar for the group to image found at `file_path`, no checking on the file. The calling peer must be of type `tgl.PEER_CHAT`.|`msg_cb`| |`peer.send_typing ()`|Tell peer that you are typing.|`empty_cb`| |`peer.send_typing_abort ()`|Tell peer you are done typing.|`empty_cb`| |`peer.send_msg (text, reply=msg_id, preview=bool)`|Sends message to peer. Optional keyword arguments: reply is the message id we are replying to, preview is a boolean that forces URL preview on or off.|`msg_cb`| |`peer.fwd_msg (msg_id)`|Forwards msg with message id to peer.|`msg_cb`| |`peer.fwd_media (msg_id)`|Forwards media with message id to peer.|`msg_cb`| |`peer.send_photo (file)`|Send media to peer using `file`. No checking is done on the contents of the file.|`msg_cb`| |`peer.send_video (file)`|Send media to peer using `file`. No checking is done on the contents of the file.|`msg_cb`| |`peer.send_audio (file)`|Send media to peer using `file`. No checking is done on the contents of the file.|`msg_cb`| |`peer.send_document (file)`|Send media to peer using `file`. No checking is done on the contents of the file.|`msg_cb`| |`peer.send_text (file)`|Send media to peer using `file`. No checking is done on the contents of the file.|`msg_cb`| |`peer.send_location (latitude, longitude)`|Sends location media message to peer, `longitude` and `latitude` should be specified as double.|`msg_cb`| |`peer.chat_add_user (user)`|Adds `user`(`tgl.Peer`) to the group. The calling peer must be of type `tgl.PEER_CHAT`|`empty_cb`| |`peer.chat_del_user (user)`|Removes `user`(`tgl.Peer`) from the group. The calling peer must be of type `tgl.PEER_CHAT`|`empty_cb`| |`peer.mark_read ()`|Marks the dialog with the peer as read. This cannot be done on message level.|`empty_cb`| |`peer.msg_search (text, callback)`|Get all messages that match the search text with the peer. *requires callback*|`msg_list_cb`| |`peer.get_history (offset, limit, callback)`|Get all messages with the peer. `offset` specifies what message to start at, and `limit` specifies how many messages to retrieve. See example below for one method to get the entire history. *requires callback*|`msg_list_cb`| |`peer.info ()`|Gets peer info.|`peer_cb`| Example usage for `peer.get_history`: ``` from functools import partial history = [] # Get all the history, 100 msgs at a time peer.get_history(0, 100, partial(history_callback, 100, peer)) def history_callback(msg_count, peer, success, msgs) history.extend(msgs) if len(msgs) == msg_count: peer.get_history(len(history), msg_count, partial(history_callback, msg_count, peer)) ``` Msg ==== ## Attributes | Attribute | Type | Description | |---------- | ---- | ----------------------| |`id`|`int`|Message id| |`flags`|`int`|tgl flags, see source code for tgl for various possible flags. This is a bitfield in an int.| |`mention`|`bool`|`True` if you are @mentioned.| |`out`|`bool`|`True` if you sent this message.| |`unread`|`bool`|`True` if you have not marked this as read.| |`service`|`bool`|`True` if the message is a service messages, see tgl.Msg.action for the type.| |`src`|`tgl.Peer`|Peer who sent the message| |`dest`|`tgl.Peer`|Peer who the message was sent too. In a group, this will be the chat peer. Otherwise it will be you.| |`text`|`string`|Text contents of the message. This may be `None` if it's media without caption.| |`media`|`dict`|Dictionary that varies based on the media type.| |`date`|`datetime`|When the message was sent.| |`fwd_src`|`tgl.Peer`|The user that sent the forwarded message.| |`fwd_date`|`datetime`|When the forwarded message was originally sent.| |`reply`|`tgl.Msg`|Message that this message is replying to.| |`reply_id`|`int`|Message id that this message is replying to.| |`action`|`int`|Action enum for the message if `msg.service == True`. See all the possible values below| ## Action Type Constants - tgl.ACTION_NONE - tgl.ACTION_GEO_CHAT_CREATE - tgl.ACTION_GEO_CHAT_CHECKIN - tgl.ACTION_CHAT_CREATE - tgl.ACTION_CHAT_EDIT_TITLE - tgl.ACTION_CHAT_EDIT_PHOTO - tgl.ACTION_CHAT_DELETE_PHOTO - tgl.ACTION_CHAT_ADD_USER - tgl.ACTION_CHAT_ADD_USER_BY_LINK - tgl.ACTION_CHAT_DELETE_USER - tgl.ACTION_SET_MESSAGE_TTL - tgl.ACTION_READ_MESSAGES - tgl.ACTION_DELETE_MESSAGES - tgl.ACTION_SCREENSHOT_MESSAGES - tgl.ACTION_FLUSH_HISTORY - tgl.ACTION_RESEND - tgl.ACTION_NOTIFY_LAYER - tgl.ACTION_TYPING - tgl.ACTION_NOOP - tgl.ACTION_COMMIT_KEY - tgl.ACTION_ABORT_KEY - tgl.ACTION_REQUEST_KEY - tgl.ACTION_ACCEPT_KEY ## Methods | Method | Description | Callback Type | |------- | ---------------------| ------------- | |`msg.load_photo(callback)`|Saves the media and returns the path to the file in the callback. *requires callback*|`file_cb`| |`msg.load_video(callback)`|Saves the media and returns the path to the file in the callback. *requires callback*|`file_cb`| |`msg.load_video_thumb(callback)`|Saves the media and returns the path to the file in the callback. *requires callback*|`file_cb`| |`msg.load_audio(callback)`|Saves the media and returns the path to the file in the callback. *requires callback*|`file_cb`| |`msg.load_document(callback)`|Saves the media and returns the path to the file in the callback. *requires callback*|`file_cb`| |`msg.load_document_thumb(callback)`|Saves the media and returns the path to the file in the callback. *requires callback*|`file_cb`| |`msg.delete_msg ()`|Deletes the message from the local history|`empty_cb`| ================================================ FILE: README.es ================================================ ## Telegram messenger CLI [![Build Status](https://travis-ci.org/vysheng/tg.png)](https://travis-ci.org/vysheng/tg) !!!! May be outdated. Please refer to english README as more actual. Interfaz de línea de comandos para: [Telegram](http://telegram.org). Usa interfaz readline. ### Documentación del API y el protocolo La documentación del APi de Telegram está disponible aquí: http://core.telegram.org/api La documentación del protocolo MTproto está disponible aquí: http://core.telegram.org/mtproto ### Instalación Clona el Repositorio GitHub $ git clone https://github.com/vysheng/tg.git && cd tg o descarga y descomprime el zip $ wget https://github.com/vysheng/tg/archive/master.zip -O tg-master.zip $ unzip tg-master.zip && cd tg-master #### Linux Librerías requeridas: readline openssl y (si desea usar config) libconfig y liblua. Si no deseas usarlo, pasa las siguientes opciones --disable-libconfig y --disable-liblua respectivamente. En Ubuntu usa: $ sudo apt-get install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev En gentoo: $ sudo emerge -av sys-libs/readline dev-libs/libconfig dev-libs/openssl dev-lang/lua En Fedora: $ sudo yum install lua-devel openssl-devel libconfig-devel readline-devel Por defecto Makefile utiliza liblua5.2 de ubuntu. Si utilizas una versión diferente de liblua o linux, tienes que ejecutar el script ./configure o recibirás un error de compilación extraño. Entonces $ ./configure $ make #### Mac OS X El cliente depende de [librería readline](http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html) y [libconfig](http://www.hyperrealm.com/libconfig/), las cuales no están incluídas en OS X por defecto. Debes instalar estas librerías de forma manual, usando por ejemplo [Homebrew](http://brew.sh/). $ brew install libconfig $ brew install readline $ brew install lua $ export CFLAGS="-I/usr/local/include -I/usr/local/Cellar/readline/6.2.4/include" $ export LDFLAGS="-L/usr/local/lib -L/usr/local/Cellar/readline/6.2.4/lib" $ ./configure && make Gracias a [@jfontan](https://github.com/vysheng/tg/issues/3#issuecomment-28293731) por esta solución. #### FreeBSD Instalar estos puertos: * devel/libconfig * devel/libexecinfo Entonces construir: $ env CC=clang CFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./configure $ make #### Otros UNIX Si logras ejecutarlo en otros UNIX, por favor házmelo saber. ### Uso ./telegram -k Por defecto la clave pública se almacena en la misma carpeta con el nombre tg-server.pub o en /etc/telegram/server.pub, si no lo es, indica dónde encontrarlo: ./telegram -k tg-server.pub El Cliente soporta completamiento con TAB e historial de comandos. Peer se refiere al nombre del contacto o de diálogo y se puede acceder por completamiento con Tab. Para los contactos de usuario el peer es el Nombre Apellido con todos los espacios cambiados a guiones bajos. Para los chats es su título con todos los espacios cambiados a guiones bajos. Para los chats encriptados es Nombre Apellido con todos los espacios cambiados a guiones bajos. Si dos o más peers tienen el mismo nombre, una almohadilla y un número es añadido al nombre. (por ejemplo A_B,A_B#1,A_B#2 y así sucesivamente). ### Comandos soportados #### Mensajería * **msg** \ texto - envía el mensaje a este usuario. * **fwd** \ \ - reenviar un mensaje al usuario. Puedes ver los número de mensajes iniciando el Cliente con -N. * **chat_with_peer** \ - inicia un chat con este usuario. /exit o /quit para salir de este modo. * **add_contact** \ \ \ - intenta añadir este contacto a la lista de contactos. * **rename_contact** \ \ \ - intenta renombrar el contacto. Si tienes otro dispositivo será una pelea. * **mark_read** \ - marca todos los mensajes como recibidos de ese usuario. #### Multimedia * **send_photo** \ \ - manda una foto al usuario. * **send_video** \ \ - envia un video al usuario. * **send_text** \ \ - envia un archivo de texto como un mensaje en plano. * **load_photo**/load_video/load_video_thumb \ - carga foto/video indicado del directorio de descarga. * **view_photo**/view_video/view_video_thumb \ - carga foto/video indicado del directorio de descarga y lo abre con el visor por defecto del sistema. #### Opciones de chat de grupo * **chat_info** \ - imprime información del chat. * **chat_add_user** \ \ - agrega un usuario al chat. * **chat_del_user** \ \ - elimina un usuario del chat. * **rename_chat** \ \ - cambia el nombre al chat. #### Search * **search** \ patrón - busca el patrón indicado en los mensajes con ese usuario. * **global_search** patrón - busca el patrón indicado en todos los mensajes. #### Chat secreto * **create_secret_chat** \ - crea un chat secreto con el usuario indicado. * **visualize_key** \ - Muestra la clave de cifrado. Debes compararla con la del otro usuario. #### Estadísticas e información varia. * **user_info** \ - muestra información sobre el usuario. * **history** \ [limit] - muestra el historial (y la marca como leído). Limite por defecto = 40. * **dialog_list** - muestra información acerca del dialogo * **contact_list** - muestra información acerca de tu lista de contactos. * **suggested_contacts** - muestra información sobre sus contactos, tiene un máximo de amigos comunes. * **stats** - solo para depuración. * **show_license** - muestra la licencia GPLv2. * **help** - imprime esta ayuda. ================================================ FILE: README.md ================================================ ## Telegram messenger CLI [![Build Status](https://travis-ci.org/vysheng/tg.png)](https://travis-ci.org/vysheng/tg) Command-line interface for [Telegram](http://telegram.org). Uses readline interface. ### API, Protocol documentation Documentation for Telegram API is available here: http://core.telegram.org/api Documentation for MTproto protocol is available here: http://core.telegram.org/mtproto ### Upgrading to version 1.0 First of all, the binary is now in ./bin folder and is named telegram-cli. So be careful, not to use old binary. Second, config folder is now ${HOME}/.telegram-cli Third, database is not compatible with older versions, so you'll have to login again. Fourth, in peer_name '#' are substitued to '@'. (Not applied to appending of '#%d' in case of two peers having same name). ### Installation Clone GitHub Repository git clone --recursive https://github.com/vysheng/tg.git && cd tg ### Python Support Python support is currently limited to Python 2.7 or Python 3.1+. Other versions may work but are not tested. #### Linux and BSDs Install libs: readline, openssl and (if you want to use config) libconfig, liblua, python and libjansson. If you do not want to use them pass options --disable-libconfig, --disable-liblua, --disable-python and --disable-json respectively. On Ubuntu/Debian use: sudo apt-get install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev libevent-dev libjansson-dev libpython-dev make On gentoo: sudo emerge -av sys-libs/readline dev-libs/libconfig dev-libs/openssl dev-lang/lua dev-libs/libevent dev-libs/jansson dev-lang/python On Fedora: sudo dnf install lua-devel openssl-devel libconfig-devel readline-devel libevent-devel libjansson-devel python-devel On Archlinux: yaourt -S telegram-cli-git On FreeBSD: pkg install libconfig libexecinfo lua52 python On OpenBSD: pkg_add libconfig libexecinfo lua python On openSUSE: sudo zypper in lua-devel libconfig-devel readline-devel libevent-devel libjansson-devel python-devel libopenssl-devel Then, ./configure make #### Other methods to install on linux On Gentoo: use ebuild provided. On Arch: https://aur.archlinux.org/packages/telegram-cli-git #### Mac OS X The client depends on [readline library](http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html) and [libconfig](http://www.hyperrealm.com/libconfig/), which are not included in OS X by default. You have to install these libraries manually. If using [Homebrew](http://brew.sh/): brew install libconfig readline lua python libevent jansson export CFLAGS="-I/usr/local/include -I/usr/local/Cellar/readline/6.3.8/include" export LDFLAGS="-L/usr/local/lib -L/usr/local/Cellar/readline/6.3.8/lib" ./configure && make Thanks to [@jfontan](https://github.com/vysheng/tg/issues/3#issuecomment-28293731) for this solution. If using [MacPorts](https://www.macports.org): sudo port install libconfig-hr sudo port install readline sudo port install lua51 sudo port install python34 sudo port install libevent export CFLAGS="-I/usr/local/include -I/opt/local/include -I/opt/local/include/lua-5.1" export LDFLAGS="-L/usr/local/lib -L/opt/local/lib -L/opt/local/lib/lua-5.1" ./configure && make Install these ports: * devel/libconfig * devel/libexecinfo * lang/lua52 Then build: env CC=clang CFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib LUA=/usr/local/bin/lua52 LUA_INCLUDE=-I/usr/local/include/lua52 LUA_LIB=-llua-5.2 ./configure make #### Other UNIX If you manage to launch it on other UNIX, please let me know. ### Contacts If you would like to ask a question, you can write to my telegram or to the github (or both). To contact me via telegram, you should use import_card method with argument 000653bf:0738ca5d:5521fbac:29246815:a27d0cda ### Usage bin/telegram-cli -k By default, the public key is stored in tg-server.pub in the same folder or in /etc/telegram-cli/server.pub. If not, specify where to find it: bin/telegram-cli -k tg-server.pub Client support TAB completion and command history. Peer refers to the name of the contact or dialog and can be accessed by TAB completion. For user contacts peer name is Name Lastname with all spaces changed to underscores. For chats it is it's title with all spaces changed to underscores For encrypted chats it is Name Lastname with all spaces changed to underscores. If two or more peers have same name, number is appended to the name. (for example A_B, A_B#1, A_B#2 and so on) ### Supported commands #### Messaging * **msg** \ Text - sends message to this peer * **fwd** \ \ - forward message to user. You can see message numbers starting client with -N * **chat_with_peer** \ starts one on one chat session with this peer. /exit or /quit to end this mode. * **add_contact** \ \ \ - tries to add contact to contact-list by phone * **rename_contact** \ \ \ - tries to rename contact. If you have another device it will be a fight * **mark_read** \ - mark read all received messages with peer * **delete_msg** \ - deletes message (not completly, though) * **restore_msg** \ - restores delete message. Impossible for secret chats. Only possible short time (one hour, I think) after deletion #### Multimedia * **send_photo** \ \ - sends photo to peer * **send_video** \ \ - sends video to peer * **send_text** \ \ - sends text file as plain messages * **load_photo**/load_video/load_video_thumb/load_audio/load_document/load_document_thumb \ - loads photo/video/audio/document to download dir * **view_photo**/view_video/view_video_thumb/view_audio/view_document/view_document_thumb \ - loads photo/video to download dir and starts system default viewer * **fwd_media** \ send media in your message. Use this to prevent sharing info about author of media (though, it is possible to determine user_id from media itself, it is not possible get access_hash of this user) * **set_profile_photo** \ - sets userpic. Photo should be square, or server will cut biggest central square part #### Group chat options * **chat_info** \ - prints info about chat * **chat_add_user** \ \ - add user to chat * **chat_del_user** \ \ - remove user from chat * **rename_chat** \ \ * **create_group_chat** \ \ \ \ ... - creates a groupchat with users, use chat_add_user to add more users * **chat_set_photo** \ \ - sets group chat photo. Same limits as for profile photos. #### Search * **search** \ pattern - searches pattern in messages with peer * **global_search** pattern - searches pattern in all messages #### Secret chat * **create_secret_chat** \ - creates secret chat with this user * **visualize_key** \ - prints visualization of encryption key. You should compare it to your partner's one * **set_ttl** \ \ - sets ttl to secret chat. Though client does ignore it, client on other end can make use of it * **accept_secret_chat** \ - manually accept secret chat (only useful when starting with -E key) #### Stats and various info * **user_info** \ - prints info about user * **history** \ [limit] - prints history (and marks it as read). Default limit = 40 * **dialog_list** - prints info about your dialogs * **contact_list** - prints info about users in your contact list * **suggested_contacts** - print info about contacts, you have max common friends * **stats** - just for debugging * **show_license** - prints contents of GPLv2 * **help** - prints this help * **get_self** - get our user info #### Card * **export_card** - print your 'card' that anyone can later use to import your contact * **import_card** \ - gets user by card. You can write messages to him after that. #### Other * **quit** - quit * **safe_quit** - wait for all queries to end then quit ================================================ FILE: ax_lua.m4 ================================================ # =========================================================================== # 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/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 # Copyright (c) 2013 Reuben Thomas # # 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 . # # 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 21 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 lua52 lua5.1 lua51 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 -E -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 -E -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_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 #include #include 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 -E -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-$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]) ]) ================================================ FILE: ax_python.m4 ================================================ # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_python.html # =========================================================================== # # SYNOPSIS # # AX_PYTHON # # DESCRIPTION # # This macro does a complete Python development environment check. # # It recurses through several python versions (from 2.1 to 2.6 in this # version), looking for an executable. When it finds an executable, it # looks to find the header files and library. # # It sets PYTHON_BIN to the name of the python executable, # PYTHON_INCLUDE_DIR to the directory holding the header files, and # PYTHON_LIB to the name of the Python library. # # This macro calls AC_SUBST on PYTHON_BIN (via AC_CHECK_PROG), # PYTHON_INCLUDE_DIR and PYTHON_LIB. # # LICENSE # # Copyright (c) 2008 Michael Tindal # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # 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 14 AC_DEFUN([AX_PYTHON], [AC_MSG_CHECKING(for python build information) AC_MSG_RESULT([]) for python in python3.5 python3.4 python3.3 python3.2 python3.1 python3 python2.7 python2.6 python2 python; do AC_CHECK_PROGS(PYTHON_BIN, [$python]) ax_python_bin=$PYTHON_BIN if test x$ax_python_bin != x; then AC_CHECK_LIB($ax_python_bin, main, ax_python_lib=$ax_python_bin, ax_python_lib=no) if test x$ax_python_lib == xno; then AC_CHECK_LIB(${ax_python_bin}m, main, ax_python_lib=${ax_python_bin}m, ax_python_lib=no) fi if test x$ax_python_lib == xno; then AC_CHECK_LIB(${ax_python_bin}mu, main, ax_python_lib=${ax_python_bin}mu, ax_python_lib=no) fi if test x$ax_python_lib != xno; then ax_python_header=`$ax_python_bin -c "from distutils.sysconfig import *; print(get_config_var('CONFINCLUDEPY'))"` if test x$ax_python_header != x; then break; fi fi fi unset ac_cv_prog_PYTHON_BIN unset PYTHON_BIN done if test x$ax_python_bin = x; then ax_python_bin=no fi if test x$ax_python_header = x; then ax_python_header=no fi if test x$ax_python_lib = x; then ax_python_lib=no fi AC_MSG_RESULT([ results of the Python check:]) AC_MSG_RESULT([ Binary: $ax_python_bin]) AC_MSG_RESULT([ Library: $ax_python_lib]) AC_MSG_RESULT([ Include Dir: $ax_python_header]) PYTHON_FOUND=yes if test x$ax_python_header != xno; then PYTHON_INCLUDE_DIR=$ax_python_header AC_SUBST(PYTHON_INCLUDE_DIR) else PYTHON_FOUND=no fi if test x$ax_python_lib != xno; then PYTHON_LIB=$ax_python_lib AC_SUBST(PYTHON_LIB) else PYTHON_FOUND=no fi AC_SUBST(PYTHON_FOUND) ])dnl ================================================ FILE: bootstrap ================================================ #! /bin/sh aclocal autoheader automake --gnu --add-missing autoconf ================================================ FILE: config.h.in ================================================ /* config.h.in. Generated from configure.ac by autoheader. */ /* disable extf queries */ #undef DISABLE_EXTF /* Use libevent v1 */ #undef EVENT_V1 /* Use libevent v2 */ #undef EVENT_V2 /* Define to 1 if you have the `alarm' function. */ #undef HAVE_ALARM /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_INET_H /* Define to 1 if you have the `endpwent' function. */ #undef HAVE_ENDPWENT /* Define to 1 if you have the header file. */ #undef HAVE_EXECINFO_H /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_LAUXLIB_H /* Define to 1 if you have the `config' library (-lconfig). */ #undef HAVE_LIBCONFIG /* Define to 1 if you have the `event' library (-levent). */ #undef HAVE_LIBEVENT /* Define to 1 if you have the `gcrypt' library (-lgcrypt). */ #undef HAVE_LIBGCRYPT /* Define to 1 if you have the `jansson' library (-ljansson). */ #undef HAVE_LIBJANSSON /* Define to 1 if you have `z' library (-lz) */ #undef HAVE_LIBZ /* Define to 1 if you have the header file. */ #undef HAVE_LUACONF_H /* Define to 1 if you have the header file. */ #undef HAVE_LUALIB_H /* Define to 1 if you have the header file. */ #undef HAVE_LUA_H /* Define to 1 if you have the header file. */ #undef HAVE_MACH_MACH_H /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ #undef HAVE_MALLOC /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET /* Define to 1 if you have the `mkdir' function. */ #undef HAVE_MKDIR /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H /* Define to 1 if your system has a GNU libc compatible `realloc' function, and to 0 otherwise. */ #undef HAVE_REALLOC /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT /* Define to 1 if you have the `socket' function. */ #undef HAVE_SOCKET /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strndup' function. */ #undef HAVE_STRNDUP /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FILE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_TERMIOS_H /* Define to 1 if you have the `uname' function. */ #undef HAVE_UNAME /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if the system has the `__builtin_bswap32' built-in function */ #undef HAVE___BUILTIN_BSWAP32 /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Use custom prog name */ #undef PROG_NAME /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* avoid OpenSSL entirely, use libgcrypt instead (this can't read *.pub files, though.) */ #undef TGL_AVOID_OPENSSL /* use json */ #undef USE_JSON /* use lua */ #undef USE_LUA /* use python */ #undef USE_PYTHON /* fixed for correct valgrind work */ #undef VALGRIND_FIXES /* Define to `int' if doesn't define. */ #undef gid_t /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif /* Define to rpl_malloc if the replacement function should be used. */ #undef malloc /* Define to rpl_realloc if the replacement function should be used. */ #undef realloc /* Define to `unsigned int' if does not define. */ #undef size_t /* Define to `int' if doesn't define. */ #undef uid_t ================================================ FILE: config.sample ================================================ # This is an empty config file # Feel free to put something here default_profile = "binlog"; test_dc1 = { config_directory = ".telegram/test_dc1"; test = true; msg_num = true; }; binlog = { config_directory = ".telegram/binlog"; test = false; msg_num = true; log_level = 2; }; binlog_mts = { config_directory = ".telegram/binlog_mts"; test = false; msg_num = true; log_level = 2; }; mega = { config_directory = ".telegram/mega"; test = false; msg_num = true; log_level = 2; }; new = { config_directory = ".telegram/new"; test = false; msg_num = true; }; production = { config_directory = ".telegram/production"; test = false; msg_num = true; }; test = { config_directory = ".telegram/test"; test = true; msg_num = true; }; test1 = { config_directory = ".telegram/test1"; msg_num = true; }; test2 = { config_directory = ".telegram/test2"; msg_num = true; pfs_enabled = true; }; ================================================ FILE: configure ================================================ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for telegram-cli 1.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='telegram-cli' PACKAGE_TARNAME='telegram-cli' PACKAGE_VERSION='1.0' PACKAGE_STRING='telegram-cli 1.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_unique_file="config.h.in" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS EXTRA_LIBS LIBOBJS PYTHON_CFLAGS PYTHON_LIBS PYTHON_FOUND PYTHON_LIB PYTHON_INCLUDE_DIR PYTHON_BIN LUA_LIB LUA_INCLUDE pkgluaexecdir luaexecdir pkgluadir luadir LUA_EXEC_PREFIX LUA_PREFIX LUA_PLATFORM LUA_SHORT_VERSION LUA_VERSION LUA OPENSSL_LDFLAGS OPENSSL_LIBS OPENSSL_INCLUDES PKG_CONFIG EGREP GREP CPP OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_openssl with_openssl with_zlib enable_libconfig enable_extf enable_liblua enable_python enable_json with_progname enable_valgrind ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP LUA LUA_INCLUDE LUA_LIB' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # 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 telegram-cli 1.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/telegram-cli] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of telegram-cli 1.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-openssl disables OpenSSL, and don't link against it (this can't read *.pub files, though.) --enable-libconfig/--disable-libconfig --enable-extf/--disable-extf --enable-liblua/--disable-liblua --enable-python/--disable-python --enable-json/--disable-json --enable-valgrind/--disable-valgrind Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-openssl=DIR root of the OpenSSL directory --with-zlib=DIR root directory path of zlib installation [defaults to /usr/local or /usr if not found in /usr/local] --without-zlib to disable zlib usage completely --with-progname= Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor LUA The Lua interpreter, e.g. /usr/bin/lua5.1 LUA_INCLUDE The Lua includes, e.g. -I/usr/include/lua5.1 LUA_LIB The Lua library, e.g. -llua5.1 Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF telegram-cli configure 1.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" 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_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { 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>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # 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; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" 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_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { 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; } && { ac_try='./conftest$ac_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 : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func 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 telegram-cli $as_me 1.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue 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 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi 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. 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 [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" # =========================================================================== # 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/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 # Copyright (c) 2013 Reuben Thomas # # 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 . # # 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 21 # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_python.html # =========================================================================== # # SYNOPSIS # # AX_PYTHON # # DESCRIPTION # # This macro does a complete Python development environment check. # # It recurses through several python versions (from 2.1 to 2.6 in this # version), looking for an executable. When it finds an executable, it # looks to find the header files and library. # # It sets PYTHON_BIN to the name of the python executable, # PYTHON_INCLUDE_DIR to the directory holding the header files, and # PYTHON_LIB to the name of the Python library. # # This macro calls AC_SUBST on PYTHON_BIN (via AC_CHECK_PROG), # PYTHON_INCLUDE_DIR and PYTHON_LIB. # # LICENSE # # Copyright (c) 2008 Michael Tindal # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # 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 14 # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_check_openssl.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]]) # # DESCRIPTION # # Look for OpenSSL in a number of default spots, or in a user-selected # spot (via --with-openssl). Sets # # OPENSSL_INCLUDES to the include directives required # OPENSSL_LIBS to the -l directives required # OPENSSL_LDFLAGS to the -L or -R flags required # # and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately # # This macro sets OPENSSL_INCLUDES such that source files should use the # openssl/ directory in include directives: # # #include # # LICENSE # # Copyright (c) 2009,2010 Zmanda Inc. # Copyright (c) 2009,2010 Dustin J. Mitchell # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 8 # This is what autoupdate's m4 run will expand. It fires # the warning (with _au_warn_XXX), outputs it into the # updated configure.ac (with AC_DIAGNOSE), and then outputs # the replacement expansion. # This is an auxiliary macro that is also run when # autoupdate runs m4. It simply calls m4_warning, but # we need a wrapper so that each warning is emitted only # once. We break the quoting in m4_warning's argument in # order to expand this macro's arguments, not AU_DEFUN's. # Finally, this is the expansion that is picked up by # autoconf. It tells the user to run autoupdate, and # then outputs the replacement expansion. We do not care # about autoupdate's warning because that contains # information on what to do *after* running autoupdate. # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_check_zlib.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_ZLIB([action-if-found], [action-if-not-found]) # # DESCRIPTION # # This macro searches for an installed zlib library. If nothing was # specified when calling configure, it searches first in /usr/local and # then in /usr, /opt/local and /sw. If the --with-zlib=DIR is specified, # it will try to find it in DIR/include/zlib.h and DIR/lib/libz.a. If # --without-zlib is specified, the library is not searched at all. # # If either the header file (zlib.h) or the library (libz) is not found, # shell commands 'action-if-not-found' is run. If 'action-if-not-found' is # not specified, the configuration exits on error, asking for a valid zlib # installation directory or --without-zlib. # # If both header file and library are found, shell commands # 'action-if-found' is run. If 'action-if-found' is not specified, the # default action appends '-I${ZLIB_HOME}/include' to CPFLAGS, appends # '-L$ZLIB_HOME}/lib' to LDFLAGS, prepends '-lz' to LIBS, and calls # AC_DEFINE(HAVE_LIBZ). You should use autoheader to include a definition # for this symbol in a config.h file. Sample usage in a C/C++ source is as # follows: # # #ifdef HAVE_LIBZ # #include # #endif /* HAVE_LIBZ */ # # LICENSE # # Copyright (c) 2008 Loic Dachary # Copyright (c) 2010 Bastien Chevreux # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # 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 14 # This is what autoupdate's m4 run will expand. It fires # the warning (with _au_warn_XXX), outputs it into the # updated configure.ac (with AC_DIAGNOSE), and then outputs # the replacement expansion. # This is an auxiliary macro that is also run when # autoupdate runs m4. It simply calls m4_warning, but # we need a wrapper so that each warning is emitted only # once. We break the quoting in m4_warning's argument in # order to expand this macro's arguments, not AU_DEFUN's. # Finally, this is the expansion that is picked up by # autoconf. It tells the user to run autoupdate, and # then outputs the replacement expansion. We do not care # about autoupdate's warning because that contains # information on what to do *after* running autoupdate. # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_gcc_builtin.html # =========================================================================== # # SYNOPSIS # # AX_GCC_BUILTIN(BUILTIN) # # DESCRIPTION # # This macro checks if the compiler supports one of GCC's built-in # functions; many other compilers also provide those same built-ins. # # The BUILTIN parameter is the name of the built-in function. # # If BUILTIN is supported define HAVE_. Keep in mind that since # builtins usually start with two underscores they will be copied over # into the HAVE_ definition (e.g. HAVE___BUILTIN_EXPECT for # __builtin_expect()). # # The macro caches its result in the ax_cv_have_ variable (e.g. # ax_cv_have___builtin_expect). # # The macro currently supports the following built-in functions: # # __builtin_assume_aligned # __builtin_bswap32 # __builtin_bswap64 # __builtin_choose_expr # __builtin___clear_cache # __builtin_clrsb # __builtin_clrsbl # __builtin_clrsbll # __builtin_clz # __builtin_clzl # __builtin_clzll # __builtin_complex # __builtin_constant_p # __builtin_ctz # __builtin_ctzl # __builtin_ctzll # __builtin_expect # __builtin_ffs # __builtin_ffsl # __builtin_ffsll # __builtin_fpclassify # __builtin_huge_val # __builtin_huge_valf # __builtin_huge_vall # __builtin_inf # __builtin_infd128 # __builtin_infd32 # __builtin_infd64 # __builtin_inff # __builtin_infl # __builtin_isinf_sign # __builtin_nan # __builtin_nand128 # __builtin_nand32 # __builtin_nand64 # __builtin_nanf # __builtin_nanl # __builtin_nans # __builtin_nansf # __builtin_nansl # __builtin_object_size # __builtin_parity # __builtin_parityl # __builtin_parityll # __builtin_popcount # __builtin_popcountl # __builtin_popcountll # __builtin_powi # __builtin_powif # __builtin_powil # __builtin_prefetch # __builtin_trap # __builtin_types_compatible_p # __builtin_unreachable # # Unsuppored built-ins will be tested with an empty parameter set and the # result of the check might be wrong or meaningless so use with care. # # LICENSE # # Copyright (c) 2013 Gabriele Svelto # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 2 # Checks for programs. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" 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_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 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. */ int main () { ; 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" # 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 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: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" 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_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $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 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "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 rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $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" 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; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done 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 compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi 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 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 ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" 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_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $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 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # BSD locations for headers and libraries from packages, Linux locations for self-compiled stuff. CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" # Checks for libraries. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 $as_echo_n "checking for library containing clock_gettime... " >&6; } if ${ac_cv_search_clock_gettime+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char clock_gettime (); int main () { return clock_gettime (); ; return 0; } _ACEOF for ac_lib in '' rt; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_clock_gettime=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_clock_gettime+:} false; then : break fi done if ${ac_cv_search_clock_gettime+:} false; then : else ac_cv_search_clock_gettime=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 $as_echo "$ac_cv_search_clock_gettime" >&6; } ac_res=$ac_cv_search_clock_gettime if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing backtrace" >&5 $as_echo_n "checking for library containing backtrace... " >&6; } if ${ac_cv_search_backtrace+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char backtrace (); int main () { return backtrace (); ; return 0; } _ACEOF for ac_lib in '' execinfo; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_backtrace=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_backtrace+:} false; then : break fi done if ${ac_cv_search_backtrace+:} false; then : else ac_cv_search_backtrace=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_backtrace" >&5 $as_echo "$ac_cv_search_backtrace" >&6; } ac_res=$ac_cv_search_backtrace if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for event_base_new in -levent" >&5 $as_echo_n "checking for event_base_new in -levent... " >&6; } if ${ac_cv_lib_event_event_base_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-levent $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char event_base_new (); int main () { return event_base_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_event_event_base_new=yes else ac_cv_lib_event_event_base_new=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_event_event_base_new" >&5 $as_echo "$ac_cv_lib_event_event_base_new" >&6; } if test "x$ac_cv_lib_event_event_base_new" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBEVENT 1 _ACEOF LIBS="-levent $LIBS" else as_fn_error $? "no libevent found" "$LINENO" 5 fi EVENT_VER="" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : 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 $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_header_mongrel "$LINENO" "event2/event.h" "ac_cv_header_event2_event_h" "$ac_includes_default" if test "x$ac_cv_header_event2_event_h" = xyes; then : $as_echo "#define EVENT_V2 1" >>confdefs.h else ac_fn_c_check_header_mongrel "$LINENO" "event.h" "ac_cv_header_event_h" "$ac_includes_default" if test "x$ac_cv_header_event_h" = xyes; then : $as_echo "#define EVENT_V1 1" >>confdefs.h else as_fn_error $? "no libevent found" "$LINENO" 5 fi fi EXTRA_LIBS="" # OPENSSL_INCLUDES to the include directives required # OPENSSL_LIBS to the -l directives required # OPENSSL_LDFLAGS to the -L or -R flags required # Check whether --enable-openssl was given. if test "${enable_openssl+set}" = set; then : enableval=$enable_openssl; if test "x$enableval" = "xno" ; then $as_echo "#define TGL_AVOID_OPENSSL 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcry_mpi_snatch in -lgcrypt" >&5 $as_echo_n "checking for gcry_mpi_snatch in -lgcrypt... " >&6; } if ${ac_cv_lib_gcrypt_gcry_mpi_snatch+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgcrypt $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gcry_mpi_snatch (); int main () { return gcry_mpi_snatch (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gcrypt_gcry_mpi_snatch=yes else ac_cv_lib_gcrypt_gcry_mpi_snatch=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gcrypt_gcry_mpi_snatch" >&5 $as_echo "$ac_cv_lib_gcrypt_gcry_mpi_snatch" >&6; } if test "x$ac_cv_lib_gcrypt_gcry_mpi_snatch" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBGCRYPT 1 _ACEOF LIBS="-lgcrypt $LIBS" else as_fn_error $? "\"Need libgcrypt >= 1.60\"" "$LINENO" 5 fi else # Don't be annoying, so don't inform the user about --disable-openssl found=false # Check whether --with-openssl was given. if test "${with_openssl+set}" = set; then : withval=$with_openssl; case "$withval" in "" | y | ye | yes | n | no) as_fn_error $? "Invalid --with-openssl value" "$LINENO" 5 ;; *) ssldirs="$withval" ;; esac else # if pkg-config is installed and openssl has installed a .pc file, # then use that information and don't search ssldirs # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$PKG_CONFIG" != x""; then OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null` if test $? = 0; then OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null` OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null` found=true fi fi # no such luck; use some default ssldirs if ! $found; then ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" fi fi # note that we #include , so the OpenSSL headers have to be in # an 'openssl' subdirectory if ! $found; then OPENSSL_INCLUDES= for ssldir in $ssldirs; do { $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl/ssl.h in $ssldir" >&5 $as_echo_n "checking for openssl/ssl.h in $ssldir... " >&6; } if test -f "$ssldir/include/openssl/ssl.h"; then OPENSSL_INCLUDES="-I$ssldir/include" OPENSSL_LDFLAGS="-L$ssldir/lib" OPENSSL_LIBS="-lssl -lcrypto" found=true { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } break else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi done # if the file wasn't found, well, go ahead and try the link anyway -- maybe # it will just work! fi # try the preprocessor and linker with our new flags, # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiling and linking against OpenSSL works" >&5 $as_echo_n "checking whether compiling and linking against OpenSSL works... " >&6; } echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \ "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&5 save_LIBS="$LIBS" save_LDFLAGS="$LDFLAGS" save_CPPFLAGS="$CPPFLAGS" LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" LIBS="$OPENSSL_LIBS $LIBS" CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { SSL_new(NULL) ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "No openssl found." "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" fi else found=false # Check whether --with-openssl was given. if test "${with_openssl+set}" = set; then : withval=$with_openssl; case "$withval" in "" | y | ye | yes | n | no) as_fn_error $? "Invalid --with-openssl value" "$LINENO" 5 ;; *) ssldirs="$withval" ;; esac else # if pkg-config is installed and openssl has installed a .pc file, # then use that information and don't search ssldirs # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$PKG_CONFIG" != x""; then OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null` if test $? = 0; then OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null` OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null` found=true fi fi # no such luck; use some default ssldirs if ! $found; then ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" fi fi # note that we #include , so the OpenSSL headers have to be in # an 'openssl' subdirectory if ! $found; then OPENSSL_INCLUDES= for ssldir in $ssldirs; do { $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl/ssl.h in $ssldir" >&5 $as_echo_n "checking for openssl/ssl.h in $ssldir... " >&6; } if test -f "$ssldir/include/openssl/ssl.h"; then OPENSSL_INCLUDES="-I$ssldir/include" OPENSSL_LDFLAGS="-L$ssldir/lib" OPENSSL_LIBS="-lssl -lcrypto" found=true { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } break else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi done # if the file wasn't found, well, go ahead and try the link anyway -- maybe # it will just work! fi # try the preprocessor and linker with our new flags, # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiling and linking against OpenSSL works" >&5 $as_echo_n "checking whether compiling and linking against OpenSSL works... " >&6; } echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \ "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&5 save_LIBS="$LIBS" save_LDFLAGS="$LDFLAGS" save_CPPFLAGS="$CPPFLAGS" LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" LIBS="$OPENSSL_LIBS $LIBS" CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { SSL_new(NULL) ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "No openssl found. With --disable-openssl, libtgl will use libgcrypt instead." "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" fi # # Handle user hints # { $as_echo "$as_me:${as_lineno-$LINENO}: checking if zlib is wanted" >&5 $as_echo_n "checking if zlib is wanted... " >&6; } zlib_places="/usr/local /usr /opt/local /sw" # Check whether --with-zlib was given. if test "${with_zlib+set}" = set; then : withval=$with_zlib; if test "$withval" != no ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } if test -d "$withval" then zlib_places="$withval $zlib_places" else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Sorry, $withval does not exist, checking usual places" >&5 $as_echo "$as_me: WARNING: Sorry, $withval does not exist, checking usual places" >&2;} fi else zlib_places= { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # # Locate zlib, if wanted # if test -n "${zlib_places}" then # check the user supplied or any other more or less 'standard' place: # Most UNIX systems : /usr/local and /usr # MacPorts / Fink on OSX : /opt/local respectively /sw for ZLIB_HOME in ${zlib_places} ; do if test -f "${ZLIB_HOME}/include/zlib.h"; then break; fi ZLIB_HOME="" done ZLIB_OLD_LDFLAGS=$LDFLAGS ZLIB_OLD_CPPFLAGS=$CPPFLAGS if test -n "${ZLIB_HOME}"; then LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateEnd in -lz" >&5 $as_echo_n "checking for inflateEnd in -lz... " >&6; } if ${ac_cv_lib_z_inflateEnd+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inflateEnd (); int main () { return inflateEnd (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_inflateEnd=yes else ac_cv_lib_z_inflateEnd=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_inflateEnd" >&5 $as_echo "$ac_cv_lib_z_inflateEnd" >&6; } if test "x$ac_cv_lib_z_inflateEnd" = xyes; then : zlib_cv_libz=yes else zlib_cv_libz=no fi ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes; then : zlib_cv_zlib_h=yes else zlib_cv_zlib_h=no fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "$zlib_cv_libz" = "yes" && test "$zlib_cv_zlib_h" = "yes" then # # If both library and header were found, action-if-found # CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" LIBS="-lz $LIBS" $as_echo "#define HAVE_LIBZ 1" >>confdefs.h else # # If either header or library was not found, action-if-not-found # as_fn_error $? "No zlib found" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_save_prompt in -lreadline" >&5 $as_echo_n "checking for rl_save_prompt in -lreadline... " >&6; } if ${ac_cv_lib_readline_rl_save_prompt+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lreadline $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char rl_save_prompt (); int main () { return rl_save_prompt (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_readline_rl_save_prompt=yes else ac_cv_lib_readline_rl_save_prompt=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_rl_save_prompt" >&5 $as_echo "$ac_cv_lib_readline_rl_save_prompt" >&6; } if test "x$ac_cv_lib_readline_rl_save_prompt" = xyes; then : EXTRA_LIBS="${EXTRA_LIBS} -lreadline" ; else as_fn_error $? "no libreadline found" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libconfig" >&5 $as_echo_n "checking for libconfig... " >&6; } # Check whether --enable-libconfig was given. if test "${enable_libconfig+set}" = set; then : enableval=$enable_libconfig; if test "x$enableval" = "xno" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 $as_echo "disabled" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5 $as_echo "enabled" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for config_init in -lconfig" >&5 $as_echo_n "checking for config_init in -lconfig... " >&6; } if ${ac_cv_lib_config_config_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lconfig $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char config_init (); int main () { return config_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_config_config_init=yes else ac_cv_lib_config_config_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_config_config_init" >&5 $as_echo "$ac_cv_lib_config_config_init" >&6; } if test "x$ac_cv_lib_config_config_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBCONFIG 1 _ACEOF LIBS="-lconfig $LIBS" else as_fn_error $? "No libconfig found. Try --disable-libconfig" "$LINENO" 5 fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5 $as_echo "enabled" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for config_init in -lconfig" >&5 $as_echo_n "checking for config_init in -lconfig... " >&6; } if ${ac_cv_lib_config_config_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lconfig $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char config_init (); int main () { return config_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_config_config_init=yes else ac_cv_lib_config_config_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_config_config_init" >&5 $as_echo "$ac_cv_lib_config_config_init" >&6; } if test "x$ac_cv_lib_config_config_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBCONFIG 1 _ACEOF LIBS="-lconfig $LIBS" else as_fn_error $? "No libconfig found. Try --disable-libconfig" "$LINENO" 5 fi fi # Check whether --enable-extf was given. if test "${enable_extf+set}" = set; then : enableval=$enable_extf; if test "x$enableval" = "xno" ; then $as_echo "#define DISABLE_EXTF 1" >>confdefs.h fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for liblua" >&5 $as_echo_n "checking for liblua... " >&6; } # Check whether --enable-liblua was given. if test "${enable_liblua+set}" = set; then : enableval=$enable_liblua; if test "x$enableval" = "xno" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 $as_echo "disabled" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5 $as_echo "enabled" >&6; } if test "x$LUA" = 'x'; then : for ac_prog in lua lua5.2 lua52 lua5.1 lua51 lua50 do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_LUA+:} false; then : $as_echo_n "(cached) " >&6 else case $LUA in [\\/]* | ?:[\\/]*) ac_cv_path_LUA="$LUA" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_LUA="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi LUA=$ac_cv_path_LUA if test -n "$LUA"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LUA" >&5 $as_echo "$LUA" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$LUA" && break done test -n "$LUA" || LUA=":" fi ax_display_LUA='lua' { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $LUA is a Lua interpreter" >&5 $as_echo_n "checking if $LUA is a Lua interpreter... " >&6; } if $LUA -e "print('Hello ' .. _VERSION .. '!')" &>/dev/null; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "not a Lua interpreter" "$LINENO" 5 fi if test "x$LUA" = 'x:'; then : as_fn_error $? "No lua found. Try --disable-liblua" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ax_display_LUA version" >&5 $as_echo_n "checking for $ax_display_LUA version... " >&6; } if ${ax_cv_lua_version+:} false; then : $as_echo_n "(cached) " >&6 else ax_cv_lua_version=`$LUA -e "print(_VERSION)" | \ sed "s|^Lua \(.*\)|\1|" | \ grep -E -o "^[0-9]+\.[0-9]+"` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_lua_version" >&5 $as_echo "$ax_cv_lua_version" >&6; } if test "x$ax_cv_lua_version" = 'x'; then : as_fn_error $? "invalid Lua version number" "$LINENO" 5 fi LUA_VERSION=$ax_cv_lua_version LUA_SHORT_VERSION=`echo "$LUA_VERSION" | sed 's|\.||'` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ax_display_LUA platform" >&5 $as_echo_n "checking for $ax_display_LUA platform... " >&6; } if ${ax_cv_lua_platform+:} false; then : $as_echo_n "(cached) " >&6 else ax_cv_lua_platform=`$LUA -e "print('unknown')"` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_lua_platform" >&5 $as_echo "$ax_cv_lua_platform" >&6; } LUA_PLATFORM=$ax_cv_lua_platform LUA_PREFIX='${prefix}' LUA_EXEC_PREFIX='${exec_prefix}' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ax_display_LUA script directory" >&5 $as_echo_n "checking for $ax_display_LUA script directory... " >&6; } if ${ax_cv_lua_luadir+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$prefix" = 'xNONE'; then : ax_lua_prefix=$ac_default_prefix else ax_lua_prefix=$prefix fi ax_cv_lua_luadir="$LUA_PREFIX/share/lua/$LUA_VERSION" ax_lua_prefixed_path='' _ax_package_paths=`$LUA -e 'print(package.path)' 2>/dev/null | sed 's|;|\n|g'` for _ax_package_path in $_ax_package_paths; do _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 _ax_package_path=$_ax_reassembled if echo "$_ax_package_path" | grep "^$ax_lua_prefix" >/dev/null; then ax_lua_prefixed_path=$_ax_package_path break fi done if test "x$ax_lua_prefixed_path" != 'x'; then : _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,"` fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_lua_luadir" >&5 $as_echo "$ax_cv_lua_luadir" >&6; } luadir=$ax_cv_lua_luadir pkgluadir=\${luadir}/$PACKAGE { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ax_display_LUA module directory" >&5 $as_echo_n "checking for $ax_display_LUA module directory... " >&6; } if ${ax_cv_lua_luaexecdir+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$exec_prefix" = 'xNONE'; then : ax_lua_exec_prefix=$ax_lua_prefix else ax_lua_exec_prefix=$exec_prefix fi ax_cv_lua_luaexecdir="$LUA_EXEC_PREFIX/lib/lua/$LUA_VERSION" ax_lua_prefixed_path='' _ax_package_paths=`$LUA -e 'print(package.cpathd)' 2>/dev/null | sed 's|;|\n|g'` for _ax_package_path in $_ax_package_paths; do _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 _ax_package_path=$_ax_reassembled if echo "$_ax_package_path" | grep "^$ax_lua_exec_prefix" >/dev/null; then ax_lua_prefixed_path=$_ax_package_path break fi done if test "x$ax_lua_prefixed_path" != 'x'; then : _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,"` fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_lua_luaexecdir" >&5 $as_echo "$ax_cv_lua_luaexecdir" >&6; } luaexecdir=$ax_cv_lua_luaexecdir pkgluaexecdir=\${luaexecdir}/$PACKAGE { $as_echo "$as_me:${as_lineno-$LINENO}: checking if LUA_VERSION is defined" >&5 $as_echo_n "checking if LUA_VERSION is defined... " >&6; } if test "x$LUA_VERSION" != 'x'; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "cannot check Lua headers without knowing LUA_VERSION" "$LINENO" 5 fi LUA_SHORT_VERSION=`echo "$LUA_VERSION" | sed 's|\.||'` _ax_lua_saved_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS $LUA_INCLUDE" for ac_header in lua.h lualib.h lauxlib.h luaconf.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done CPPFLAGS=$_ax_lua_saved_cppflags if test "x$LUA_INCLUDE" = 'x' && test "x$ac_cv_header_lua_h" != 'xyes'; then : for _ax_include_path in /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_VERSION \ /usr/local/include/lua$LUA_SHORT_VERSION \ ; do test ! -d "$_ax_include_path" && continue { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Lua headers in" >&5 $as_echo_n "checking for Lua headers in... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_ax_include_path" >&5 $as_echo "$_ax_include_path" >&6; } { ac_cv_header_lua_h=; unset ac_cv_header_lua_h;} { ac_cv_header_lualib_h=; unset ac_cv_header_lualib_h;} { ac_cv_header_lauxlib_h=; unset ac_cv_header_lauxlib_h;} { ac_cv_header_luaconf_h=; unset ac_cv_header_luaconf_h;} _ax_lua_saved_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS -I$_ax_include_path" for ac_header in lua.h lualib.h lauxlib.h luaconf.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done CPPFLAGS=$_ax_lua_saved_cppflags if test "x$ac_cv_header_lua_h" = 'xyes'; then : LUA_INCLUDE="-I$_ax_include_path" break fi done fi if test "x$ac_cv_header_lua_h" = 'xyes'; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Lua header version" >&5 $as_echo_n "checking for Lua header version... " >&6; } if ${ax_cv_lua_header_version+:} false; then : $as_echo_n "(cached) " >&6 else _ax_lua_saved_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS $LUA_INCLUDE" if test "$cross_compiling" = yes; then : { { $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 test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main(int argc, char ** argv) { if(argc > 1) printf("%s", LUA_VERSION); exit(EXIT_SUCCESS); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ax_cv_lua_header_version=`./conftest$EXEEXT p | \ sed "s|^Lua \(.*\)|\1|" | \ grep -E -o "^[0-9]+\.[0-9]+"` else ax_cv_lua_header_version='unknown' fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi CPPFLAGS=$_ax_lua_saved_cppflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_lua_header_version" >&5 $as_echo "$ax_cv_lua_header_version" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Lua header version matches $LUA_VERSION" >&5 $as_echo_n "checking if Lua header version matches $LUA_VERSION... " >&6; } if test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } ax_header_version_match='yes' else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ax_header_version_match='no' fi fi if test "x$ax_header_version_match" != 'xyes' && test "x$LUA_INCLUDE" != 'x'; then : as_fn_error $? "cannot find headers for specified LUA_INCLUDE" "$LINENO" 5 fi if test "x$ax_header_version_match" = 'xyes'; then : else as_fn_error $? "No lua headers found. Try --disable-liblua" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if LUA_VERSION is defined" >&5 $as_echo_n "checking if LUA_VERSION is defined... " >&6; } if test "x$LUA_VERSION" != 'x'; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "cannot check Lua libs without knowing LUA_VERSION" "$LINENO" 5 fi if test "x$LUA_LIB" != 'x'; then : _ax_lua_saved_libs=$LIBS LIBS="$LIBS $LUA_LIB" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing lua_load" >&5 $as_echo_n "checking for library containing lua_load... " >&6; } if ${ac_cv_search_lua_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char lua_load (); int main () { return lua_load (); ; return 0; } _ACEOF for ac_lib in '' ; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_lua_load=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_lua_load+:} false; then : break fi done if ${ac_cv_search_lua_load+:} false; then : else ac_cv_search_lua_load=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_lua_load" >&5 $as_echo "$ac_cv_search_lua_load" >&6; } ac_res=$ac_cv_search_lua_load if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" _ax_found_lua_libs='yes' else _ax_found_lua_libs='no' fi LIBS=$_ax_lua_saved_libs if test "x$_ax_found_lua_libs" != 'xyes'; then : as_fn_error $? "cannot find libs for specified LUA_LIB" "$LINENO" 5 fi else _ax_lua_extra_libs='' _ax_lua_saved_libs=$LIBS LIBS="$LIBS $LUA_LIB" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing exp" >&5 $as_echo_n "checking for library containing exp... " >&6; } if ${ac_cv_search_exp+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char exp (); int main () { return exp (); ; return 0; } _ACEOF for ac_lib in '' m; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_exp=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_exp+:} false; then : break fi done if ${ac_cv_search_exp+:} false; then : else ac_cv_search_exp=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_exp" >&5 $as_echo "$ac_cv_search_exp" >&6; } ac_res=$ac_cv_search_exp if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi LIBS=$_ax_lua_saved_libs if test "x$ac_cv_search_exp" != 'xno' && test "x$ac_cv_search_exp" != 'xnone required'; then : _ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_exp" fi if test "x$ac_cv_search_dlopen" != 'xno' && test "x$ac_cv_search_dlopen" != 'xnone required'; then : _ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_dlopen" fi _ax_lua_saved_libs=$LIBS LIBS="$LIBS $LUA_LIB" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing lua_load" >&5 $as_echo_n "checking for library containing lua_load... " >&6; } if ${ac_cv_search_lua_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char lua_load (); int main () { return lua_load (); ; return 0; } _ACEOF for ac_lib in '' lua$LUA_VERSION \ lua$LUA_SHORT_VERSION \ lua-$LUA_VERSION \ lua-$LUA_SHORT_VERSION \ lua; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $_ax_lua_extra_libs $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_lua_load=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_lua_load+:} false; then : break fi done if ${ac_cv_search_lua_load+:} false; then : else ac_cv_search_lua_load=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_lua_load" >&5 $as_echo "$ac_cv_search_lua_load" >&6; } ac_res=$ac_cv_search_lua_load if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" _ax_found_lua_libs='yes' else _ax_found_lua_libs='no' fi LIBS=$_ax_lua_saved_libs if test "x$ac_cv_search_lua_load" != 'xno' && test "x$ac_cv_search_lua_load" != 'xnone required'; then : LUA_LIB="$ac_cv_search_lua_load $_ax_lua_extra_libs" fi fi if test "x$_ax_found_lua_libs" = 'xyes'; then : else as_fn_error $? "No lua libs found. Try --disable-liblua" "$LINENO" 5 fi EXTRA_LIBS="${EXTRA_LIBS} ${LUA_LIB}" ; CPPFLAGS="${CPPFLAGS} ${LUA_INCLUDE}" ; $as_echo "#define USE_LUA 1" >>confdefs.h fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5 $as_echo "enabled" >&6; } if test "x$LUA" = 'x'; then : for ac_prog in lua lua5.2 lua52 lua5.1 lua51 lua50 do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_LUA+:} false; then : $as_echo_n "(cached) " >&6 else case $LUA in [\\/]* | ?:[\\/]*) ac_cv_path_LUA="$LUA" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_LUA="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi LUA=$ac_cv_path_LUA if test -n "$LUA"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LUA" >&5 $as_echo "$LUA" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$LUA" && break done test -n "$LUA" || LUA=":" fi ax_display_LUA='lua' { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $LUA is a Lua interpreter" >&5 $as_echo_n "checking if $LUA is a Lua interpreter... " >&6; } if $LUA -e "print('Hello ' .. _VERSION .. '!')" &>/dev/null; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "not a Lua interpreter" "$LINENO" 5 fi if test "x$LUA" = 'x:'; then : as_fn_error $? "No lua found. Try --disable-liblua" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ax_display_LUA version" >&5 $as_echo_n "checking for $ax_display_LUA version... " >&6; } if ${ax_cv_lua_version+:} false; then : $as_echo_n "(cached) " >&6 else ax_cv_lua_version=`$LUA -e "print(_VERSION)" | \ sed "s|^Lua \(.*\)|\1|" | \ grep -E -o "^[0-9]+\.[0-9]+"` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_lua_version" >&5 $as_echo "$ax_cv_lua_version" >&6; } if test "x$ax_cv_lua_version" = 'x'; then : as_fn_error $? "invalid Lua version number" "$LINENO" 5 fi LUA_VERSION=$ax_cv_lua_version LUA_SHORT_VERSION=`echo "$LUA_VERSION" | sed 's|\.||'` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ax_display_LUA platform" >&5 $as_echo_n "checking for $ax_display_LUA platform... " >&6; } if ${ax_cv_lua_platform+:} false; then : $as_echo_n "(cached) " >&6 else ax_cv_lua_platform=`$LUA -e "print('unknown')"` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_lua_platform" >&5 $as_echo "$ax_cv_lua_platform" >&6; } LUA_PLATFORM=$ax_cv_lua_platform LUA_PREFIX='${prefix}' LUA_EXEC_PREFIX='${exec_prefix}' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ax_display_LUA script directory" >&5 $as_echo_n "checking for $ax_display_LUA script directory... " >&6; } if ${ax_cv_lua_luadir+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$prefix" = 'xNONE'; then : ax_lua_prefix=$ac_default_prefix else ax_lua_prefix=$prefix fi ax_cv_lua_luadir="$LUA_PREFIX/share/lua/$LUA_VERSION" ax_lua_prefixed_path='' _ax_package_paths=`$LUA -e 'print(package.path)' 2>/dev/null | sed 's|;|\n|g'` for _ax_package_path in $_ax_package_paths; do _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 _ax_package_path=$_ax_reassembled if echo "$_ax_package_path" | grep "^$ax_lua_prefix" >/dev/null; then ax_lua_prefixed_path=$_ax_package_path break fi done if test "x$ax_lua_prefixed_path" != 'x'; then : _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,"` fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_lua_luadir" >&5 $as_echo "$ax_cv_lua_luadir" >&6; } luadir=$ax_cv_lua_luadir pkgluadir=\${luadir}/$PACKAGE { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ax_display_LUA module directory" >&5 $as_echo_n "checking for $ax_display_LUA module directory... " >&6; } if ${ax_cv_lua_luaexecdir+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$exec_prefix" = 'xNONE'; then : ax_lua_exec_prefix=$ax_lua_prefix else ax_lua_exec_prefix=$exec_prefix fi ax_cv_lua_luaexecdir="$LUA_EXEC_PREFIX/lib/lua/$LUA_VERSION" ax_lua_prefixed_path='' _ax_package_paths=`$LUA -e 'print(package.cpathd)' 2>/dev/null | sed 's|;|\n|g'` for _ax_package_path in $_ax_package_paths; do _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 _ax_package_path=$_ax_reassembled if echo "$_ax_package_path" | grep "^$ax_lua_exec_prefix" >/dev/null; then ax_lua_prefixed_path=$_ax_package_path break fi done if test "x$ax_lua_prefixed_path" != 'x'; then : _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,"` fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_lua_luaexecdir" >&5 $as_echo "$ax_cv_lua_luaexecdir" >&6; } luaexecdir=$ax_cv_lua_luaexecdir pkgluaexecdir=\${luaexecdir}/$PACKAGE { $as_echo "$as_me:${as_lineno-$LINENO}: checking if LUA_VERSION is defined" >&5 $as_echo_n "checking if LUA_VERSION is defined... " >&6; } if test "x$LUA_VERSION" != 'x'; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "cannot check Lua headers without knowing LUA_VERSION" "$LINENO" 5 fi LUA_SHORT_VERSION=`echo "$LUA_VERSION" | sed 's|\.||'` _ax_lua_saved_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS $LUA_INCLUDE" for ac_header in lua.h lualib.h lauxlib.h luaconf.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done CPPFLAGS=$_ax_lua_saved_cppflags if test "x$LUA_INCLUDE" = 'x' && test "x$ac_cv_header_lua_h" != 'xyes'; then : for _ax_include_path in /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_VERSION \ /usr/local/include/lua$LUA_SHORT_VERSION \ ; do test ! -d "$_ax_include_path" && continue { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Lua headers in" >&5 $as_echo_n "checking for Lua headers in... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_ax_include_path" >&5 $as_echo "$_ax_include_path" >&6; } { ac_cv_header_lua_h=; unset ac_cv_header_lua_h;} { ac_cv_header_lualib_h=; unset ac_cv_header_lualib_h;} { ac_cv_header_lauxlib_h=; unset ac_cv_header_lauxlib_h;} { ac_cv_header_luaconf_h=; unset ac_cv_header_luaconf_h;} _ax_lua_saved_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS -I$_ax_include_path" for ac_header in lua.h lualib.h lauxlib.h luaconf.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done CPPFLAGS=$_ax_lua_saved_cppflags if test "x$ac_cv_header_lua_h" = 'xyes'; then : LUA_INCLUDE="-I$_ax_include_path" break fi done fi if test "x$ac_cv_header_lua_h" = 'xyes'; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Lua header version" >&5 $as_echo_n "checking for Lua header version... " >&6; } if ${ax_cv_lua_header_version+:} false; then : $as_echo_n "(cached) " >&6 else _ax_lua_saved_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS $LUA_INCLUDE" if test "$cross_compiling" = yes; then : { { $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 test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main(int argc, char ** argv) { if(argc > 1) printf("%s", LUA_VERSION); exit(EXIT_SUCCESS); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ax_cv_lua_header_version=`./conftest$EXEEXT p | \ sed "s|^Lua \(.*\)|\1|" | \ grep -E -o "^[0-9]+\.[0-9]+"` else ax_cv_lua_header_version='unknown' fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi CPPFLAGS=$_ax_lua_saved_cppflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_lua_header_version" >&5 $as_echo "$ax_cv_lua_header_version" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Lua header version matches $LUA_VERSION" >&5 $as_echo_n "checking if Lua header version matches $LUA_VERSION... " >&6; } if test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } ax_header_version_match='yes' else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ax_header_version_match='no' fi fi if test "x$ax_header_version_match" != 'xyes' && test "x$LUA_INCLUDE" != 'x'; then : as_fn_error $? "cannot find headers for specified LUA_INCLUDE" "$LINENO" 5 fi if test "x$ax_header_version_match" = 'xyes'; then : else as_fn_error $? "No lua headers found. Try --disable-liblua" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if LUA_VERSION is defined" >&5 $as_echo_n "checking if LUA_VERSION is defined... " >&6; } if test "x$LUA_VERSION" != 'x'; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "cannot check Lua libs without knowing LUA_VERSION" "$LINENO" 5 fi if test "x$LUA_LIB" != 'x'; then : _ax_lua_saved_libs=$LIBS LIBS="$LIBS $LUA_LIB" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing lua_load" >&5 $as_echo_n "checking for library containing lua_load... " >&6; } if ${ac_cv_search_lua_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char lua_load (); int main () { return lua_load (); ; return 0; } _ACEOF for ac_lib in '' ; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_lua_load=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_lua_load+:} false; then : break fi done if ${ac_cv_search_lua_load+:} false; then : else ac_cv_search_lua_load=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_lua_load" >&5 $as_echo "$ac_cv_search_lua_load" >&6; } ac_res=$ac_cv_search_lua_load if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" _ax_found_lua_libs='yes' else _ax_found_lua_libs='no' fi LIBS=$_ax_lua_saved_libs if test "x$_ax_found_lua_libs" != 'xyes'; then : as_fn_error $? "cannot find libs for specified LUA_LIB" "$LINENO" 5 fi else _ax_lua_extra_libs='' _ax_lua_saved_libs=$LIBS LIBS="$LIBS $LUA_LIB" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing exp" >&5 $as_echo_n "checking for library containing exp... " >&6; } if ${ac_cv_search_exp+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char exp (); int main () { return exp (); ; return 0; } _ACEOF for ac_lib in '' m; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_exp=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_exp+:} false; then : break fi done if ${ac_cv_search_exp+:} false; then : else ac_cv_search_exp=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_exp" >&5 $as_echo "$ac_cv_search_exp" >&6; } ac_res=$ac_cv_search_exp if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi LIBS=$_ax_lua_saved_libs if test "x$ac_cv_search_exp" != 'xno' && test "x$ac_cv_search_exp" != 'xnone required'; then : _ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_exp" fi if test "x$ac_cv_search_dlopen" != 'xno' && test "x$ac_cv_search_dlopen" != 'xnone required'; then : _ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_dlopen" fi _ax_lua_saved_libs=$LIBS LIBS="$LIBS $LUA_LIB" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing lua_load" >&5 $as_echo_n "checking for library containing lua_load... " >&6; } if ${ac_cv_search_lua_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char lua_load (); int main () { return lua_load (); ; return 0; } _ACEOF for ac_lib in '' lua$LUA_VERSION \ lua$LUA_SHORT_VERSION \ lua-$LUA_VERSION \ lua-$LUA_SHORT_VERSION \ lua; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $_ax_lua_extra_libs $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_lua_load=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_lua_load+:} false; then : break fi done if ${ac_cv_search_lua_load+:} false; then : else ac_cv_search_lua_load=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_lua_load" >&5 $as_echo "$ac_cv_search_lua_load" >&6; } ac_res=$ac_cv_search_lua_load if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" _ax_found_lua_libs='yes' else _ax_found_lua_libs='no' fi LIBS=$_ax_lua_saved_libs if test "x$ac_cv_search_lua_load" != 'xno' && test "x$ac_cv_search_lua_load" != 'xnone required'; then : LUA_LIB="$ac_cv_search_lua_load $_ax_lua_extra_libs" fi fi if test "x$_ax_found_lua_libs" = 'xyes'; then : else as_fn_error $? "No lua libs found. Try --disable-liblua" "$LINENO" 5 fi EXTRA_LIBS="${EXTRA_LIBS} ${LUA_LIB}" ; CPPFLAGS="${CPPFLAGS} ${LUA_INCLUDE}" ; $as_echo "#define USE_LUA 1" >>confdefs.h fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for python" >&5 $as_echo_n "checking for python... " >&6; } # Check whether --enable-python was given. if test "${enable_python+set}" = set; then : enableval=$enable_python; if test "x$enableval" = "xyes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 $as_echo "disabled" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5 $as_echo "enabled" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for python build information" >&5 $as_echo_n "checking for python build information... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 $as_echo "" >&6; } for python in python3.5 python3.4 python3.3 python3.2 python3.1 python3 python2.7 python2.6 python2 python; do for ac_prog in $python do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_PYTHON_BIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$PYTHON_BIN"; then ac_cv_prog_PYTHON_BIN="$PYTHON_BIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_PYTHON_BIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi PYTHON_BIN=$ac_cv_prog_PYTHON_BIN if test -n "$PYTHON_BIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_BIN" >&5 $as_echo "$PYTHON_BIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$PYTHON_BIN" && break done ax_python_bin=$PYTHON_BIN if test x$ax_python_bin != x; then as_ac_Lib=`$as_echo "ac_cv_lib_$ax_python_bin''_main" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -l$ax_python_bin" >&5 $as_echo_n "checking for main in -l$ax_python_bin... " >&6; } if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-l$ax_python_bin $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$as_ac_Lib=yes" else eval "$as_ac_Lib=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : ax_python_lib=$ax_python_bin else ax_python_lib=no fi if test x$ax_python_lib == xno; then as_ac_Lib=`$as_echo "ac_cv_lib_${ax_python_bin}m''_main" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -l${ax_python_bin}m" >&5 $as_echo_n "checking for main in -l${ax_python_bin}m... " >&6; } if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-l${ax_python_bin}m $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$as_ac_Lib=yes" else eval "$as_ac_Lib=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : ax_python_lib=${ax_python_bin}m else ax_python_lib=no fi fi if test x$ax_python_lib == xno; then as_ac_Lib=`$as_echo "ac_cv_lib_${ax_python_bin}mu''_main" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -l${ax_python_bin}mu" >&5 $as_echo_n "checking for main in -l${ax_python_bin}mu... " >&6; } if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-l${ax_python_bin}mu $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$as_ac_Lib=yes" else eval "$as_ac_Lib=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : ax_python_lib=${ax_python_bin}mu else ax_python_lib=no fi fi if test x$ax_python_lib != xno; then ax_python_header=`$ax_python_bin -c "from distutils.sysconfig import *; print(get_config_var('CONFINCLUDEPY'))"` if test x$ax_python_header != x; then break; fi fi fi unset ac_cv_prog_PYTHON_BIN unset PYTHON_BIN done if test x$ax_python_bin = x; then ax_python_bin=no fi if test x$ax_python_header = x; then ax_python_header=no fi if test x$ax_python_lib = x; then ax_python_lib=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: results of the Python check:" >&5 $as_echo " results of the Python check:" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: Binary: $ax_python_bin" >&5 $as_echo " Binary: $ax_python_bin" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: Library: $ax_python_lib" >&5 $as_echo " Library: $ax_python_lib" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: Include Dir: $ax_python_header" >&5 $as_echo " Include Dir: $ax_python_header" >&6; } PYTHON_FOUND=yes if test x$ax_python_header != xno; then PYTHON_INCLUDE_DIR=$ax_python_header else PYTHON_FOUND=no fi if test x$ax_python_lib != xno; then PYTHON_LIB=$ax_python_lib else PYTHON_FOUND=no fi if test $PYTHON_FOUND = no ; then as_fn_error $? "No supported python lib version found. Try --disable-python" "$LINENO" 5 else EXTRA_LIBS="${EXTRA_LIBS} -l${PYTHON_LIB}" CPPFLAGS="${CPPFLAGS} -I${PYTHON_INCLUDE_DIR}" $as_echo "#define USE_PYTHON 1" >>confdefs.h fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 $as_echo "disabled" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libjansson" >&5 $as_echo_n "checking for libjansson... " >&6; } # Check whether --enable-json was given. if test "${enable_json+set}" = set; then : enableval=$enable_json; if test "x$enableval" = "xno" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 $as_echo "disabled" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5 $as_echo "enabled" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for json_array_set_new in -ljansson" >&5 $as_echo_n "checking for json_array_set_new in -ljansson... " >&6; } if ${ac_cv_lib_jansson_json_array_set_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ljansson $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char json_array_set_new (); int main () { return json_array_set_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_jansson_json_array_set_new=yes else ac_cv_lib_jansson_json_array_set_new=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jansson_json_array_set_new" >&5 $as_echo "$ac_cv_lib_jansson_json_array_set_new" >&6; } if test "x$ac_cv_lib_jansson_json_array_set_new" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBJANSSON 1 _ACEOF LIBS="-ljansson $LIBS" else as_fn_error $? "No libjansson found. Try --disable-json" "$LINENO" 5 fi $as_echo "#define USE_JSON 1" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5 $as_echo "enabled" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for json_array_set_new in -ljansson" >&5 $as_echo_n "checking for json_array_set_new in -ljansson... " >&6; } if ${ac_cv_lib_jansson_json_array_set_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ljansson $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char json_array_set_new (); int main () { return json_array_set_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_jansson_json_array_set_new=yes else ac_cv_lib_jansson_json_array_set_new=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jansson_json_array_set_new" >&5 $as_echo "$ac_cv_lib_jansson_json_array_set_new" >&6; } if test "x$ac_cv_lib_jansson_json_array_set_new" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBJANSSON 1 _ACEOF LIBS="-ljansson $LIBS" else as_fn_error $? "No libjansson found. Try --disable-json" "$LINENO" 5 fi $as_echo "#define USE_JSON 1" >>confdefs.h fi #check for custom prog name { $as_echo "$as_me:${as_lineno-$LINENO}: checking progname" >&5 $as_echo_n "checking progname... " >&6; } # Check whether --with-progname was given. if test "${with_progname+set}" = set; then : withval=$with_progname; if test "x$with_progname" = "xno" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: default" >&5 $as_echo "default" >&6; } elif test "x$with_progname" = "xyes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: default" >&5 $as_echo "default" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$with_progname\"" >&5 $as_echo "\"$with_progname\"" >&6; } cat >>confdefs.h <<_ACEOF #define PROG_NAME "$with_progname" _ACEOF fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: default" >&5 $as_echo "default" >&6; } fi # Check whether --enable-valgrind was given. if test "${enable_valgrind+set}" = set; then : enableval=$enable_valgrind; if test "x$enableval" = "xyes" ; then ac_fn_c_check_header_mongrel "$LINENO" "valgrind/memcheck.h" "ac_cv_header_valgrind_memcheck_h" "$ac_includes_default" if test "x$ac_cv_header_valgrind_memcheck_h" = xyes; then : $as_echo "#define VALGRIND_FIXES 1" >>confdefs.h fi fi fi # Checks for header files. for ac_header in execinfo.h fcntl.h malloc.h netdb.h stdlib.h string.h unistd.h arpa/inet.h mach/mach.h netinet/in.h sys/file.h sys/socket.h termios.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Checks for typedefs, structures, and compiler characteristics. ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 $as_echo_n "checking for uid_t in sys/types.h... " >&6; } if ${ac_cv_type_uid_t+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "uid_t" >/dev/null 2>&1; then : ac_cv_type_uid_t=yes else ac_cv_type_uid_t=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 $as_echo "$ac_cv_type_uid_t" >&6; } if test $ac_cv_type_uid_t = no; then $as_echo "#define uid_t int" >>confdefs.h $as_echo "#define gid_t int" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac # Checks for library functions. for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 $as_echo_n "checking for GNU libc compatible malloc... " >&6; } if ${ac_cv_func_malloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_malloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *malloc (); #endif int main () { return ! malloc (0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_malloc_0_nonnull=yes else ac_cv_func_malloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 $as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } if test $ac_cv_func_malloc_0_nonnull = yes; then : $as_echo "#define HAVE_MALLOC 1" >>confdefs.h else $as_echo "#define HAVE_MALLOC 0" >>confdefs.h case " $LIBOBJS " in *" malloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS malloc.$ac_objext" ;; esac $as_echo "#define malloc rpl_malloc" >>confdefs.h fi for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5 $as_echo_n "checking for GNU libc compatible realloc... " >&6; } if ${ac_cv_func_realloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_realloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *realloc (); #endif int main () { return ! realloc (0, 0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_realloc_0_nonnull=yes else ac_cv_func_realloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5 $as_echo "$ac_cv_func_realloc_0_nonnull" >&6; } if test $ac_cv_func_realloc_0_nonnull = yes; then : $as_echo "#define HAVE_REALLOC 1" >>confdefs.h else $as_echo "#define HAVE_REALLOC 0" >>confdefs.h case " $LIBOBJS " in *" realloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS realloc.$ac_objext" ;; esac $as_echo "#define realloc rpl_realloc" >>confdefs.h fi for ac_func in alarm endpwent memset memmove mkdir select socket strdup strndup uname do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_bswap32" >&5 $as_echo_n "checking for __builtin_bswap32... " >&6; } if ${ax_cv_have___builtin_bswap32+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { __builtin_bswap32(0) ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_cv_have___builtin_bswap32=yes else ax_cv_have___builtin_bswap32=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_have___builtin_bswap32" >&5 $as_echo "$ax_cv_have___builtin_bswap32" >&6; } if test yes = $ax_cv_have___builtin_bswap32; then : cat >>confdefs.h <<_ACEOF #define HAVE___BUILTIN_BSWAP32 1 _ACEOF fi ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by telegram-cli $as_me 1.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. 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 --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ telegram-cli config.status 1.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) 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 ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi ================================================ FILE: configure.ac ================================================ AC_PREREQ([2.68]) AC_INIT([telegram-cli], [1.0]) AC_CONFIG_SRCDIR([config.h.in]) AC_CONFIG_HEADERS([config.h]) m4_include([ax_lua.m4]) m4_include([ax_python.m4]) m4_include([m4_ax_check_openssl.m4]) m4_include([m4_ax_check_zlib.m4]) m4_include([m4-ax_gcc_builtin.m4]) # Checks for programs. AC_PROG_CC # BSD locations for headers and libraries from packages, Linux locations for self-compiled stuff. CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" # Checks for libraries. AC_SEARCH_LIBS([clock_gettime], [rt]) AC_SEARCH_LIBS([backtrace], [execinfo]) AC_CHECK_LIB([event], [event_base_new], [], [AC_MSG_ERROR([no libevent found])]) EVENT_VER="" AC_CHECK_HEADER(event2/event.h, [AC_DEFINE([EVENT_V2], [1], [Use libevent v2])], [ AC_CHECK_HEADER(event.h, [AC_DEFINE([EVENT_V1], [1], [Use libevent v1])], [AC_MSG_ERROR([no libevent found])]) ]) EXTRA_LIBS="" # OPENSSL_INCLUDES to the include directives required # OPENSSL_LIBS to the -l directives required # OPENSSL_LDFLAGS to the -L or -R flags required AC_ARG_ENABLE(openssl,[ --disable-openssl disables OpenSSL, and don't link against it (this can't read *.pub files, though.)], [ if test "x$enableval" = "xno" ; then AC_DEFINE([TGL_AVOID_OPENSSL],[1],[avoid OpenSSL entirely, use libgcrypt instead (this can't read *.pub files, though.)]) AC_CHECK_LIB([gcrypt], [gcry_mpi_snatch], [], [AC_MSG_ERROR(["Need libgcrypt >= 1.60"])]) else # Don't be annoying, so don't inform the user about --disable-openssl AX_CHECK_OPENSSL(,[AC_MSG_ERROR([No openssl found.])]) fi ],[ AX_CHECK_OPENSSL(,[AC_MSG_ERROR([No openssl found. With --disable-openssl, libtgl will use libgcrypt instead.])]) ]) AX_CHECK_ZLIB(, [AC_MSG_ERROR([No zlib found])]) AC_CHECK_LIB([readline], [rl_save_prompt], [ EXTRA_LIBS="${EXTRA_LIBS} -lreadline" ; ], [AC_MSG_ERROR([no libreadline found])]) AC_MSG_CHECKING([for libconfig]) AC_ARG_ENABLE(libconfig,[--enable-libconfig/--disable-libconfig], [ if test "x$enableval" = "xno" ; then AC_MSG_RESULT([disabled]) else AC_MSG_RESULT([enabled]) AC_CHECK_LIB([config],[config_init],[],AC_MSG_ERROR([No libconfig found. Try --disable-libconfig])) fi ],[ AC_MSG_RESULT([enabled]) AC_CHECK_LIB([config],[config_init],[],AC_MSG_ERROR([No libconfig found. Try --disable-libconfig])) ]) AC_ARG_ENABLE(extf,[--enable-extf/--disable-extf], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_EXTF],[1],[disable extf queries]) fi ],[ ]) 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}" ; ] [CPPFLAGS="${CPPFLAGS} ${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}" ; ] [CPPFLAGS="${CPPFLAGS} ${LUA_INCLUDE}" ; ] AC_DEFINE(USE_LUA,1,[use lua]) ], [ AC_MSG_ERROR([No lua found. Try --disable-liblua]) ]) ]) AC_MSG_CHECKING([for python]) AC_ARG_ENABLE(python,[--enable-python/--disable-python], [ if test "x$enableval" = "xyes" ; then AC_MSG_RESULT([disabled]) else AC_MSG_RESULT([enabled]) AX_PYTHON() AC_SUBST([PYTHON_FOUND]) if test $PYTHON_FOUND = no ; then AC_MSG_ERROR([No supported python lib version found. Try --disable-python]) else AC_SUBST([PYTHON_LIBS]) AC_SUBST([PYTHON_CFLAGS]) EXTRA_LIBS="${EXTRA_LIBS} -l${PYTHON_LIB}" CPPFLAGS="${CPPFLAGS} -I${PYTHON_INCLUDE_DIR}" AC_DEFINE(USE_PYTHON,1,[use python]) fi fi ],[ AC_MSG_RESULT([disabled]) ]) AC_MSG_CHECKING([for libjansson]) AC_ARG_ENABLE(json,[--enable-json/--disable-json], [ if test "x$enableval" = "xno" ; then AC_MSG_RESULT([disabled]) else AC_MSG_RESULT([enabled]) AC_CHECK_LIB([jansson],[json_array_set_new],[],AC_MSG_ERROR([No libjansson found. Try --disable-json])) AC_DEFINE(USE_JSON,1,[use json]) fi ],[ AC_MSG_RESULT([enabled]) AC_CHECK_LIB([jansson],[json_array_set_new],[],AC_MSG_ERROR([No libjansson found. Try --disable-json])) AC_DEFINE(USE_JSON,1,[use json]) ]) #check for custom prog name AC_MSG_CHECKING([progname]) AC_ARG_WITH(progname,[--with-progname=], [ if test "x$with_progname" = "xno" ; then AC_MSG_RESULT([default]) elif test "x$with_progname" = "xyes" ; then AC_MSG_RESULT([default]) else AC_MSG_RESULT(["$with_progname"]) AC_DEFINE_UNQUOTED([PROG_NAME], ["$with_progname"], [Use custom prog name]) fi ],[ AC_MSG_RESULT([default]) ]) AC_ARG_ENABLE(valgrind,[--enable-valgrind/--disable-valgrind], [ if test "x$enableval" = "xyes" ; then AC_CHECK_HEADER(valgrind/memcheck.h, [AC_DEFINE([VALGRIND_FIXES], [1], [fixed for correct valgrind work])], [ ]) fi ],[ ]) # Checks for header files. AC_CHECK_HEADERS([execinfo.h fcntl.h malloc.h netdb.h stdlib.h string.h unistd.h arpa/inet.h mach/mach.h netinet/in.h sys/file.h sys/socket.h termios.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_SIZE_T AC_TYPE_UID_T AC_C_INLINE # Checks for library functions. AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([alarm endpwent memset memmove mkdir select socket strdup strndup uname]) AX_GCC_BUILTIN(__builtin_bswap32) AC_SUBST(EXTRA_LIBS) AC_CONFIG_FILES([Makefile]) AC_OUTPUT ================================================ FILE: debian/changelog ================================================ telegram-cli (1.0.6-1) unstable; urgency=low * Upstream update version * Inpliment -e option -- Steve Illichevsky Sat, 11 Oct 2014 08:47:07 +0400 telegram-cli (1.0.5.1-1) unstable; urgency=low * Initial release -- Steve Illichevsky Sun, 05 Oct 2014 09:37:06 +0400 ================================================ FILE: debian/clean ================================================ Makefile ================================================ FILE: debian/compat ================================================ 9 ================================================ FILE: debian/control ================================================ Source: telegram-cli Section: net Priority: extra Maintainer: Steve Illichevsky Build-Depends: debhelper (>= 8.0.0), autotools-dev, autoconf-archive, libreadline-dev, libconfig-dev, libssl-dev, lua5.1, liblua5.1-dev, lua-lgi, libevent-dev Standards-Version: 3.9.5 Homepage: https://github.com/vysheng/tg Vcs-Git: git://github.com/vysheng/tg.git Vcs-Browser: https://github.com/vysheng/tg Package: telegram-cli Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: Command-line interface for Telegram messenger Telegram messenger is a cloud-based instant messaging designed for smart phones and similar to Whatsapp but more flexible, and powerful. You can send messages, photos, videos and documents to people who are in your phone contacts (and have Telegram). Telegram also supports secret chats whose provide a private (encrypted) way of communication. . This package contains a command-line based client for Telegram with the following features: * Colored terminal messages. * Message management: history, stats, etc. * Group chat: create and manage groups. * Secret chat: secured and encrypted conversations. * Contact management: add/edit/remove contacts. * Multimedia support: send/load photos and videos. ================================================ FILE: debian/copyright ================================================ Format: http://dep.debian.net/deps/dep5 Upstream-Name: telegram-cli Source: https://github.com/vysheng/tg Files: * Copyright: 2013-2014 Vitaly Valtman License: GPL-3.0+ Files: debian/* Copyright: 2014 Steve Illichevsky License: GPL-3.0+ License: GPL-3.0+ 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 package 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 . . On Debian systems, the complete text of the GNU General Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". # Please also look if there are files or directories which have a # different copyright/license attached and list them here. ================================================ FILE: debian/docs ================================================ README.es README-LUA README.md #telegram-cli.8 ================================================ FILE: debian/install ================================================ bin/telegram-cli usr/bin server.pub etc/telegram-cli #bin/telegram-cli usr/share/telegram-daemon/bin #start-telegram-daemon /usr/share/telegram-daemon/bin test.lua var/lib/telegram-cli/ #telegram-daemon etc/init.d ================================================ FILE: debian/rules ================================================ #!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # This file was originally written by Joey Hess and Craig Small. # As a special exception, when this file is copied by dh-make into a # dh-make output file, you may use that output file without restriction. # This special exception was added by Craig Small in version 0.37 of dh-make. # Uncomment this to turn on verbose mode. export DH_VERBOSE=1 VERSION=$(shell dpkg-parsechangelog | sed -n 's/^Version: //p' | cut -f1 -d'-') PACKAGE_NAME=$(shell dpkg-parsechangelog | sed -n 's/^Source: //p') %: dh $@ --with autotools-dev build-orig: mkdir -p $(PACKAGE_NAME)-$(VERSION) tar --exclude=ax_lua.m4 --exclude=debian --exclude=\.pc \ --exclude=$(PACKAGE_NAME)-$(VERSION) -cf - . \ | ( cd $(PACKAGE_NAME)-$(VERSION) && tar xf - ) tar -cf ../$(PACKAGE_NAME)_$(VERSION).orig.tar $(PACKAGE_NAME)-$(VERSION) $(RM) -r $(PACKAGE_NAME)-$(VERSION) xz ../$(PACKAGE_NAME)_$(VERSION).orig.tar ================================================ FILE: debian/source/format ================================================ 3.0 (quilt) ================================================ FILE: debian/telegram-cli.8 ================================================ .TH man 8 "02 October 2014" "1.0.5.1" "telegram-cli man page" .SH NAME telegram-cli \- Command-line interface for Telegram messenger .SH SYNOPSIS telegram-cli -k [keyfile] .SH DESCRIPTION Telegram messenger is a cloud-based instant messaging designed for smart phones and similar to Whatsapp but more flexible, and powerful. You can send messages, photos, videos and documents to people who are in your phone contacts (and have Telegram). Telegram also supports secret chats whose provide a private (encrypted) way of communication. . This package contains a command-line based client for Telegram with the following features: * Colored terminal messages. * Message management: history, stats, etc. * Group chat: create and manage groups. * Secret chat: secured and encrypted conversations. * Contact management: add/edit/remove contacts. * Multimedia support: send/load photos and videos. .SH OPTIONS Telegram-cli Usage -u specify username (would not be asked during authorization) -k specify location of public key (possible multiple entries) -v increase verbosity (0-ERROR 1-WARNIN 2-NOTICE 3+-DEBUG-levels) -N message num mode -c config file name -p use specified profile -l log level -f during authorization fetch all messages since registration -E diable auto accept of encrypted chats -s lua script file -W send dialog_list query and wait for answer before reading input -C disable color output -R disable readline -d daemon mode -L log file name -U change uid after start -G change gid after start -D disable output -P port to listen for input commands -S unix socket to create .SH SEE ALSO .SH BUGS No known bugs. .SH AUTHOR Vitaliy Vatman (-@-) ================================================ FILE: debian/telegram-cli.logrotate ================================================ /var/lib/telegram-cli/*.log { daily missingok rotate 31 compress notifempty nocreate } ================================================ FILE: debian/telegram-cli.manpages ================================================ debian/telegram-cli.8 ================================================ FILE: debian/telegram-cli.postinst.debhelper ================================================ # Automatically added by dh_installinit if [ -e "/etc/init/telegram-cli.conf" ]; then invoke-rc.d telegram-cli start || exit $? fi # End automatically added section # Automatically added by dh_installinit update-rc.d -f telegram-cli remove >/dev/null || exit $? # End automatically added section ================================================ FILE: debian/telegram-cli.preinst ================================================ adduser --system --home /var/lib/telegram-cli --gecos "Telegram Daemon User" --group telegramd ================================================ FILE: debian/telegram-cli.preinst.debhelper ================================================ # Automatically added by dh_installinit if [ "$1" = install ] || [ "$1" = upgrade ]; then if [ -e "/etc/init.d/telegram-cli" ] && [ ! -L "/etc/init.d/telegram-cli" ]; then if [ "`md5sum \"/etc/init.d/telegram-cli\" | sed -e \"s/ .*//\"`" != \ "`dpkg-query -W -f='${Conffiles}' telegram-cli | sed -n -e \"\\\\' /etc/init.d/telegram-cli '{s/ obsolete$//;s/.* //p}\"`" ] then echo "Obsolete conffile /etc/init.d/telegram-cli has been modified by you, renaming to .dpkg-bak" mv -f "/etc/init.d/telegram-cli" "/etc/init.d/telegram-cli.dpkg-bak" else rm -f "/etc/init.d/telegram-cli" fi fi fi # End automatically added section ================================================ FILE: debian/telegram-cli.prerm ================================================ # Automatically added by dh_installinit if [ -e "/etc/init/telegram-cli.conf" ]; then invoke-rc.d telegram-cli stop || exit $? fi # End automatically added section deluser --remove-home telegramd ================================================ FILE: debian/telegram-cli.prerm.debhelper ================================================ # Automatically added by dh_installinit if [ -e "/etc/init/telegram-cli.conf" ]; then invoke-rc.d telegram-cli stop || exit $? fi # End automatically added section ================================================ FILE: debian/telegram-cli.upstart ================================================ # Service setuid telegramd setgid telegramd script exec /usr/bin/telegram-cli -s /var/lib/telegram-cli/test.lua -W -d -C -vvvv -l 0 -L /var/lib/telegram-cli/telegram-cli.log -P 8002 # This example for Daemon wich keep log in his home directory # This daemon can listen localhost:8002 tcp port end script ================================================ FILE: debian/watch ================================================ version=3 opts=filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/tg-$1\.tar\.gz/ \ https://github.com/vysheng/tg/tags .*/v?(\d\S*)\.tar\.gz ================================================ FILE: event-old.h ================================================ #ifndef __EVENT_OLD_H__ #define __EVENT_OLD_H__ #include #include #define BEV_EVENT_READ EVBUFFER_READ #define BEV_EVENT_WRITE EVBUFFER_WRITE #define BEV_EVENT_EOF EVBUFFER_EOF #define BEV_EVENT_ERROR EVBUFFER_ERROR #define BEV_EVENT_TIMEOUT EVBUFFER_TIMEOUT typedef int evutil_socket_t; static inline struct event *event_new (struct event_base *base, int fd, int what, void(*callback)(int, short, void *), void *arg) __attribute__ ((unused)); static inline struct event *event_new (struct event_base *base, int fd, int what, void(*callback)(int, short, void *), void *arg) { struct event *ev = malloc (sizeof (*ev)); event_set (ev, fd, what, callback, arg); event_base_set (base, ev); return ev; } static inline struct event *evtimer_new (struct event_base *base, void(*callback)(int, short, void *), void *arg) __attribute__ ((unused)); static inline struct event *evtimer_new (struct event_base *base, void(*callback)(int, short, void *), void *arg) { struct event *ev = malloc (sizeof (*ev)); event_set (ev, -1, 0, callback, arg); event_base_set (base, ev); return ev; } static void event_free (struct event *ev) __attribute__ ((unused)); static void event_free (struct event *ev) { event_del (ev); free (ev); } static struct bufferevent *bufferevent_socket_new (struct event_base *base, int fd, int flags) __attribute__ ((unused)); static struct bufferevent *bufferevent_socket_new (struct event_base *base, int fd, int flags) { assert (!flags); struct bufferevent *bev = bufferevent_new(fd, 0, 0, 0, 0); bufferevent_base_set (base, bev); return bev; } static inline void *event_get_callback_arg(const struct event *ev) { return ev->ev_arg; } #endif ================================================ FILE: gentoo/net-im/telegram-cli/Manifest ================================================ EBUILD telegram-cli-9999.ebuild 926 SHA256 d9c959af30c77afe8e6b1cee162e5362edfb9da6980b53ef71c3cae5f621bf05 SHA512 eeef9e1d2d7cd0b600be0d44de39e9c38207d5fb8f675e7ba239c1e907ab5df6e198a5810e6bb08445c7c2a98cc50bf78554f52b4c7c0534f111bfa3256b8186 WHIRLPOOL 700a6fd9930074ec36dfb3f4b248a43e6d7c0ab0f97ed6b56343e79fb15a087d99eb52ad67a818e67cbb1a848d65cc395f60b319f3fda60c87c10e9f4e132838 ================================================ FILE: gentoo/net-im/telegram-cli/telegram-cli-9999.ebuild ================================================ # Copyright 1999-2013 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ EAPI=5 EGIT_REPO_URI="https://github.com/vysheng/tg.git" EGIT_BRANCH="master" EGIT_HAS_SUBMODULES=1 inherit git-2 IUSE="+lua +json +python" DESCRIPTION="Command line interface client for Telegram" HOMEPAGE="https://github.com/vysheng/tg" LICENSE="GPL-2" SLOT="0" KEYWORDS="~amd64 ~x86" DEPEND="sys-libs/zlib sys-libs/readline dev-libs/libconfig dev-libs/openssl dev-libs/libevent lua? ( dev-lang/lua ) json? ( dev-libs/jansson ) python? ( dev-lang/python )" src_unpack() { git-2_src_unpack cd $EGIT_SOURCEDIR git submodule update --init --recursive } src_configure() { econf $(use_enable lua liblua ) econf $(use_enable python python ) econf $(use_enable json json ) } src_install() { newbin bin/telegram-cli telegram-cli insinto /etc/telegram-cli/ newins tg-server.pub server.pub } ================================================ FILE: interface.c ================================================ /* This file is part of telegram-cli. Telegram-cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Telegram-cli 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 telegram-cli. If not, see . Copyright Vitaly Valtman 2013-2015 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef USE_PYTHON # include "python-tg.h" #endif #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #ifdef READLINE_GNU #include #include #else #include #include #endif #include //#include "queries.h" #include "interface.h" #include "telegram.h" #ifdef EVENT_V2 #include #include #include #else #include #include "event-old.h" #endif //#include "auto/constants.h" //#include "tools.h" //#include "structures.h" #ifdef USE_LUA # include "lua-tg.h" #endif //#include "mtproto-common.h" #include #include #include "loop.h" #ifndef PATH_MAX #define PATH_MAX 4096 #endif #ifdef __APPLE__ #define OPEN_BIN "open %s" #else #define OPEN_BIN "xdg-open %s" #endif #ifdef USE_JSON # include # include "json-tg.h" #endif #include "tgl/mtproto-common.h" #include "auto/auto-store.h" #include "auto/auto-fetch-ds.h" #include "auto/auto-types.h" #include "auto/auto-free-ds.h" #include #include "tgl/tree.h" struct username_peer_pair { const char *username; tgl_peer_t *peer; }; #define username_peer_pair_cmp(a,b) strcmp (a->username, b->username) DEFINE_TREE (username_peer_pair, struct username_peer_pair *, username_peer_pair_cmp, NULL) struct tree_username_peer_pair *username_peer_pair; struct username_peer_pair *current_map; #define ALLOW_MULT 1 char *default_prompt = "> "; extern int read_one_string; extern char one_string[]; extern int one_string_len; extern char *one_string_prompt; extern int one_string_flags; extern int enable_json; int disable_auto_accept; int msg_num_mode; int permanent_msg_id_mode; int permanent_peer_id_mode; int disable_colors; extern int alert_sound; extern int binlog_read; extern char *home_directory; int do_html; int safe_quit; int in_readline; int readline_active; int log_level; char *line_ptr; int in_chat_mode; tgl_peer_id_t chat_mode_id; extern int readline_disabled; extern int disable_output; struct in_ev *notify_ev; extern int usfd; extern int sfd; extern int use_ids; extern int daemonize; extern struct tgl_state *TLS; int readline_deactivated; void fail_interface (struct tgl_state *TLS, struct in_ev *ev, int error_code, const char *format, ...) __attribute__ (( format (printf, 4, 5))); void event_incoming (struct bufferevent *bev, short what, void *_arg); int is_same_word (const char *s, size_t l, const char *word) { return s && word && strlen (word) == l && !memcmp (s, word, l); } static void skip_wspc (void) { while (*line_ptr && ((unsigned char)*line_ptr) <= ' ') { line_ptr ++; } } static char *cur_token; static int cur_token_len; static int cur_token_end_str; static int cur_token_quoted; #define SOCKET_ANSWER_MAX_SIZE (1 << 25) static char socket_answer[SOCKET_ANSWER_MAX_SIZE + 1]; static int socket_answer_pos = -1; void socket_answer_start (void) { socket_answer_pos = 0; } static void socket_answer_add_printf (const char *format, ...) __attribute__ ((format (printf, 1, 2))); void socket_answer_add_printf (const char *format, ...) { if (socket_answer_pos < 0) { return; } va_list ap; va_start (ap, format); socket_answer_pos += vsnprintf (socket_answer + socket_answer_pos, SOCKET_ANSWER_MAX_SIZE - socket_answer_pos, format, ap); va_end (ap); if (socket_answer_pos > SOCKET_ANSWER_MAX_SIZE) { socket_answer_pos = -1; } } void socket_answer_end (struct in_ev *ev) { if (ev->bev) { static char s[100]; sprintf (s, "ANSWER %d\n", socket_answer_pos); bufferevent_write (ev->bev, s, strlen (s)); bufferevent_write (ev->bev, socket_answer, socket_answer_pos); bufferevent_write (ev->bev, "\n", 1); } socket_answer_pos = -1; } #define mprintf(ev,...) \ if (ev) { socket_answer_add_printf (__VA_ARGS__); } \ else { printf (__VA_ARGS__); } #define mprint_start(ev,...) \ if (!ev) { print_start (__VA_ARGS__); } \ else { socket_answer_start (); } #define mprint_end(ev,...) \ if (!ev) { print_end (__VA_ARGS__); } \ else { socket_answer_end (ev); } #define mpush_color(ev,...) \ if (!ev) { push_color (__VA_ARGS__); } #define mpop_color(ev,...) \ if (!ev) { pop_color (__VA_ARGS__); } static void unescape_token (char *start, char *end) { static char cur_token_buff[(1 << 20) + 1]; cur_token_len = 0; cur_token = cur_token_buff; while (start < end) { assert (cur_token_len < (1 << 20)); switch (*start) { case '\\': start ++; switch (*start) { case 'n': cur_token[cur_token_len ++] = '\n'; break; case 'r': cur_token[cur_token_len ++] = '\r'; break; case 't': cur_token[cur_token_len ++] = '\t'; break; case 'b': cur_token[cur_token_len ++] = '\b'; break; case 'a': cur_token[cur_token_len ++] = '\a'; break; default: cur_token[cur_token_len ++] = *start; break; } break; default: cur_token[cur_token_len ++] = *start;; break; } start ++; } cur_token[cur_token_len] = 0; } int force_end_mode; static void next_token (void) { skip_wspc (); cur_token_end_str = 0; cur_token_quoted = 0; if (!*line_ptr) { cur_token_len = 0; cur_token_end_str = 1; return; } char c = *line_ptr; char *start = line_ptr; if (c == '"' || c == '\'') { cur_token_quoted = 1; line_ptr ++; int esc = 0; while (*line_ptr && (esc || *line_ptr != c)) { if (*line_ptr == '\\') { esc = 1 - esc; } else { esc = 0; } line_ptr ++; } if (!*line_ptr) { cur_token_len = -2; } else { unescape_token (start + 1, line_ptr); line_ptr ++; } } else { while (*line_ptr && ((unsigned char)*line_ptr) > ' ') { line_ptr ++; } cur_token = start; cur_token_len = line_ptr - start; cur_token_end_str = (!force_end_mode) && (*line_ptr == 0); } } void next_token_end (void) { skip_wspc (); if (*line_ptr && *line_ptr != '"' && *line_ptr != '\'') { cur_token_quoted = 0; cur_token = line_ptr; while (*line_ptr) { line_ptr ++; } cur_token_len = line_ptr - cur_token; while (((unsigned char)cur_token[cur_token_len - 1]) <= ' ' && cur_token_len >= 0) { cur_token_len --; } assert (cur_token_len > 0); cur_token_end_str = !force_end_mode; return; } else { if (*line_ptr) { next_token (); skip_wspc (); if (*line_ptr) { cur_token_len = -1; } } else { next_token (); } } } void next_token_end_ac (void) { skip_wspc (); if (*line_ptr && *line_ptr != '"' && *line_ptr != '\'') { cur_token_quoted = 0; cur_token = line_ptr; while (*line_ptr) { line_ptr ++; } cur_token_len = line_ptr - cur_token; assert (cur_token_len > 0); cur_token_end_str = !force_end_mode; return; } else { if (*line_ptr) { next_token (); skip_wspc (); if (*line_ptr) { cur_token_len = -1; } } else { next_token (); } } } #define NOT_FOUND (int)0x80000000 tgl_peer_id_t TGL_PEER_NOT_FOUND = {.peer_id = NOT_FOUND}; long long cur_token_int (void) { if (cur_token_len <= 0) { return NOT_FOUND; } else { char c = cur_token[cur_token_len]; cur_token[cur_token_len] = 0; char *end = 0; long long x = strtoll (cur_token, &end, 0); cur_token[cur_token_len] = c; if (end != cur_token + cur_token_len) { return NOT_FOUND; } else { return x; } } } int hex2int (char c) { if (c >= '0' && c <= '9') { return c - '0'; } if (c >= 'a' && c <= 'f') { return c - 'a' + 10; } assert (0); return 0; } char *print_permanent_msg_id (tgl_message_id_t id) { static char buf[2 * sizeof (tgl_message_id_t) + 1]; unsigned char *s = (void *)&id; int i; for (i = 0; i < (int)sizeof (tgl_message_id_t); i++) { sprintf (buf + 2 * i, "%02x", (unsigned)s[i]); } return buf; } char *print_permanent_peer_id (tgl_peer_id_t id) { static char buf[2 * sizeof (tgl_peer_id_t) + 2]; buf[0] = '$'; unsigned char *s = (void *)&id; int i; for (i = 0; i < (int)sizeof (tgl_peer_id_t); i++) { sprintf (buf + 1 + 2 * i, "%02x", (unsigned)s[i]); } return buf; } tgl_message_id_t parse_input_msg_id (const char *s, int l) { if (!s || l <= 0) { tgl_message_id_t id; memset (&id, 0, sizeof (id)); id.peer_type = 0; return id; } else { tgl_message_id_t id; memset (&id, 0, sizeof (id)); if (l == 2 * sizeof (tgl_message_id_t)) { int i; for (i = 0; i < (int)sizeof (tgl_message_id_t); i++) { if ( (s[i] < '0' || s[i] > '9') && (s[i] < 'a' || s[i] > 'f') ) { id.peer_type = 0; return id; } } unsigned char *d = (void *)&id; for (i = 0; i < (int)sizeof (tgl_message_id_t); i++) { d[i] = hex2int (s[2 * i]) * 16 + hex2int (s[2 * i + 1]); } return id; } else { char *sc = tstrndup (s, l); char *end = 0; long long x = strtoll (sc, &end, 0); tfree_str (sc); if (end != sc + l) { id.peer_type = 0; } else { id.peer_type = TGL_PEER_TEMP_ID; id.id = x; } return id; } } } tgl_message_id_t cur_token_msg_id (void) { return parse_input_msg_id (cur_token, cur_token_len); } double cur_token_double (void) { if (cur_token_len <= 0) { return NOT_FOUND; } else { char c = cur_token[cur_token_len]; cur_token[cur_token_len] = 0; char *end = 0; double x = strtod (cur_token, &end); cur_token[cur_token_len] = c; if (end != cur_token + cur_token_len) { return NOT_FOUND; } else { return x; } } } tgl_peer_id_t parse_input_peer_id (const char *s, int l, int mask) { if (!s || l <= 0) { return TGL_PEER_NOT_FOUND; } if (*s == '$') { s ++; l --; if (l != 2 * sizeof (tgl_peer_id_t)) { return TGL_PEER_NOT_FOUND; } tgl_peer_id_t res; unsigned char *r = (void *)&res; int i; for (i = 0; i < l; i++) { if ((s[i] < '0' || s[i] > '9') && (s[i] < 'a' || s[i] > 'f')) { return TGL_PEER_NOT_FOUND; } } for (i = 0; i < (int)sizeof (tgl_peer_id_t); i++) { r[i] = hex2int (s[2 * i]) * 16 + hex2int (s[2 * i + 1]); } if (mask && tgl_get_peer_type (res) != mask) { return TGL_PEER_NOT_FOUND; } return res; } if (*s == '@') { s ++; l --; char *tmp = tstrndup (s, l); struct username_peer_pair *p = tree_lookup_username_peer_pair (username_peer_pair, (void *)&tmp); tfree_str (tmp); if (p && (!mask || tgl_get_peer_type (p->peer->id) == mask)) { return p->peer->id; } else { return TGL_PEER_NOT_FOUND; } } const char *ss[] = {"user#id", "user#", "chat#id", "chat#", "secret_chat#id", "secret_chat#", "channel#id", "channel#"}; int tt[] = {TGL_PEER_USER, TGL_PEER_USER, TGL_PEER_CHAT, TGL_PEER_CHAT, TGL_PEER_ENCR_CHAT, TGL_PEER_ENCR_CHAT, TGL_PEER_CHANNEL, TGL_PEER_CHANNEL}; char *sc = tstrndup (s, l); int i; for (i = 0; i < 8; i++) if (!mask || mask == tt[i]) { int x = strlen (ss[i]); if (l > x && !memcmp (s, ss[i], x)) { int r = atoi (sc + x); tfree_str (sc); if (r < 0) { return TGL_PEER_NOT_FOUND; } tgl_peer_t *P = tgl_peer_get (TLS, tgl_set_peer_id (tt[i], r)); if (!P) { return TGL_PEER_NOT_FOUND; } return P->id; } } tgl_peer_t *P = tgl_peer_get_by_name (TLS, sc); tfree_str (sc); if (P && (!mask || tgl_get_peer_type (P->id) == mask)) { return P->id; } else { return TGL_PEER_NOT_FOUND; } } tgl_peer_id_t cur_token_user (void) { return parse_input_peer_id (cur_token, cur_token_len, TGL_PEER_USER); } tgl_peer_id_t cur_token_chat (void) { return parse_input_peer_id (cur_token, cur_token_len, TGL_PEER_CHAT); } tgl_peer_id_t cur_token_encr_chat (void) { return parse_input_peer_id (cur_token, cur_token_len, TGL_PEER_ENCR_CHAT); } tgl_peer_id_t cur_token_channel (void) { return parse_input_peer_id (cur_token, cur_token_len, TGL_PEER_CHANNEL); } tgl_peer_id_t cur_token_peer (void) { return parse_input_peer_id (cur_token, cur_token_len, 0); } /* static tgl_peer_t *mk_peer (tgl_peer_id_t id) { if (tgl_get_peer_type (id) == NOT_FOUND) { return 0; } tgl_peer_t *P = tgl_peer_get (TLS, id); if (!P) { if (tgl_get_peer_type (id) == TGL_PEER_USER) { tgl_insert_empty_user (TLS, tgl_get_peer_id (id)); } if (tgl_get_peer_type (id) == TGL_PEER_CHAT) { tgl_insert_empty_chat (TLS, tgl_get_peer_id (id)); } P = tgl_peer_get (TLS, id); } return P; }*/ char *get_default_prompt (void) { static char buf[1000]; int l = 0; if (in_chat_mode) { tgl_peer_t *U = tgl_peer_get (TLS, chat_mode_id); assert (U && U->print_name); l += snprintf (buf + l, 999 - l, COLOR_RED "%.*s " COLOR_NORMAL, 100, U->print_name); } if (TLS->unread_messages || TLS->cur_uploading_bytes || TLS->cur_downloading_bytes) { l += snprintf (buf + l, 999 - l, COLOR_RED "["); int ok = 0; if (TLS->unread_messages) { l += snprintf (buf + l, 999 - l, "%d unread", TLS->unread_messages); ok = 1; } if (TLS->cur_uploading_bytes) { if (ok) { *(buf + l) = ' '; l ++; } ok = 1; l += snprintf (buf + l, 999 - l, "%lld%%Up", 100 * TLS->cur_uploaded_bytes / TLS->cur_uploading_bytes); } if (TLS->cur_downloading_bytes) { if (ok) { *(buf + l) = ' '; l ++; } ok = 1; l += snprintf (buf + l, 999 - l, "%lld%%Down", 100 * TLS->cur_downloaded_bytes / TLS->cur_downloading_bytes); } l += snprintf (buf + l, 999 - l, "]" COLOR_NORMAL); l += snprintf (buf + l, 999 - l, "%s", default_prompt); return buf; } l += snprintf (buf + l, 999 - l, "%s", default_prompt); return buf; } char *complete_none (const char *text, int state) { return 0; } void set_prompt (const char *s) { if (readline_disabled) { return; } rl_set_prompt (s); } void update_prompt (void) { if (readline_disabled) { fflush (stdout); return; } if (read_one_string) { return; } print_start (); set_prompt (get_default_prompt ()); if (readline_active) { rl_redisplay (); } print_end (); } char *modifiers[] = { "[offline]", "[enable_preview]", "[disable_preview]", "[html]", "[reply=", 0 }; char *in_chat_commands[] = { "/exit", "/quit", "/history", "/read", 0 }; enum command_argument { ca_none, ca_user, ca_chat, ca_secret_chat, ca_channel, ca_peer, ca_file_name, ca_file_name_end, ca_period, ca_number, ca_double, ca_string_end, ca_msg_string_end, ca_string, ca_modifier, ca_command, ca_extf, ca_msg_id, ca_optional = 256 }; struct arg { int flags; union { //tgl_peer_t *P; //struct tgl_message *M; char *str; long long num; double dval; tgl_message_id_t msg_id; tgl_peer_id_t peer_id; }; }; struct command { char *name; enum command_argument args[10]; void (*fun)(struct command *command, int arg_num, struct arg args[], struct in_ev *ev); char *desc; void *arg; }; int offline_mode; int reply_id; int disable_msg_preview; void print_user_list_gw (struct tgl_state *TLS, void *extra, int success, int num, struct tgl_user *UL[]); void print_msg_list_gw (struct tgl_state *TLS, void *extra, int success, int num, struct tgl_message *ML[]); void print_msg_list_history_gw (struct tgl_state *TLS, void *extra, int success, int num, struct tgl_message *ML[]); void print_msg_list_success_gw (struct tgl_state *TLS, void *extra, int success, int num, struct tgl_message *ML[]); void print_dialog_list_gw (struct tgl_state *TLS, void *extra, int success, int size, tgl_peer_id_t peers[], tgl_message_id_t *last_msg_id[], int unread_count[]); void print_chat_info_gw (struct tgl_state *TLS, void *extra, int success, struct tgl_chat *C); void print_channel_info_gw (struct tgl_state *TLS, void *extra, int success, struct tgl_channel *C); void print_user_info_gw (struct tgl_state *TLS, void *extra, int success, struct tgl_user *C); void print_filename_gw (struct tgl_state *TLS, void *extra, int success, const char *name); void print_string_gw (struct tgl_state *TLS, void *extra, int success, const char *name); void open_filename_gw (struct tgl_state *TLS, void *extra, int success, const char *name); void print_secret_chat_gw (struct tgl_state *TLS, void *extra, int success, struct tgl_secret_chat *E); void print_card_gw (struct tgl_state *TLS, void *extra, int success, int size, int *card); void print_user_gw (struct tgl_state *TLS, void *extra, int success, struct tgl_user *U); void print_peer_gw (struct tgl_state *TLS, void *extra, int success, tgl_peer_t *U); void print_msg_gw (struct tgl_state *TLS, void *extra, int success, struct tgl_message *M); void print_msg_success_gw (struct tgl_state *TLS, void *extra, int success, struct tgl_message *M); void print_encr_chat_success_gw (struct tgl_state *TLS, void *extra, int success, struct tgl_secret_chat *E);; void print_success_gw (struct tgl_state *TLS, void *extra, int success); struct command commands[]; /* {{{ client methods */ void do_help (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { mprint_start (ev); } int total = 0; mpush_color (ev, COLOR_YELLOW); struct command *cmd = commands; while (cmd->name) { if (!args[0].str || !strcmp (args[0].str, cmd->name)) { mprintf (ev, "%s\n", cmd->desc); total ++; } cmd ++; } if (!total) { assert (arg_num == 1); mprintf (ev, "Unknown command '%s'\n", args[0].str); } mpop_color (ev); if (ev) { mprint_end (ev); } if (!ev) { fflush (stdout); } } void do_get_terms_of_service (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (!arg_num); if (ev) { ev->refcnt ++; } tgl_do_get_terms_of_service (TLS, print_string_gw, ev); } void do_stats (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (!arg_num); static char stat_buf[1 << 15]; tgl_print_stat (TLS, stat_buf, (1 << 15) - 1); if (ev) { mprint_start (ev); } mprintf (ev, "%s\n", stat_buf); if (ev) { mprint_end (ev); } if (!ev) { fflush (stdout); } } void do_show_license (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (!arg_num); static char *b = #include "LICENSE.h" ; if (ev) { mprint_start (ev); } mprintf (ev, "%s", b); if (ev) { mprint_end (ev); } } void do_quit (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { if (daemonize) { event_incoming (ev->bev, BEV_EVENT_EOF, ev); } do_halt (0); } void do_safe_quit (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { if (daemonize) { event_incoming (ev->bev, BEV_EVENT_EOF, ev); } safe_quit = 1; } void do_set (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { int num = args[1].num; if (!strcmp (args[0].str, "debug_verbosity")) { tgl_set_verbosity (TLS, num); } else if (!strcmp (args[0].str, "log_level")) { log_level = num; } else if (!strcmp (args[0].str, "msg_num")) { msg_num_mode = num; } else if (!strcmp (args[0].str, "alert")) { alert_sound = num; } } void do_chat_with_peer (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { if (!ev) { in_chat_mode = 1; chat_mode_id = args[0].peer_id; } } void do_main_session (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { if (notify_ev && !--notify_ev->refcnt) { free (notify_ev); } notify_ev = ev; if (ev) { ev->refcnt ++; } } void do_version (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (!arg_num); if (ev) { mprint_start (ev); } mpush_color (ev, COLOR_YELLOW); mprintf (ev, "Telegram-cli version %s (uses tgl version %s)\n", TELEGRAM_CLI_VERSION, TGL_VERSION); #ifdef TGL_AVOID_OPENSSL mprintf (ev, "uses libgcrypt for encryption\n"); #else mprintf (ev, "uses libopenssl for encryption\n"); #endif mpop_color (ev); if (ev) { mprint_end (ev); } if (!ev) { fflush (stdout); } } /* }}} */ #define ARG2STR_DEF(n,def) args[n].str ? args[n].str : def, args[n].str ? strlen (args[n].str) : strlen (def) #define ARG2STR(n) args[n].str, args[n].str ? strlen (args[n].str) : 0 /* {{{ WORK WITH ACCOUNT */ void do_set_password (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_set_password (TLS, ARG2STR_DEF(0, "empty"), print_success_gw, ev); } /* }}} */ /* {{{ SENDING MESSAGES */ void do_msg (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } vlogprintf (E_DEBUG, "reply_id=%d, disable=%d\n", reply_id, disable_msg_preview); tgl_do_send_message (TLS, args[0].peer_id, ARG2STR(1), TGL_SEND_MSG_FLAG_REPLY(reply_id) | disable_msg_preview | do_html, NULL, print_msg_success_gw, ev); } void do_post (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } vlogprintf (E_DEBUG, "reply_id=%d, disable=%d\n", reply_id, disable_msg_preview); tgl_do_send_message (TLS, args[0].peer_id, ARG2STR(1), TGL_SEND_MSG_FLAG_REPLY(reply_id) | disable_msg_preview | TGLMF_POST_AS_CHANNEL | do_html, NULL, print_msg_success_gw, ev); } void do_msg_kbd (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 3); if (ev) { ev->refcnt ++; } clear_packet (); if (tglf_store_type (TLS, ARG2STR(1), TYPE_TO_PARAM (reply_markup)) < 0) { fail_interface (TLS, ev, ENOSYS, "can not parse reply markup"); return; } in_ptr = packet_buffer; in_end = packet_ptr; struct tl_ds_reply_markup *DS_RM = fetch_ds_type_reply_markup (TYPE_TO_PARAM (reply_markup)); assert (DS_RM); tgl_do_send_message (TLS, args[0].peer_id, ARG2STR(2), TGL_SEND_MSG_FLAG_REPLY(reply_id) | disable_msg_preview | do_html, DS_RM, print_msg_success_gw, ev); free_ds_type_reply_markup (DS_RM, TYPE_TO_PARAM (reply_markup)); } void do_reply (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_do_reply_message (TLS, &args[0].msg_id, ARG2STR(1), disable_msg_preview | do_html, print_msg_success_gw, ev); } void do_send_text (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_do_send_text (TLS, args[0].peer_id, args[1].str, TGL_SEND_MSG_FLAG_REPLY(reply_id) | disable_msg_preview | do_html, print_msg_success_gw, ev); } void do_post_text (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_do_send_text (TLS, args[0].peer_id, args[1].str, TGL_SEND_MSG_FLAG_REPLY(reply_id) | disable_msg_preview | TGLMF_POST_AS_CHANNEL | do_html, print_msg_success_gw, ev); } void do_reply_text (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_do_reply_text (TLS, &args[0].msg_id, args[1].str, disable_msg_preview | do_html, print_msg_success_gw, ev); } static void _do_send_file (struct command *command, int arg_num, struct arg args[], struct in_ev *ev, unsigned long long flags) { assert (arg_num >= 2); if (ev) { ev->refcnt ++; } tgl_do_send_document (TLS, args[0].peer_id, args[1].str, arg_num == 2 ? NULL : args[2].str, arg_num == 2 ? 0 : strlen (args[2].str), flags | TGL_SEND_MSG_FLAG_REPLY (reply_id), print_msg_success_gw, ev); } void do_send_photo (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { _do_send_file (command, arg_num, args, ev, TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO); } void do_send_file (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { _do_send_file (command, arg_num, args, ev, TGL_SEND_MSG_FLAG_DOCUMENT_AUTO); } void do_send_audio (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { _do_send_file (command, arg_num, args, ev, TGL_SEND_MSG_FLAG_DOCUMENT_AUDIO); } void do_send_video (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { _do_send_file (command, arg_num, args, ev, TGL_SEND_MSG_FLAG_DOCUMENT_VIDEO); } void do_send_document (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { _do_send_file (command, arg_num, args, ev, 0); } void do_post_photo (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { _do_send_file (command, arg_num, args, ev, TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO | TGLMF_POST_AS_CHANNEL); } void do_post_file (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { _do_send_file (command, arg_num, args, ev, TGL_SEND_MSG_FLAG_DOCUMENT_AUTO | TGLMF_POST_AS_CHANNEL); } void do_post_audio (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { _do_send_file (command, arg_num, args, ev, TGL_SEND_MSG_FLAG_DOCUMENT_AUDIO | TGLMF_POST_AS_CHANNEL); } void do_post_video (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { _do_send_file (command, arg_num, args, ev, TGL_SEND_MSG_FLAG_DOCUMENT_VIDEO | TGLMF_POST_AS_CHANNEL); } void do_post_document (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { _do_send_file (command, arg_num, args, ev, TGLMF_POST_AS_CHANNEL); } void _do_reply_file (struct command *command, int arg_num, struct arg args[], struct in_ev *ev, unsigned long long flags) { assert (arg_num >= 2); if (ev) { ev->refcnt ++; } tgl_do_reply_document (TLS, &args[0].msg_id, args[1].str, arg_num == 2 ? NULL : args[2].str, arg_num == 2 ? 0 : strlen (args[2].str), flags, print_msg_success_gw, ev); } void do_reply_photo (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { _do_reply_file (command, arg_num, args, ev, TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO); } void do_reply_file (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { _do_reply_file (command, arg_num, args, ev, TGL_SEND_MSG_FLAG_DOCUMENT_AUTO); } void do_reply_audio (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { _do_reply_file (command, arg_num, args, ev, TGL_SEND_MSG_FLAG_DOCUMENT_AUDIO); } void do_reply_video (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { _do_reply_file (command, arg_num, args, ev, TGL_SEND_MSG_FLAG_DOCUMENT_VIDEO); } void do_reply_document (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { _do_reply_file (command, arg_num, args, ev, 0); } void do_fwd (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num >= 2); if (ev) { ev->refcnt ++; } assert (arg_num <= 1000); //if (arg_num == 2) { // tgl_do_forward_message (TLS, args[0].P->id, &args[1].msg_id, 0, print_msg_success_gw, ev); //} else { static tgl_message_id_t *list[1000]; int i; for (i = 0; i < arg_num - 1; i++) { list[i] = &args[i + 1].msg_id; } tgl_do_forward_messages (TLS, args[0].peer_id, arg_num - 1, (void *)list, 0, print_msg_list_success_gw, ev); //} } void do_fwd_media (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_do_forward_media (TLS, args[0].peer_id, &args[1].msg_id, 0, print_msg_success_gw, ev); } void do_send_contact (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 4); if (ev) { ev->refcnt ++; } tgl_do_send_contact (TLS, args[0].peer_id, ARG2STR (1), ARG2STR (2), ARG2STR (3), TGL_SEND_MSG_FLAG_REPLY(reply_id), print_msg_success_gw, ev); } void do_reply_contact (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 4); if (ev) { ev->refcnt ++; } tgl_do_reply_contact (TLS, &args[0].msg_id, ARG2STR (1), ARG2STR (2), ARG2STR (3), 0, print_msg_success_gw, ev); } void do_send_location (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 3); if (ev) { ev->refcnt ++; } tgl_do_send_location (TLS, args[0].peer_id, args[1].dval, args[2].dval, TGL_SEND_MSG_FLAG_REPLY(reply_id), print_msg_success_gw, ev); } void do_post_location (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 3); if (ev) { ev->refcnt ++; } tgl_do_send_location (TLS, args[0].peer_id, args[1].dval, args[2].dval, TGL_SEND_MSG_FLAG_REPLY(reply_id) | TGLMF_POST_AS_CHANNEL, print_msg_success_gw, ev); } void do_reply_location (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 3); if (ev) { ev->refcnt ++; } tgl_do_reply_location (TLS, &args[0].msg_id, args[1].dval, args[2].dval, 0, print_msg_success_gw, ev); } void do_broadcast (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num >= 1 && arg_num <= 1000); static tgl_peer_id_t ids[1000]; int i; for (i = 0; i < arg_num - 1; i++) { ids[i] = args[i].peer_id; } if (ev) { ev->refcnt ++; } tgl_do_send_broadcast (TLS, arg_num - 1, ids, args[arg_num - 1].str, strlen (args[arg_num - 1].str), disable_msg_preview | do_html, print_msg_list_success_gw, ev); } /* }}} */ /* {{{ EDITING SELF PROFILE */ void do_get_self(struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { if (ev) { ev->refcnt ++; } tgl_do_get_user_info (TLS, TLS->our_id, 0, print_user_info_gw, ev); } void do_set_profile_photo (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_set_profile_photo (TLS, args[0].str, print_success_gw, ev); } void do_set_profile_name (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_do_set_profile_name (TLS, ARG2STR (0), ARG2STR (1), print_user_gw, ev); } void do_set_username (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_set_username (TLS, ARG2STR (0), print_user_gw, ev); } void do_set_phone_number (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_set_phone_number (TLS, ARG2STR (0), print_success_gw, ev); } void do_status_online (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (!arg_num); if (ev) { ev->refcnt ++; } tgl_do_update_status (TLS, 1, print_success_gw, ev); } void do_status_offline (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (!arg_num); if (ev) { ev->refcnt ++; } tgl_do_update_status (TLS, 0, print_success_gw, ev); } void do_export_card (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (!arg_num); if (ev) { ev->refcnt ++; } tgl_do_export_card (TLS, print_card_gw, ev); } /* }}} */ /* {{{ WORKING WITH GROUP CHATS */ void do_chat_set_photo (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_do_set_chat_photo (TLS, args[0].peer_id, args[1].str, print_success_gw, ev); } void do_rename_chat (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_do_rename_chat (TLS, args[0].peer_id, ARG2STR (1), print_success_gw, ev); } void do_chat_info (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_get_chat_info (TLS, args[0].peer_id, offline_mode, print_chat_info_gw, ev); } void do_channel_info (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_get_channel_info (TLS, args[0].peer_id, offline_mode, print_channel_info_gw, ev); } void do_chat_add_user (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 3); if (ev) { ev->refcnt ++; } tgl_do_add_user_to_chat (TLS, args[0].peer_id, args[1].peer_id, args[2].num != NOT_FOUND ? args[2].num : 100, print_success_gw, ev); } void do_chat_del_user (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_do_del_user_from_chat (TLS, args[0].peer_id, args[1].peer_id, print_success_gw, ev); } void do_create_group_chat (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num >= 1 && arg_num <= 1000); static tgl_peer_id_t ids[1000]; int i; for (i = 0; i < arg_num - 1; i++) { ids[i] = args[i + 1].peer_id; } if (ev) { ev->refcnt ++; } tgl_do_create_group_chat (TLS, arg_num - 1, ids, ARG2STR (0), print_success_gw, ev); } void do_export_chat_link (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_export_chat_link (TLS, args[0].peer_id, print_string_gw, ev); } void do_import_chat_link (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_import_chat_link (TLS, ARG2STR (0), print_success_gw, ev); } void do_channel_invite (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_do_channel_invite_user (TLS, args[0].peer_id, args[1].peer_id, print_success_gw, ev); } void do_channel_kick (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_do_channel_kick_user (TLS, args[0].peer_id, args[1].peer_id, print_success_gw, ev); } void do_channel_get_members (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 3); if (ev) { ev->refcnt ++; } tgl_do_channel_get_members (TLS, args[0].peer_id, args[1].num == NOT_FOUND ? 100 : args[1].num, args[2].num == NOT_FOUND ? 0 : args[2].num, 0, print_user_list_gw, ev); } void do_channel_get_admins (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 3); if (ev) { ev->refcnt ++; } tgl_do_channel_get_members (TLS, args[0].peer_id, args[1].num == NOT_FOUND ? 100 : args[1].num, args[2].num == NOT_FOUND ? 0 : args[2].num, 1, print_user_list_gw, ev); } void do_chat_upgrade (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_upgrade_group (TLS, args[0].peer_id, print_success_gw, ev); } /* }}} */ /* {{{ WORKING WITH USERS */ void do_user_info (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_get_user_info (TLS, args[0].peer_id, offline_mode, print_user_info_gw, ev); } void do_add_contact (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 3); if (ev) { ev->refcnt ++; } tgl_do_add_contact (TLS, ARG2STR (0), ARG2STR (1), ARG2STR (2), 0, print_user_list_gw, ev); } void do_rename_contact (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 3); tgl_peer_t *P = tgl_peer_get (TLS, args[0].peer_id); if (P && P->user.phone) { if (ev) { ev->refcnt ++; } tgl_do_add_contact (TLS, P->user.phone, strlen (P->user.phone), args[1].str, strlen (args[1].str), args[2].str, strlen (args[2].str), 0, print_user_list_gw, ev); } else { if (ev) { ev->refcnt ++; } print_success_gw (TLS, ev, 0); } } void do_del_contact (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_del_contact (TLS, args[0].peer_id, print_success_gw, ev); } void do_import_card (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); char *s = args[0].str; int l = strlen (s); if (l > 0) { int i; static int p[10]; int pp = 0; int cur = 0; int ok = 1; for (i = 0; i < l; i ++) { if (s[i] >= '0' && s[i] <= '9') { cur = cur * 16 + s[i] - '0'; } else if (s[i] >= 'a' && s[i] <= 'f') { cur = cur * 16 + s[i] - 'a' + 10; } else if (s[i] == ':') { if (pp >= 9) { ok = 0; break; } p[pp ++] = cur; cur = 0; } } if (ok) { p[pp ++] = cur; if (ev) { ev->refcnt ++; } tgl_do_import_card (TLS, pp, p, print_user_gw, ev); } } } void do_block_user (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_block_user (TLS, args[0].peer_id, print_success_gw, ev); } void do_unblock_user (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_unblock_user (TLS, args[0].peer_id, print_success_gw, ev); } /* }}} */ /* {{{ WORKING WITH SECRET CHATS */ void do_accept_secret_chat (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_peer_t *P = tgl_peer_get (TLS, args[0].peer_id); if (P) { tgl_do_accept_encr_chat_request (TLS, &P->encr_chat, print_encr_chat_success_gw, ev); } else { print_success_gw (TLS, ev, 0); } } void do_set_ttl (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_peer_t *P = tgl_peer_get (TLS, args[0].peer_id); if (P && P->encr_chat.state == sc_ok) { tgl_do_set_encr_chat_ttl (TLS, &P->encr_chat, args[1].num, print_msg_success_gw, ev); } else { print_success_gw (TLS, ev, 0); } } void do_visualize_key (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); static char *colors[4] = {COLOR_GREY, COLOR_CYAN, COLOR_BLUE, COLOR_GREEN}; static unsigned char buf[16]; memset (buf, 0, sizeof (buf)); tgl_do_visualize_key (TLS, args[0].peer_id, buf); mprint_start (ev); int i; for (i = 0; i < 16; i++) { int x = buf[i]; int j; for (j = 0; j < 4; j ++) { if (!ev) { mpush_color (ev, colors[x & 3]); mpush_color (ev, COLOR_INVERSE); } if (!disable_colors && !ev) { mprintf (ev, " "); } else { switch (x & 3) { case 0: mprintf (ev, " "); break; case 1: mprintf (ev, "--"); break; case 2: mprintf (ev, "=="); break; case 3: mprintf (ev, "||"); break; } } if (!ev) { mpop_color (ev); mpop_color (ev); } x = x >> 2; } if (i & 1) { mprintf (ev, "\n"); } } mprint_end (ev); } void do_create_secret_chat (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_create_secret_chat (TLS, args[0].peer_id, print_secret_chat_gw, ev); } /* }}} */ /* WORKING WITH CHANNELS {{{ */ void do_rename_channel (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_do_rename_channel (TLS, args[0].peer_id, ARG2STR (1), print_success_gw, ev); } void do_channel_set_photo (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_do_set_channel_photo (TLS, args[0].peer_id, args[1].str, print_success_gw, ev); } void do_channel_set_about (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_do_channel_set_about (TLS, args[0].peer_id, ARG2STR (1), print_success_gw, ev); } void do_channel_set_admin (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 3); if (ev) { ev->refcnt ++; } tgl_do_channel_set_admin (TLS, args[0].peer_id, args[1].peer_id, args[2].num, print_success_gw, ev); } void do_channel_set_username (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); if (ev) { ev->refcnt ++; } tgl_do_channel_set_username (TLS, args[0].peer_id, ARG2STR (1), print_success_gw, ev); } void do_create_channel (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num >= 2 && arg_num <= 1000); static tgl_peer_id_t ids[1000]; int i; for (i = 0; i < arg_num - 2; i++) { ids[i] = args[i + 2].peer_id; } if (ev) { ev->refcnt ++; } tgl_do_create_channel (TLS, arg_num - 2, ids, ARG2STR (0), ARG2STR (1), 1, print_success_gw, ev); } void do_join_channel (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_join_channel (TLS, args[0].peer_id, print_success_gw, ev); } void do_leave_channel (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_leave_channel (TLS, args[0].peer_id, print_success_gw, ev); } void do_export_channel_link (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_export_channel_link (TLS, args[0].peer_id, print_string_gw, ev); } /* }}} */ /* {{{ WORKING WITH DIALOG LIST */ void do_dialog_list (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num <= 2); if (ev) { ev->refcnt ++; } tgl_do_get_dialog_list (TLS, args[0].num != NOT_FOUND ? args[0].num : 100, args[1].num != NOT_FOUND ? args[1].num : 0, print_dialog_list_gw, ev); } void do_channel_list (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num <= 2); if (ev) { ev->refcnt ++; } tgl_do_get_channels_dialog_list (TLS, args[0].num != NOT_FOUND ? args[0].num : 100, args[1].num != NOT_FOUND ? args[1].num : 0, print_dialog_list_gw, ev); } void do_resolve_username (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_contact_search (TLS, args[0].str, strlen (args[0].str), print_peer_gw, ev); } void do_contact_list (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (!arg_num); if (ev) { ev->refcnt ++; } tgl_do_update_contact_list (TLS, print_user_list_gw, ev); } /* }}} */ /* {{{ WORKING WITH ONE DIALOG */ void do_mark_read (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_mark_read (TLS, args[0].peer_id, print_success_gw, ev); } void do_history (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 3); if (ev) { ev->refcnt ++; } tgl_do_get_history (TLS, args[0].peer_id, args[2].num != NOT_FOUND ? args[2].num : 0, args[1].num != NOT_FOUND ? args[1].num : 40, offline_mode, print_msg_list_history_gw, ev); } void print_fail (struct in_ev *ev); void do_send_typing (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 2); enum tgl_typing_status status = tgl_typing_typing; //de if (args[1].num != NOT_FOUND) { if (args[1].num > 0 && args[1].num > 10) { fail_interface (TLS, ev, ENOSYS, "illegal typing status"); return; } status = (enum tgl_typing_status) args[1].num; // if the status parameter is given, and is in range. } if (ev) { ev->refcnt ++; } tgl_do_send_typing (TLS, args[0].peer_id, status, print_success_gw, ev); } void do_send_typing_abort (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_send_typing (TLS, args[0].peer_id, tgl_typing_cancel, print_success_gw, ev); } /* }}} */ /* {{{ WORKING WITH MEDIA */ #define DO_LOAD_PHOTO(tp,act,actf) \ void do_ ## act ## _ ## tp (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { \ assert (arg_num == 1);\ struct tgl_message *M = tgl_message_get (TLS, &args[0].msg_id);\ if (M && !(M->flags & TGLMF_SERVICE)) {\ if (ev) { ev->refcnt ++; } \ if (M->media.type == tgl_message_media_photo) { \ tgl_do_load_photo (TLS, M->media.photo, actf, ev);\ } else if (M->media.type == tgl_message_media_document) {\ tgl_do_load_document (TLS, M->media.document, actf, ev);\ } else if (M->media.type == tgl_message_media_video) {\ tgl_do_load_video (TLS, M->media.document, actf, ev);\ } else if (M->media.type == tgl_message_media_audio) {\ tgl_do_load_audio (TLS, M->media.document, actf, ev);\ } else if (M->media.type == tgl_message_media_document_encr) {\ tgl_do_load_encr_document (TLS, M->media.encr_document, actf, ev); \ } else if (M->media.type == tgl_message_media_webpage) {\ actf (TLS, ev, 1, M->media.webpage->url);\ } else if (M->media.type == tgl_message_media_geo || M->media.type == tgl_message_media_venue) { \ static char s[1000]; \ sprintf (s, "https://maps.google.com/?q=%.6lf,%.6lf", M->media.geo.latitude, M->media.geo.longitude);\ actf (TLS, ev, 1, s);\ }\ }\ } #define DO_LOAD_PHOTO_THUMB(tp,act,actf) \ void do_ ## act ## _ ## tp ## _thumb (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { \ assert (arg_num == 1);\ struct tgl_message *M = tgl_message_get (TLS, &args[0].msg_id);\ if (M && !(M->flags & TGLMF_SERVICE)) {\ if (M->media.type == tgl_message_media_document) {\ if (ev) { ev->refcnt ++; } \ tgl_do_load_document_thumb (TLS, M->media.document, actf, ev);\ }\ }\ } DO_LOAD_PHOTO(photo, load, print_filename_gw) DO_LOAD_PHOTO(video, load, print_filename_gw) DO_LOAD_PHOTO(audio, load, print_filename_gw) DO_LOAD_PHOTO(document, load, print_filename_gw) DO_LOAD_PHOTO(file, load, print_filename_gw) DO_LOAD_PHOTO_THUMB(video, load, print_filename_gw) DO_LOAD_PHOTO_THUMB(document, load, print_filename_gw) DO_LOAD_PHOTO_THUMB(file, load, print_filename_gw) DO_LOAD_PHOTO(photo, open, open_filename_gw) DO_LOAD_PHOTO(video, open, open_filename_gw) DO_LOAD_PHOTO(audio, open, open_filename_gw) DO_LOAD_PHOTO(document, open, open_filename_gw) DO_LOAD_PHOTO(file, open, open_filename_gw) DO_LOAD_PHOTO_THUMB(video, open, open_filename_gw) DO_LOAD_PHOTO_THUMB(document, open, open_filename_gw) DO_LOAD_PHOTO_THUMB(file, open, open_filename_gw) DO_LOAD_PHOTO(any, open, open_filename_gw) void do_load_user_photo (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_peer_t *P = tgl_peer_get (TLS, args[0].peer_id); if (P) { tgl_do_load_file_location (TLS, &P->user.photo_big, print_filename_gw, ev); } else { print_filename_gw (TLS, ev, 0, NULL); } } void do_view_user_photo (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_peer_t *P = tgl_peer_get (TLS, args[0].peer_id); if (P) { tgl_do_load_file_location (TLS, &P->user.photo_big, print_filename_gw, ev); } else { open_filename_gw (TLS, ev, 0, NULL); } } /* }}} */ /* {{{ ANOTHER MESSAGES FUNCTIONS */ void do_search (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 6); int limit; if (args[1].num != NOT_FOUND) { limit = args[1].num; } else { limit = 40; } int from; if (args[2].num != NOT_FOUND) { from = args[2].num; } else { from = 0; } int to; if (args[3].num != NOT_FOUND) { to = args[3].num; } else { to = 0; } int offset; if (args[4].num != NOT_FOUND) { offset = args[4].num; } else { offset = 0; } if (ev) { ev->refcnt ++; } tgl_do_msg_search (TLS, args[0].peer_id, from, to, limit, offset, args[5].str, strlen (args[5].str), print_msg_list_gw, ev); } void do_delete_msg (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { if (ev) { ev->refcnt ++; } tgl_do_delete_msg (TLS, &args[0].msg_id, print_success_gw, ev); } void do_get_message (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 1); if (ev) { ev->refcnt ++; } tgl_do_get_message (TLS, &args[0].msg_id, print_msg_gw, ev); } /* }}} */ /* {{{ BOT */ void do_start_bot (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { assert (arg_num == 3); if (ev) { ev->refcnt ++; } tgl_do_start_bot (TLS, args[0].peer_id, args[1].peer_id, ARG2STR(2), print_success_gw, ev); } /* }}} */ extern char *default_username; extern char *config_filename; extern char *prefix; extern char *auth_file_name; extern char *state_file_name; extern char *secret_chat_file_name; extern char *downloads_directory; extern char *config_directory; extern char *binlog_file_name; extern char *lua_file; extern char *python_file; extern struct event *term_ev; void do_clear (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { logprintf ("Do_clear\n"); free (default_username); tfree_str (config_filename); //free (prefix); tfree_str (auth_file_name); tfree_str (state_file_name); tfree_str (secret_chat_file_name); tfree_str (downloads_directory); //tfree_str (config_directory); tfree_str (binlog_file_name); tfree_str (lua_file); tfree_str (python_file); if (home_directory) { tfree_str (home_directory); } clear_history (); event_free (term_ev); struct event_base *ev_base = TLS->ev_base; tgl_free_all (TLS); event_base_free (ev_base); logprintf ("Bytes left allocated: %lld\n", tgl_get_allocated_bytes ()); do_halt (0); } #define MAX_COMMANDS_SIZE 1000 struct command commands[MAX_COMMANDS_SIZE] = { {"accept_secret_chat", {ca_secret_chat, ca_none}, do_accept_secret_chat, "accept_secret_chat \tAccepts secret chat. Only useful with -E option", NULL}, {"add_contact", {ca_string, ca_string, ca_string, ca_none}, do_add_contact, "add_contact \tTries to add user to contact list", NULL}, {"block_user", {ca_user, ca_none}, do_block_user, "block_user \tBlocks user", NULL}, {"broadcast", {ca_user, ca_period, ca_string_end, ca_none}, do_broadcast, "broadcast + \tSends text to several users at once", NULL}, {"channel_get_admins", {ca_channel, ca_number | ca_optional, ca_number | ca_optional, ca_none}, do_channel_get_admins, "channel_get_admins [limit=100] [offset=0]\tGets channel admins", NULL}, {"channel_get_members", {ca_channel, ca_number | ca_optional, ca_number | ca_optional, ca_none}, do_channel_get_members, "channel_get_members [limit=100] [offset=0]\tGets channel members", NULL}, {"channel_info", {ca_channel, ca_none}, do_channel_info, "channel_info \tPrints info about channel (id, members, admin, etc.)", NULL}, {"channel_invite", {ca_channel, ca_user, ca_none}, do_channel_invite, "channel_invite \tInvites user to channel", NULL}, {"channel_join", {ca_channel, ca_none}, do_join_channel, "channel_join \tJoins to channel", NULL}, {"channel_kick", {ca_channel, ca_user, ca_none}, do_channel_kick, "channel_kick \tKicks user from channel", NULL}, {"channel_leave", {ca_channel, ca_none}, do_leave_channel, "channel_leave \tLeaves from channel", NULL}, {"channel_list", {ca_number | ca_optional, ca_number | ca_optional, ca_none}, do_channel_list, "channel_list [limit=100] [offset=0]\tList of last channels", NULL}, {"channel_set_about", {ca_channel, ca_string, ca_none}, do_channel_set_about, "channel_set_about \tSets channel about info.", NULL}, {"channel_set_admin", {ca_channel, ca_user, ca_number, ca_none}, do_channel_set_admin, "channel_set_admin \tSets channel admin. 0 - not admin, 1 - moderator, 2 - editor", NULL}, {"channel_set_username", {ca_channel, ca_string, ca_none}, do_channel_set_username, "channel_set_username \tSets channel username info.", NULL}, {"channel_set_photo", {ca_channel, ca_file_name_end, ca_none}, do_channel_set_photo, "channel_set_photo \tSets channel photo. Photo will be cropped to square", NULL}, {"chat_add_user", {ca_chat, ca_user, ca_number | ca_optional, ca_none}, do_chat_add_user, "chat_add_user [msgs-to-forward]\tAdds user to chat. Sends him last msgs-to-forward message from this chat. Default 100", NULL}, {"chat_del_user", {ca_chat, ca_user, ca_none}, do_chat_del_user, "chat_del_user \tDeletes user from chat", NULL}, {"chat_info", {ca_chat, ca_none}, do_chat_info, "chat_info \tPrints info about chat (id, members, admin, etc.)", NULL}, {"chat_set_photo", {ca_chat, ca_file_name_end, ca_none}, do_chat_set_photo, "chat_set_photo \tSets chat photo. Photo will be cropped to square", NULL}, {"chat_upgrade", {ca_chat, ca_none}, do_chat_upgrade, "chat_upgrade \tUpgrades chat to megagroup", NULL}, {"chat_with_peer", {ca_peer, ca_none}, do_chat_with_peer, "chat_with_peer \tInterface option. All input will be treated as messages to this peer. Type /quit to end this mode", NULL}, {"clear", {ca_none}, do_clear, "clear\tClears all data and exits. For debug.", NULL}, {"contact_list", {ca_none}, do_contact_list, "contact_list\tPrints contact list", NULL}, {"contact_search", {ca_string, ca_none}, do_resolve_username, "contact_search username\tSearches user by username", NULL}, {"create_channel", {ca_string, ca_string, ca_user | ca_optional, ca_period, ca_none}, do_create_channel, "create_channel +\tCreates channel with users", NULL}, {"create_group_chat", {ca_string, ca_user, ca_period, ca_none}, do_create_group_chat, "create_group_chat +\tCreates group chat with users", NULL}, {"create_secret_chat", {ca_user, ca_none}, do_create_secret_chat, "create_secret_chat \tStarts creation of secret chat", NULL}, {"del_contact", {ca_user, ca_none}, do_del_contact, "del_contact \tDeletes contact from contact list", NULL}, {"delete_msg", {ca_msg_id, ca_none}, do_delete_msg, "delete_msg \tDeletes message", NULL}, {"dialog_list", {ca_number | ca_optional, ca_number | ca_optional, ca_none}, do_dialog_list, "dialog_list [limit=100] [offset=0]\tList of last conversations", NULL}, {"export_card", {ca_none}, do_export_card, "export_card\tPrints card that can be imported by another user with import_card method", NULL}, {"export_channel_link", {ca_channel, ca_none}, do_export_channel_link, "export_channel_link\tPrints channel link that can be used to join to channel", NULL}, {"export_chat_link", {ca_chat, ca_none}, do_export_chat_link, "export_chat_link\tPrints chat link that can be used to join to chat", NULL}, {"fwd", {ca_peer, ca_msg_id, ca_period, ca_none}, do_fwd, "fwd +\tForwards message to peer. Forward to secret chats is forbidden", NULL}, {"fwd_media", {ca_peer, ca_msg_id, ca_none}, do_fwd_media, "fwd_media \tForwards message media to peer. Forward to secret chats is forbidden. Result slightly differs from fwd", NULL}, {"get_terms_of_service", {ca_none}, do_get_terms_of_service, "get_terms_of_service\tPrints telegram's terms of service", NULL}, {"get_message", {ca_msg_id, ca_none}, do_get_message, "get_message \tGet message by id", NULL}, {"get_self", {ca_none}, do_get_self, "get_self \tGet our user info", NULL}, {"help", {ca_command | ca_optional, ca_none}, do_help, "help [command]\tPrints this help", NULL}, {"history", {ca_peer, ca_number | ca_optional, ca_number | ca_optional, ca_none}, do_history, "history [limit] [offset]\tPrints messages with this peer (most recent message lower). Also marks messages as read", NULL}, {"import_card", {ca_string, ca_none}, do_import_card, "import_card \tGets user by card and prints it name. You can then send messages to him as usual", NULL}, {"import_chat_link", {ca_string, ca_none}, do_import_chat_link, "import_chat_link \tJoins to chat by link", NULL}, {"import_channel_link", {ca_string, ca_none}, do_import_chat_link, "import_channel_link \tJoins to channel by link", NULL}, {"load_audio", {ca_msg_id, ca_none}, do_load_audio, "load_audio \tDownloads file to downloads dirs. Prints file name after download end", NULL}, {"load_channel_photo", {ca_channel, ca_none}, do_load_user_photo, "load_channel_photo \tDownloads file to downloads dirs. Prints file name after download end", NULL}, {"load_chat_photo", {ca_chat, ca_none}, do_load_user_photo, "load_chat_photo \tDownloads file to downloads dirs. Prints file name after download end", NULL}, {"load_document", {ca_msg_id, ca_none}, do_load_document, "load_document \tDownloads file to downloads dirs. Prints file name after download end", NULL}, {"load_document_thumb", {ca_msg_id, ca_none}, do_load_document_thumb, "load_document_thumb \tDownloads file to downloads dirs. Prints file name after download end", NULL}, {"load_file", {ca_msg_id, ca_none}, do_load_file, "load_file \tDownloads file to downloads dirs. Prints file name after download end", NULL}, {"load_file_thumb", {ca_msg_id, ca_none}, do_load_file_thumb, "load_file_thumb \tDownloads file to downloads dirs. Prints file name after download end", NULL}, {"load_photo", {ca_msg_id, ca_none}, do_load_photo, "load_photo \tDownloads file to downloads dirs. Prints file name after download end", NULL}, {"load_user_photo", {ca_user, ca_none}, do_load_user_photo, "load_user_photo \tDownloads file to downloads dirs. Prints file name after download end", NULL}, {"load_video", {ca_msg_id, ca_none}, do_load_video, "load_video \tDownloads file to downloads dirs. Prints file name after download end", NULL}, {"load_video_thumb", {ca_msg_id, ca_none}, do_load_video_thumb, "load_video_thumb \tDownloads file to downloads dirs. Prints file name after download end", NULL}, {"main_session", {ca_none}, do_main_session, "main_session\tSends updates to this connection (or terminal). Useful only with listening socket", NULL}, {"mark_read", {ca_peer, ca_none}, do_mark_read, "mark_read \tMarks messages with peer as read", NULL}, {"msg", {ca_peer, ca_msg_string_end, ca_none}, do_msg, "msg \tSends text message to peer", NULL}, {"msg_kbd", {ca_peer, ca_string, ca_msg_string_end, ca_none}, do_msg_kbd, "msg \tSends text message to peer with custom kbd", NULL}, {"post", {ca_peer, ca_msg_string_end, ca_none}, do_post, "post \tSends text message to peer as admin", NULL}, {"post_audio", {ca_peer, ca_file_name, ca_none}, do_post_audio, "post_audio \tPosts audio to peer", NULL}, {"post_document", {ca_peer, ca_file_name, ca_none}, do_post_document, "post_document \tPosts document to peer", NULL}, {"post_file", {ca_peer, ca_file_name, ca_none}, do_post_file, "post_file \tSends document to peer", NULL}, {"post_location", {ca_peer, ca_double, ca_double, ca_none}, do_post_location, "post_location \tSends geo location", NULL}, {"post_photo", {ca_peer, ca_file_name, ca_string_end | ca_optional, ca_none}, do_post_photo, "post_photo [caption]\tSends photo to peer", NULL}, {"post_text", {ca_peer, ca_file_name_end, ca_none}, do_post_text, "post_text \tSends contents of text file as plain text message", NULL}, {"post_video", {ca_peer, ca_file_name, ca_string_end | ca_optional, ca_none}, do_post_video, "post_video [caption]\tSends video to peer", NULL}, {"quit", {ca_none}, do_quit, "quit\tQuits immediately", NULL}, {"rename_channel", {ca_channel, ca_string_end, ca_none}, do_rename_channel, "rename_channel \tRenames channel", NULL}, {"rename_chat", {ca_chat, ca_string_end, ca_none}, do_rename_chat, "rename_chat \tRenames chat", NULL}, {"rename_contact", {ca_user, ca_string, ca_string, ca_none}, do_rename_contact, "rename_contact \tRenames contact", NULL}, {"reply", {ca_msg_id, ca_msg_string_end, ca_none}, do_reply, "reply \tSends text reply to message", NULL}, {"reply_audio", {ca_msg_id, ca_file_name, ca_none}, do_send_audio, "reply_audio \tSends audio to peer", NULL}, {"reply_contact", {ca_msg_id, ca_string, ca_string, ca_string, ca_none}, do_reply_contact, "reply_contact \tSends contact (not necessary telegram user)", NULL}, {"reply_document", {ca_msg_id, ca_file_name, ca_none}, do_reply_document, "reply_document \tSends document to peer", NULL}, {"reply_file", {ca_msg_id, ca_file_name, ca_none}, do_reply_file, "reply_file \tSends document to peer", NULL}, {"reply_location", {ca_msg_id, ca_double, ca_double, ca_none}, do_reply_location, "reply_location \tSends geo location", NULL}, {"reply_photo", {ca_msg_id, ca_file_name, ca_string_end | ca_optional, ca_none}, do_reply_photo, "reply_photo [caption]\tSends photo to peer", NULL}, //{"reply_text", {ca_number, ca_file_name_end, ca_none}, do_reply_text, "reply_text \tSends contents of text file as plain text message", NULL}, {"reply_video", {ca_msg_id, ca_file_name, ca_none}, do_reply_video, "reply_video \tSends video to peer", NULL}, {"resolve_username", {ca_string, ca_none}, do_resolve_username, "resolve_username username\tSearches user by username", NULL}, //{"restore_msg", {ca_number, ca_none}, do_restore_msg, "restore_msg \tRestores message. Only available shortly (one hour?) after deletion", NULL}, {"safe_quit", {ca_none}, do_safe_quit, "safe_quit\tWaits for all queries to end, then quits", NULL}, {"search", {ca_peer | ca_optional, ca_number | ca_optional, ca_number | ca_optional, ca_number | ca_optional, ca_number | ca_optional, ca_string_end}, do_search, "search [peer] [limit] [from] [to] [offset] pattern\tSearch for pattern in messages from date from to date to (unixtime) in messages with peer (if peer not present, in all messages)", NULL}, //{"secret_chat_rekey", { ca_secret_chat, ca_none}, do_secret_chat_rekey, "generate new key for active secret chat", NULL}, {"send_audio", {ca_peer, ca_file_name, ca_string_end | ca_optional, ca_none}, do_send_audio, "send_audio \tSends audio to peer", NULL}, {"send_contact", {ca_peer, ca_string, ca_string, ca_string, ca_none}, do_send_contact, "send_contact \tSends contact (not necessary telegram user)", NULL}, {"send_document", {ca_peer, ca_file_name, ca_string_end | ca_optional, ca_none}, do_send_document, "send_document \tSends document to peer", NULL}, {"send_file", {ca_peer, ca_file_name, ca_string_end | ca_optional, ca_none}, do_send_file, "send_file \tSends document to peer", NULL}, {"send_location", {ca_peer, ca_double, ca_double, ca_none}, do_send_location, "send_location \tSends geo location", NULL}, {"send_photo", {ca_peer, ca_file_name, ca_string_end | ca_optional, ca_none}, do_send_photo, "send_photo [caption]\tSends photo to peer", NULL}, {"send_text", {ca_peer, ca_file_name_end, ca_none}, do_send_text, "send_text \tSends contents of text file as plain text message", NULL}, {"send_typing", {ca_peer, ca_number | ca_optional, ca_none}, do_send_typing, "send_typing [status]\tSends typing notification. You can supply a custom status (range 0-10): none, typing, cancel, record video, upload video, record audio, upload audio, upload photo, upload document, geo, choose contact.", NULL}, {"send_typing_abort", {ca_peer, ca_none}, do_send_typing_abort, "send_typing_abort \tSends typing notification abort", NULL}, {"send_video", {ca_peer, ca_file_name, ca_string_end | ca_optional, ca_none}, do_send_video, "send_video [caption]\tSends video to peer", NULL}, {"set", {ca_string, ca_number, ca_none}, do_set, "set \tSets value of param. Currently available: log_level, debug_verbosity, alarm, msg_num", NULL}, {"set_password", {ca_string | ca_optional, ca_none}, do_set_password, "set_password \tSets password", NULL}, {"set_profile_name", {ca_string, ca_string, ca_none}, do_set_profile_name, "set_profile_name \tSets profile name.", NULL}, {"set_profile_photo", {ca_file_name_end, ca_none}, do_set_profile_photo, "set_profile_photo \tSets profile photo. Photo will be cropped to square", NULL}, {"set_ttl", {ca_secret_chat, ca_number, ca_none}, do_set_ttl, "set_ttl \tSets secret chat ttl. Client itself ignores ttl", NULL}, {"set_username", {ca_string, ca_none}, do_set_username, "set_username \tSets username.", NULL}, {"set_phone_number", {ca_string, ca_none}, do_set_phone_number, "set_phone_number \tChanges the phone number of this account", NULL}, {"show_license", {ca_none}, do_show_license, "show_license\tPrints contents of GPL license", NULL}, {"start_bot", {ca_user, ca_chat, ca_string, ca_none}, do_start_bot, "start_bot \tAdds bot to chat", NULL}, {"stats", {ca_none}, do_stats, "stats\tFor debug purpose", NULL}, {"status_online", {ca_none}, do_status_online, "status_online\tSets status as online", NULL}, {"status_offline", {ca_none}, do_status_offline, "status_offline\tSets status as offline", NULL}, {"unblock_user", {ca_user, ca_none}, do_unblock_user, "unblock_user \tUnblocks user", NULL}, {"user_info", {ca_user, ca_none}, do_user_info, "user_info \tPrints info about user (id, last online, phone)", NULL}, {"version", {ca_none}, do_version, "version\tPrints client and library version", NULL}, {"view_audio", {ca_msg_id, ca_none}, do_open_audio, "view_audio \tDownloads file to downloads dirs. Then tries to open it with system default action", NULL}, {"view_channel_photo", {ca_channel, ca_none}, do_view_user_photo, "view_channel_photo \tDownloads file to downloads dirs. Then tries to open it with system default action", NULL}, {"view_chat_photo", {ca_chat, ca_none}, do_view_user_photo, "view_chat_photo \tDownloads file to downloads dirs. Then tries to open it with system default action", NULL}, {"view_document", {ca_msg_id, ca_none}, do_open_document, "view_document \tDownloads file to downloads dirs. Then tries to open it with system default action", NULL}, {"view_document_thumb", {ca_msg_id, ca_none}, do_open_document_thumb, "view_document_thumb \tDownloads file to downloads dirs. Then tries to open it with system default action", NULL}, {"view_file", {ca_msg_id, ca_none}, do_open_file, "view_file \tDownloads file to downloads dirs. Then tries to open it with system default action", NULL}, {"view_file_thumb", {ca_msg_id, ca_none}, do_open_file_thumb, "view_file_thumb \tDownloads file to downloads dirs. Then tries to open it with system default action", NULL}, {"view_photo", {ca_msg_id, ca_none}, do_open_photo, "view_photo \tDownloads file to downloads dirs. Then tries to open it with system default action", NULL}, {"view_user_photo", {ca_user, ca_none}, do_view_user_photo, "view_user_photo \tDownloads file to downloads dirs. Then tries to open it with system default action", NULL}, {"view_video", {ca_msg_id, ca_none}, do_open_video, "view_video \tDownloads file to downloads dirs. Then tries to open it with system default action", NULL}, {"view_video_thumb", {ca_msg_id, ca_none}, do_open_video_thumb, "view_video_thumb \tDownloads file to downloads dirs. Then tries to open it with system default action", NULL}, {"view", {ca_msg_id, ca_none}, do_open_any, "view \tTries to view message contents", NULL}, {"visualize_key", {ca_secret_chat, ca_none}, do_visualize_key, "visualize_key \tPrints visualization of encryption key (first 16 bytes sha1 of it in fact)", NULL} }; void register_new_command (struct command *cmd) { int i = 0; while (commands[i].name) { i ++; } assert (i < MAX_COMMANDS_SIZE - 1); commands[i] = *cmd; } tgl_peer_t *autocomplete_peer; tgl_message_id_t autocomplete_id; enum command_argument get_complete_mode (void) { force_end_mode = 0; line_ptr = rl_line_buffer; autocomplete_peer = NULL; autocomplete_id.peer_type = NOT_FOUND; while (1) { next_token (); if (cur_token_quoted) { return ca_none; } if (cur_token_len <= 0) { return ca_command; } if (*cur_token == '[') { if (cur_token_end_str) { return ca_modifier; } if (cur_token[cur_token_len - 1] != ']') { return ca_none; } continue; } break; } if (cur_token_quoted) { return ca_none; } if (cur_token_end_str) { return ca_command; } if (*cur_token == '(') { return ca_extf; } struct command *command = commands; int n = 0; struct tgl_command; while (command->name) { if (is_same_word (cur_token, cur_token_len, command->name)) { break; } n ++; command ++; } if (!command->name) { return ca_none; } enum command_argument *flags = command->args; while (1) { int period = 0; if (*flags == ca_period) { flags --; period = 1; } enum command_argument op = (*flags) & 255; int opt = (*flags) & ca_optional; if (op == ca_none) { return ca_none; } if (op == ca_string_end || op == ca_file_name_end || op == ca_msg_string_end) { next_token_end_ac (); if (cur_token_len < 0 || !cur_token_end_str) { return ca_none; } else { return op; } } char *save = line_ptr; next_token (); if (op == ca_user || op == ca_chat || op == ca_secret_chat || op == ca_peer || op == ca_number || op == ca_double || op == ca_msg_id || op == ca_command || op == ca_channel) { if (cur_token_quoted) { if (opt) { line_ptr = save; flags ++; continue; } else if (period) { line_ptr = save; flags += 2; continue; } else { return ca_none; } } else { if (cur_token_end_str) { return op; } int ok = 1; switch (op) { case ca_user: ok = (tgl_get_peer_type (cur_token_user ()) != NOT_FOUND); break; case ca_chat: ok = (tgl_get_peer_type (cur_token_chat ()) != NOT_FOUND); break; case ca_secret_chat: ok = (tgl_get_peer_type (cur_token_encr_chat ()) != NOT_FOUND); break; case ca_channel: ok = (tgl_get_peer_type (cur_token_channel ()) != NOT_FOUND); break; case ca_peer: ok = (tgl_get_peer_type (cur_token_peer ()) != NOT_FOUND); if (ok) { autocomplete_peer = tgl_peer_get (TLS, cur_token_peer ()); autocomplete_id.peer_type = NOT_FOUND; } break; case ca_number: ok = (cur_token_int () != NOT_FOUND); break; case ca_msg_id: ok = (cur_token_msg_id ().peer_type != 0); if (ok) { autocomplete_peer = NULL; autocomplete_id = cur_token_msg_id (); } break; case ca_double: ok = (cur_token_double () != NOT_FOUND); break; case ca_command: ok = cur_token_len > 0; break; default: assert (0); } if (opt && !ok) { line_ptr = save; flags ++; continue; } if (period && !ok) { line_ptr = save; flags += 2; continue; } if (!ok) { return ca_none; } flags ++; continue; } } if (op == ca_string || op == ca_file_name) { if (cur_token_end_str) { return op; } else { flags ++; continue; } } assert (0); } } int complete_string_list (char **list, int index, const char *text, int len, char **R) { index ++; while (list[index] && strncmp (list[index], text, len)) { index ++; } if (list[index]) { *R = strdup (list[index]); assert (*R); return index; } else { *R = 0; return -1; } } void print_msg_success_gw (struct tgl_state *TLS, void *extra, int success, struct tgl_message *M); void print_encr_chat_success_gw (struct tgl_state *TLS, void *extra, int success, struct tgl_secret_chat *E);; void print_success_gw (struct tgl_state *TLS, void *extra, int success); int complete_command_list (int index, const char *text, int len, char **R) { index ++; while (commands[index].name && strncmp (commands[index].name, text, len)) { index ++; } if (commands[index].name) { *R = strdup (commands[index].name); assert (*R); return index; } else { *R = 0; return -1; } } int complete_spec_message_answer (struct tgl_message *M, int index, const char *text, int len, char **R) { if (!M || !M->reply_markup || !M->reply_markup->rows) { *R = NULL; return -1; } index ++; int total = M->reply_markup->row_start[M->reply_markup->rows]; while (index < total && strncmp (M->reply_markup->buttons[index], text, len)) { index ++; } if (index < total) { *R = strdup (M->reply_markup->buttons[index]); assert (*R); return index; } else { *R = NULL; return -1; } } int complete_message_answer (tgl_peer_t *P, int index, const char *text, int len, char **R) { struct tgl_message *M = P->last; while (M && (M->flags & TGLMF_OUT)) { M = M->next; } return complete_spec_message_answer (M, index, text, len, R); } int complete_user_command (tgl_peer_t *P, int index, const char *text, int len, char **R) { if (len <= 0 || *text != '/') { return complete_message_answer (P, index, text, len, R); } text ++; len --; struct tgl_user *U = (void *)P; if (!U->bot_info) { *R = NULL; return -1; } if (index >= U->bot_info->commands_num) { return U->bot_info->commands_num + complete_message_answer (P, index - U->bot_info->commands_num, text - 1, len + 1, R); } index ++; while (index < U->bot_info->commands_num && strncmp (U->bot_info->commands[index].command, text, len)) { index ++; } if (index < U->bot_info->commands_num) { *R = NULL; assert (asprintf (R, "/%s", U->bot_info->commands[index].command) >= 0); assert (*R); return index; } else { return U->bot_info->commands_num + complete_message_answer (P, index - U->bot_info->commands_num, text - 1, len + 1, R); } } int complete_chat_command (tgl_peer_t *P, int index, const char *text, int len, char **R) { if (len <= 0 || *text != '/') { return complete_message_answer (P, index, text, len, R); } text ++; len --; index ++; int tot = 0; int i; for (i = 0; i < P->chat.user_list_size; i++) { struct tgl_user *U = (void *)tgl_peer_get (TLS, TGL_MK_USER (P->chat.user_list[i].user_id)); if (!U) { continue; } if (!U->bot_info) { continue; } int p = len - 1; while (p >= 0 && text[p] != '@') { p --; } if (p < 0) { p = len; } while (index - tot < U->bot_info->commands_num && strncmp (U->bot_info->commands[index - tot].command, text, p)) { index ++; } if (index - tot < U->bot_info->commands_num) { *R = NULL; if (U->username) { assert (asprintf (R, "/%s@%s", U->bot_info->commands[index].command, U->username) >= 0); } else { assert (asprintf (R, "/%s", U->bot_info->commands[index].command) >= 0); } assert (*R); return index; } tot += U->bot_info->commands_num; } if (index == tot) { return tot + complete_message_answer (P, index - tot, text - 1, len + 1, R); } else { return tot + complete_message_answer (P, index - tot - 1, text - 1, len + 1, R); } } int complete_username (int mode, int index, const char *text, int len, char **R) { *R = NULL; if (len > 0 && *text == '@') { text ++; len --; } index ++; while (index < TLS->peer_num) { tgl_peer_t *P = TLS->Peers[index]; if (mode && tgl_get_peer_type (P->id) != mode) { index ++; continue; } char *u = NULL; if (tgl_get_peer_type (P->id) == TGL_PEER_USER) { u = P->user.username; } else if (tgl_get_peer_type (P->id) == TGL_PEER_CHANNEL) { u = P->channel.username; } if (!u) { index ++; continue; } if ((int)strlen (u) < len || memcmp (u, text, len)) { index ++; continue; } *R = malloc (strlen (u) + 2); *R[0] = '@'; memcpy (*R + 1, u, strlen (u) + 1); break; } if (index == TLS->peer_num) { return -1; } return index; } char *command_generator (const char *text, int state) { #ifndef DISABLE_EXTF static int len; #endif static int index; static enum command_argument mode; static char *command_pos; static int command_len; if (in_chat_mode) { char *R = 0; index = complete_string_list (in_chat_commands, index, text, rl_point, &R); return R; } char c = 0; c = rl_line_buffer[rl_point]; rl_line_buffer[rl_point] = 0; if (!state) { #ifndef DISABLE_EXTF len = strlen (text); #endif index = -1; mode = get_complete_mode (); command_pos = cur_token; command_len = cur_token_len; } else { if (mode != ca_file_name && mode != ca_file_name_end && index == -1) { return 0; } } if (mode == ca_none || mode == ca_string || mode == ca_string_end || mode == ca_number || mode == ca_double || mode == ca_msg_id) { if (c) { rl_line_buffer[rl_point] = c; } return 0; } assert (command_len >= 0); char *R = 0; switch (mode & 255) { case ca_command: index = complete_command_list (index, command_pos, command_len, &R); if (c) { rl_line_buffer[rl_point] = c; } return R; case ca_user: if (command_len && command_pos[0] == '@') { index = complete_username (TGL_PEER_USER, index, command_pos, command_len, &R); } else { index = tgl_complete_user_list (TLS, index, command_pos, command_len, &R); } if (c) { rl_line_buffer[rl_point] = c; } return R; case ca_peer: if (command_len && command_pos[0] == '@') { index = complete_username (0, index, command_pos, command_len, &R); } else { index = tgl_complete_peer_list (TLS, index, command_pos, command_len, &R); } if (c) { rl_line_buffer[rl_point] = c; } return R; case ca_file_name: case ca_file_name_end: if (c) { rl_line_buffer[rl_point] = c; } R = rl_filename_completion_function (command_pos, state); return R; case ca_chat: index = tgl_complete_chat_list (TLS, index, command_pos, command_len, &R); if (c) { rl_line_buffer[rl_point] = c; } return R; case ca_secret_chat: index = tgl_complete_encr_chat_list (TLS, index, command_pos, command_len, &R); if (c) { rl_line_buffer[rl_point] = c; } return R; case ca_channel: if (command_len && command_pos[0] == '@') { index = complete_username (TGL_PEER_CHANNEL, index, command_pos, command_len, &R); } else { index = tgl_complete_channel_list (TLS, index, command_pos, command_len, &R); } if (c) { rl_line_buffer[rl_point] = c; } return R; case ca_modifier: index = complete_string_list (modifiers, index, command_pos, command_len, &R); if (c) { rl_line_buffer[rl_point] = c; } return R; case ca_msg_string_end: if (autocomplete_peer) { if (tgl_get_peer_type (autocomplete_peer->id) == TGL_PEER_USER) { index = complete_user_command (autocomplete_peer, index, command_pos, command_len, &R); } if (tgl_get_peer_type (autocomplete_peer->id) == TGL_PEER_CHAT) { index = complete_chat_command (autocomplete_peer, index, command_pos, command_len, &R); } } if (autocomplete_id.peer_type != (unsigned)NOT_FOUND) { struct tgl_message *M = tgl_message_get (TLS, &autocomplete_id); if (M) { if (command_len > 0 && *command_pos == '/') { tgl_peer_t *P = tgl_peer_get (TLS, M->from_id); if (P) { index = complete_user_command (autocomplete_peer, index, command_pos, command_len, &R); } } else { index = complete_spec_message_answer (M, index, command_pos, command_len, &R); } } } if (c) { rl_line_buffer[rl_point] = c; } return R; #ifndef DISABLE_EXTF case ca_extf: index = tglf_extf_autocomplete (TLS, text, len, index, &R, rl_line_buffer, rl_point); if (c) { rl_line_buffer[rl_point] = c; } return R; #endif default: if (c) { rl_line_buffer[rl_point] = c; } return 0; } } int count = 1; void work_modifier (const char *s, int l) { if (is_same_word (s, l, "[offline]")) { offline_mode = 1; } if (sscanf (s, "[reply=%d]", &reply_id) >= 1) { } if (is_same_word (s, l, "[html]")) { do_html = TGLMF_HTML; } if (is_same_word (s, l, "[disable_preview]")) { disable_msg_preview = TGL_SEND_MSG_FLAG_DISABLE_PREVIEW; } if (is_same_word (s, l, "[enable_preview]")) { disable_msg_preview = TGL_SEND_MSG_FLAG_ENABLE_PREVIEW; } #ifdef ALLOW_MULT if (sscanf (s, "[x%d]", &count) >= 1) { } #endif } void print_fail (struct in_ev *ev) { mprint_start (ev); if (!enable_json) { mprintf (ev, "FAIL: %d: %s\n", TLS->error_code, TLS->error); } else { #ifdef USE_JSON json_t *res = json_object (); assert (json_object_set (res, "result", json_string ("FAIL")) >= 0); assert (json_object_set (res, "error_code", json_integer (TLS->error_code)) >= 0); assert (json_object_set (res, "error", json_string (TLS->error)) >= 0); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void fail_interface (struct tgl_state *TLS, struct in_ev *ev, int error_code, const char *format, ...) { static char error[1001]; va_list ap; va_start (ap, format); int error_len = vsnprintf (error, 1000, format, ap); va_end (ap); if (error_len > 1000) { error_len = 1000; } error[error_len] = 0; mprint_start (ev); if (!enable_json) { mprintf (ev, "FAIL: %d: %s\n", error_code, error); } else { #ifdef USE_JSON json_t *res = json_object (); assert (json_object_set (res, "result", json_string ("FAIL")) >= 0); assert (json_object_set (res, "error_code", json_integer (error_code)) >= 0); assert (json_object_set (res, "error", json_string (error)) >= 0); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void print_success (struct in_ev *ev) { if (ev || enable_json) { mprint_start (ev); if (!enable_json) { mprintf (ev, "SUCCESS\n"); } else { #ifdef USE_JSON json_t *res = json_object (); assert (json_object_set (res, "result", json_string ("SUCCESS")) >= 0); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } } void print_success_gw (struct tgl_state *TLSR, void *extra, int success) { assert (TLS == TLSR); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } else { print_success (ev); return; } } void print_msg_success_gw (struct tgl_state *TLS, void *extra, int success, struct tgl_message *M) { write_secret_chat_file (); print_success_gw (TLS, extra, success); } void print_msg_list_success_gw (struct tgl_state *TLSR, void *extra, int success, int num, struct tgl_message *ML[]) { assert (TLS == TLSR); print_success_gw (TLSR, extra, success); } void print_encr_chat_success_gw (struct tgl_state *TLS, void *extra, int success, struct tgl_secret_chat *E) { write_secret_chat_file (); print_success_gw (TLS, extra, success); } void print_msg_list_gw (struct tgl_state *TLSR, void *extra, int success, int num, struct tgl_message *ML[]) { assert (TLS == TLSR); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } mprint_start (ev); if (!enable_json) { int i; for (i = num - 1; i >= 0; i--) { print_message (ev, ML[i]); } } else { #ifdef USE_JSON json_t *res = json_array (); int i; for (i = num - 1; i >= 0; i--) { json_t *a = json_pack_message (ML[i]); assert (json_array_append (res, a) >= 0); } char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void print_msg_list_history_gw (struct tgl_state *TLSR, void *extra, int success, int num, struct tgl_message *ML[]) { print_msg_list_gw (TLSR, extra, success, num, ML); if (num > 0) { if (tgl_cmp_peer_id (ML[0]->to_id, TLS->our_id)) { tgl_do_messages_mark_read (TLS, ML[0]->to_id, ML[0]->server_id, 0, NULL, NULL); } else { tgl_do_messages_mark_read (TLS, ML[0]->from_id, ML[0]->server_id, 0, NULL, NULL); } } } void print_msg_gw (struct tgl_state *TLSR, void *extra, int success, struct tgl_message *M) { assert (TLS == TLSR); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } mprint_start (ev); if (!enable_json) { print_message (ev, M); } else { #ifdef USE_JSON json_t *res = json_pack_message (M); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void print_user_list_gw (struct tgl_state *TLSR, void *extra, int success, int num, struct tgl_user *UL[]) { assert (TLS == TLSR); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } mprint_start (ev); if (!enable_json) { int i; for (i = num - 1; i >= 0; i--) { print_user_name (ev, UL[i]->id, (void *)UL[i]); mprintf (ev, "\n"); } } else { #ifdef USE_JSON json_t *res = json_array (); int i; for (i = num - 1; i >= 0; i--) { json_t *a = json_pack_peer (UL[i]->id); assert (json_array_append (res, a) >= 0); } char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void print_user_gw (struct tgl_state *TLSR, void *extra, int success, struct tgl_user *U) { assert (TLS == TLSR); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } mprint_start (ev); if (!enable_json) { print_user_name (ev, U->id, (void *)U); mprintf (ev, "\n"); } else { #ifdef USE_JSON json_t *res = json_pack_peer (U->id); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void print_chat_gw (struct tgl_state *TLSR, void *extra, int success, struct tgl_chat *U) { assert (TLS == TLSR); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } mprint_start (ev); if (!enable_json) { print_chat_name (ev, U->id, (void *)U); mprintf (ev, "\n"); } else { #ifdef USE_JSON json_t *res = json_pack_peer (U->id); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void print_channel_gw (struct tgl_state *TLSR, void *extra, int success, struct tgl_channel *U) { assert (TLS == TLSR); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } mprint_start (ev); if (!enable_json) { print_channel_name (ev, U->id, (void *)U); mprintf (ev, "\n"); } else { #ifdef USE_JSON json_t *res = json_pack_peer (U->id); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void print_peer_gw (struct tgl_state *TLSR, void *extra, int success, tgl_peer_t *U) { if (!success) { print_user_gw (TLSR, extra, success, (void *)U); return; } switch (tgl_get_peer_type (U->id)) { case TGL_PEER_USER: print_user_gw (TLSR, extra, success, (void *)U); break; case TGL_PEER_CHAT: print_chat_gw (TLSR, extra, success, (void *)U); break; case TGL_PEER_CHANNEL: print_channel_gw (TLSR, extra, success, (void *)U); break; default: assert (0); } } void print_filename_gw (struct tgl_state *TLSR, void *extra, int success, const char *name) { assert (TLS == TLSR); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } mprint_start (ev); if (!enable_json) { mprintf (ev, "Saved to %s\n", name); } else { #ifdef USE_JSON json_t *res = json_object (); assert (json_object_set (res, "result", json_string (name)) >= 0); assert (json_object_set (res, "event", json_string ("download")) >= 0); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void print_string_gw (struct tgl_state *TLSR, void *extra, int success, const char *name) { assert (TLS == TLSR); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } mprint_start (ev); if (!enable_json) { mprintf (ev, "%s\n", name); } else { #ifdef USE_JSON json_t *res = json_object (); assert (json_object_set (res, "result", json_string (name)) >= 0); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void open_filename_gw (struct tgl_state *TLSR, void *extra, int success, const char *name) { assert (TLS == TLSR); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (ev) { return; } if (!success) { print_fail (ev); return; } static char buf[PATH_MAX]; if (snprintf (buf, sizeof (buf), OPEN_BIN, name) >= (int) sizeof (buf)) { logprintf ("Open image command buffer overflow\n"); } else { int pid = fork (); if (!pid) { execl("/bin/sh", "sh", "-c", buf, (char *) 0); exit (0); } } } void print_chat_info_gw (struct tgl_state *TLSR, void *extra, int success, struct tgl_chat *C) { assert (TLS == TLSR); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } mprint_start (ev); if (!enable_json) { tgl_peer_t *U = (void *)C; mpush_color (ev, COLOR_YELLOW); mprintf (ev, "Chat "); print_chat_name (ev, U->id, U); mprintf (ev, " (id %d) members:\n", tgl_get_peer_id (U->id)); int i; for (i = 0; i < C->user_list_size; i++) { mprintf (ev, "\t\t"); print_user_name (ev, TGL_MK_USER (C->user_list[i].user_id), tgl_peer_get (TLS, TGL_MK_USER (C->user_list[i].user_id))); mprintf (ev, " invited by "); print_user_name (ev, TGL_MK_USER (C->user_list[i].inviter_id), tgl_peer_get (TLS, TGL_MK_USER (C->user_list[i].inviter_id))); mprintf (ev, " at "); print_date_full (ev, C->user_list[i].date); if (C->user_list[i].user_id == C->admin_id) { mprintf (ev, " admin"); } mprintf (ev, "\n"); } mpop_color (ev); } else { #ifdef USE_JSON json_t *res = json_pack_peer (C->id); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void print_channel_info_gw (struct tgl_state *TLSR, void *extra, int success, struct tgl_channel *C) { assert (TLS == TLSR); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } mprint_start (ev); if (!enable_json) { tgl_peer_t *U = (void *)C; mpush_color (ev, COLOR_YELLOW); mprintf (ev, "Channel "); if (U->flags & TGLCHF_OFFICIAL) { mprintf (ev, "[verified] "); } if (U->flags & TGLCHF_BROADCAST) { mprintf (ev, "[broadcast] "); } if (U->flags & TGLCHF_MEGAGROUP) { mprintf (ev, "[megagroup] "); } if (U->flags & TGLCHF_DEACTIVATED) { mprintf (ev, "[deactivated] "); } print_channel_name (ev, U->id, U); if (C->username) { mprintf (ev, " @%s", C->username); } mprintf (ev, " (#%d):\n", tgl_get_peer_id (U->id)); mprintf (ev, "\tabout: %s\n", C->about); mprintf (ev, "\t%d participants, %d admins, %d kicked\n", C->participants_count, C->admins_count, C->kicked_count); mpop_color (ev); } else { #ifdef USE_JSON json_t *res = json_pack_peer (C->id); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void print_user_status (struct tgl_user_status *S, struct in_ev *ev) { assert(!enable_json); //calling functions print_user_info_gw() and user_status_upd() already check. if (S->online > 0) { mprintf (ev, "online (was online "); print_date_full (ev, S->when); mprintf (ev, ")"); } else { if (S->online == 0) { mprintf (ev, "offline"); } else if (S->online == -1) { mprintf (ev, "offline (was online "); print_date_full (ev, S->when); mprintf (ev, ")"); } else if (S->online == -2) { mprintf (ev, "offline (was online recently)"); } else if (S->online == -3) { mprintf (ev, "offline (was online last week)"); } else if (S->online == -4) { mprintf (ev, "offline (was online last month)"); } } } void print_user_info_gw (struct tgl_state *TLSR, void *extra, int success, struct tgl_user *U) { assert (TLS == TLSR); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } mprint_start (ev); tgl_peer_t *C = (void *)U; if (!enable_json) { mpush_color (ev, COLOR_YELLOW); mprintf (ev, "User "); print_user_name (ev, U->id, C); if (U->username) { mprintf (ev, " @%s", U->username); } mprintf (ev, " (#%d):\n", tgl_get_peer_id (U->id)); mprintf (ev, "\tphone: %s\n", U->phone); mprintf (ev, "\t"); print_user_status (&U->status, ev); mprintf (ev, "\n"); if (U->bot_info) { mprintf (ev, "\tshare_text: %s\n", U->bot_info->share_text); mprintf (ev, "\tdescription: %s\n", U->bot_info->description); mprintf (ev, "\tcommands:\n"); int i; for (i = 0; i < U->bot_info->commands_num; i++) { mprintf (ev, "\t\t/%s: %s\n", U->bot_info->commands[i].command, U->bot_info->commands[i].description); } } mpop_color (ev); } else { #ifdef USE_JSON json_t *res = json_pack_peer (U->id); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void print_secret_chat_gw (struct tgl_state *TLSR, void *extra, int success, struct tgl_secret_chat *E) { assert (TLS == TLSR); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } mprint_start (ev); if (!enable_json) { mpush_color (ev, COLOR_YELLOW); mprintf (ev, " Encrypted chat "); print_encr_chat_name (ev, E->id, (void *)E); mprintf (ev, " is now in wait state\n"); mpop_color (ev); } else { #ifdef USE_JSON json_t *res = json_pack_peer (E->id); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void print_dialog_list_gw (struct tgl_state *TLSR, void *extra, int success, int size, tgl_peer_id_t peers[], tgl_message_id_t *last_msg_id[], int unread_count[]) { assert (TLS == TLSR); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } mprint_start (ev); if (!enable_json) { mpush_color (ev, COLOR_YELLOW); int i; for (i = size - 1; i >= 0; i--) { tgl_peer_t *UC; switch (tgl_get_peer_type (peers[i])) { case TGL_PEER_USER: UC = tgl_peer_get (TLS, peers[i]); mprintf (ev, "User "); print_user_name (ev, peers[i], UC); mprintf (ev, ": %d unread\n", unread_count[i]); break; case TGL_PEER_CHAT: UC = tgl_peer_get (TLS, peers[i]); mprintf (ev, "Chat "); print_chat_name (ev, peers[i], UC); mprintf (ev, ": %d unread\n", unread_count[i]); break; case TGL_PEER_CHANNEL: UC = tgl_peer_get (TLS, peers[i]); mprintf (ev, "Channel "); print_channel_name (ev, peers[i], UC); mprintf (ev, ": %d unread\n", unread_count[i]); break; } } mpop_color (ev); } else { #ifdef USE_JSON json_t *res = json_array (); int i; for (i = size - 1; i >= 0; i--) { json_t *a = json_pack_peer (peers[i]); assert (json_array_append (res, a) >= 0); } char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void interpreter_chat_mode (char *line) { if (line == NULL || /* EOF received */ !strncmp (line, "/exit", 5) || !strncmp (line, "/quit", 5)) { in_chat_mode = 0; update_prompt (); return; } if (!strncmp (line, "/history", 8)) { int limit = 40; sscanf (line, "/history %99d", &limit); if (limit < 0 || limit > 1000) { limit = 40; } tgl_do_get_history (TLS, chat_mode_id, 0, limit, offline_mode, print_msg_list_gw, 0); return; } if (!strncmp (line, "/read", 5)) { tgl_do_mark_read (TLS, chat_mode_id, 0, 0); return; } if (strlen (line) > 0) { tgl_do_send_message (TLS, chat_mode_id, line, strlen (line), 0, NULL, 0, 0); } } #define MAX_UNREAD_MESSAGE_COUNT 10000 struct tgl_message *unread_message_list[MAX_UNREAD_MESSAGE_COUNT]; int unread_message_count; struct event *unread_message_event; void print_read_list (int num, struct tgl_message *list[]) { struct in_ev *ev = notify_ev; int i; mprint_start (ev); for (i = 0; i < num; i++) if (list[i]) { if (enable_json) { #ifdef USE_JSON json_t *res = json_pack_read (list[i]); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } tgl_peer_id_t to_id; if (!tgl_cmp_peer_id (list[i]->to_id, TLS->our_id)) { to_id = list[i]->from_id; } else { to_id = list[i]->to_id; } int j; int c1 = 0; int c2 = 0; for (j = i; j < num; j++) if (list[j]) { tgl_peer_id_t end_id; if (!tgl_cmp_peer_id (list[j]->to_id, TLS->our_id)) { end_id = list[j]->from_id; } else { end_id = list[j]->to_id; } if (!tgl_cmp_peer_id (to_id, end_id)) { if (list[j]->flags & TGLMF_OUT) { c1 ++; } else { c2 ++; } list[j] = 0; } } assert (c1 + c2 > 0); if (!enable_json) { mpush_color (ev, COLOR_YELLOW); switch (tgl_get_peer_type (to_id)) { case TGL_PEER_USER: mprintf (ev, "User "); print_user_name (ev, to_id, tgl_peer_get (TLS, to_id)); break; case TGL_PEER_CHAT: mprintf (ev, "Chat "); print_chat_name (ev, to_id, tgl_peer_get (TLS, to_id)); break; case TGL_PEER_ENCR_CHAT: mprintf (ev, "Secret chat "); print_encr_chat_name (ev, to_id, tgl_peer_get (TLS, to_id)); break; default: assert (0); } mprintf (ev, " marked read %d outbox and %d inbox messages\n", c1, c2); mpop_color (ev); } } mprint_end (ev); } void unread_message_alarm (evutil_socket_t fd, short what, void *arg) { print_read_list (unread_message_count, unread_message_list); unread_message_count = 0; event_free (unread_message_event); unread_message_event = 0; } void mark_read_upd (struct tgl_state *TLSR, int num, struct tgl_message *list[]) { assert (TLSR == TLS); if (!binlog_read) { return; } if (log_level < 1) { return; } if (unread_message_count + num <= MAX_UNREAD_MESSAGE_COUNT) { memcpy (unread_message_list + unread_message_count, list, num * sizeof (void *)); unread_message_count += num; if (!unread_message_event) { unread_message_event = evtimer_new (TLS->ev_base, unread_message_alarm, 0); static struct timeval ptimeout = { 1, 0}; event_add (unread_message_event, &ptimeout); } } else { print_read_list (unread_message_count, unread_message_list); print_read_list (num, list); unread_message_count = 0; if (unread_message_event) { event_free (unread_message_event); unread_message_event = 0; } } } void print_typing (struct in_ev *ev, enum tgl_typing_status status) { switch (status) { case tgl_typing_none: mprintf (ev, "doing nothing"); break; case tgl_typing_typing: mprintf (ev, "typing"); break; case tgl_typing_cancel: mprintf (ev, "deleting typed message"); break; case tgl_typing_record_video: mprintf (ev, "recording video"); break; case tgl_typing_upload_video: mprintf (ev, "uploading video"); break; case tgl_typing_record_audio: mprintf (ev, "recording audio"); break; case tgl_typing_upload_audio: mprintf (ev, "uploading audio"); break; case tgl_typing_upload_photo: mprintf (ev, "uploading photo"); break; case tgl_typing_upload_document: mprintf (ev, "uploading document"); break; case tgl_typing_geo: mprintf (ev, "choosing location"); break; case tgl_typing_choose_contact: mprintf (ev, "choosing contact"); break; } } void type_notification_upd (struct tgl_state *TLSR, struct tgl_user *U, enum tgl_typing_status status) { assert (TLSR == TLS); if (log_level < 2 || (disable_output && !notify_ev)) { return; } if (enable_json) { return; } struct in_ev *ev = notify_ev; mprint_start (ev); mpush_color (ev, COLOR_YELLOW); mprintf (ev, "User "); print_user_name (ev, U->id, (void *)U); mprintf (ev, " is "); print_typing (ev, status); mprintf (ev, "\n"); mpop_color (ev); mprint_end (ev); } void type_in_chat_notification_upd (struct tgl_state *TLSR, struct tgl_user *U, struct tgl_chat *C, enum tgl_typing_status status) { assert (TLSR == TLS); if (log_level < 2 || (disable_output && !notify_ev)) { return; } if (enable_json) { return; } struct in_ev *ev = notify_ev; mprint_start (ev); mpush_color (ev, COLOR_YELLOW); mprintf (ev, "User "); print_user_name (ev, U->id, (void *)U); mprintf (ev, " is "); print_typing (ev, status); mprintf (ev, " in chat "); print_chat_name (ev, C->id, (void *)C); mprintf (ev, "\n"); mpop_color (ev); mprint_end (ev); } void print_message_gw (struct tgl_state *TLSR, struct tgl_message *M) { assert (TLSR == TLS); #ifdef USE_LUA lua_new_msg (M); #endif #ifdef USE_PYTHON py_new_msg (M); #endif if (!binlog_read) { return; } if (tgl_get_peer_type (M->to_id) == TGL_PEER_ENCR_CHAT) { write_secret_chat_file (); } if (alert_sound) { play_sound (); } if (disable_output && !notify_ev) { return; } struct in_ev *ev = notify_ev; mprint_start (ev); if (!enable_json) { print_message (ev, M); } else { #ifdef USE_JSON json_t *res = json_pack_message (M); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void our_id_gw (struct tgl_state *TLSR, tgl_peer_id_t id) { assert (TLSR == TLS); #ifdef USE_LUA lua_our_id (id); #endif #ifdef USE_PYTHON py_our_id (id); #endif } void print_peer_updates (struct in_ev *ev, int flags) { if (flags & TGL_UPDATE_PHONE) { mprintf (ev, " phone"); } if (flags & TGL_UPDATE_CONTACT) { mprintf (ev, " contact"); } if (flags & TGL_UPDATE_PHOTO) { mprintf (ev, " photo"); } if (flags & TGL_UPDATE_BLOCKED) { mprintf (ev, " blocked"); } if (flags & TGL_UPDATE_REAL_NAME) { mprintf (ev, " name"); } if (flags & TGL_UPDATE_NAME) { mprintf (ev, " contact_name"); } if (flags & TGL_UPDATE_REQUESTED) { mprintf (ev, " status"); } if (flags & TGL_UPDATE_WORKING) { mprintf (ev, " status"); } if (flags & TGL_UPDATE_FLAGS) { mprintf (ev, " flags"); } if (flags & TGL_UPDATE_TITLE) { mprintf (ev, " title"); } if (flags & TGL_UPDATE_ADMIN) { mprintf (ev, " admin"); } if (flags & TGL_UPDATE_MEMBERS) { mprintf (ev, " members"); } if (flags & TGL_UPDATE_ACCESS_HASH) { mprintf (ev, " access_hash"); } if (flags & TGL_UPDATE_USERNAME) { mprintf (ev, " username"); } } void json_peer_update (struct in_ev *ev, tgl_peer_t *P, unsigned flags) { #ifdef USE_JSON json_t *res = json_object (); assert (json_object_set (res, "event", json_string ("updates")) >= 0); assert (json_object_set (res, "peer", json_pack_peer (P->id)) >= 0); assert (json_object_set (res, "updates", json_pack_updates (flags)) >= 0); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } void peer_update_username (tgl_peer_t *P, const char *username) { if (!username) { if (P->extra) { struct username_peer_pair *p = tree_lookup_username_peer_pair (username_peer_pair, (void *)&P->extra); assert (p); username_peer_pair = tree_delete_username_peer_pair (username_peer_pair, p); tfree_str (P->extra); tfree (p, sizeof (*p)); P->extra = NULL; } return; } assert (username); if (P->extra && !strcmp (P->extra, username)) { return; } if (P->extra) { struct username_peer_pair *p = tree_lookup_username_peer_pair (username_peer_pair, (void *)&P->extra); assert (p); username_peer_pair = tree_delete_username_peer_pair (username_peer_pair, p); tfree_str (P->extra); tfree (p, sizeof (*p)); P->extra = NULL; } P->extra = tstrdup (username); struct username_peer_pair *p = talloc (sizeof (*p)); p->peer = P; p->username = P->extra; username_peer_pair = tree_insert_username_peer_pair (username_peer_pair, p, rand ()); } void user_update_gw (struct tgl_state *TLSR, struct tgl_user *U, unsigned flags) { assert (TLSR == TLS); #ifdef USE_LUA lua_user_update (U, flags); #endif #ifdef USE_PYTHON py_user_update (U, flags); #endif peer_update_username ((void *)U, U->username); if (disable_output && !notify_ev) { return; } if (!binlog_read) { return; } struct in_ev *ev = notify_ev; if (!(flags & TGL_UPDATE_CREATED)) { mprint_start (ev); if (!enable_json) { mpush_color (ev, COLOR_YELLOW); mprintf (ev, "User "); print_user_name (ev, U->id, (void *)U); if (!(flags & TGL_UPDATE_DELETED)) { mprintf (ev, " updated"); print_peer_updates (ev, flags); } else { mprintf (ev, " deleted"); } mprintf (ev, "\n"); mpop_color (ev); } else { json_peer_update (ev, (void *)U, flags); } mprint_end (ev); } } void chat_update_gw (struct tgl_state *TLSR, struct tgl_chat *U, unsigned flags) { assert (TLSR == TLS); #ifdef USE_LUA lua_chat_update (U, flags); #endif #ifdef USE_PYTHON py_chat_update (U, flags); #endif if (disable_output && !notify_ev) { return; } if (!binlog_read) { return; } struct in_ev *ev = notify_ev; if (!(flags & TGL_UPDATE_CREATED)) { mprint_start (ev); if (!enable_json) { mpush_color (ev, COLOR_YELLOW); mprintf (ev, "Chat "); print_chat_name (ev, U->id, (void *)U); if (!(flags & TGL_UPDATE_DELETED)) { mprintf (ev, " updated"); print_peer_updates (ev, flags); } else { mprintf (ev, " deleted"); } mprintf (ev, "\n"); mpop_color (ev); } else { json_peer_update (ev, (void *)U, flags); } mprint_end (ev); } } void secret_chat_update_gw (struct tgl_state *TLSR, struct tgl_secret_chat *U, unsigned flags) { assert (TLSR == TLS); #ifdef USE_LUA lua_secret_chat_update (U, flags); #endif #ifdef USE_PYTHON py_secret_chat_update (U, flags); #endif if ((flags & TGL_UPDATE_WORKING) || (flags & TGL_UPDATE_DELETED)) { write_secret_chat_file (); } if (!binlog_read) { return; } if ((flags & TGL_UPDATE_REQUESTED) && !disable_auto_accept) { //tgl_do_accept_encr_chat_request (TLS, U, 0, 0); tgl_do_accept_encr_chat_request (TLS, U, print_encr_chat_success_gw, 0); } if (disable_output && !notify_ev) { return; } struct in_ev *ev = notify_ev; if (!(flags & TGL_UPDATE_CREATED)) { mprint_start (ev); if (!enable_json) { mpush_color (ev, COLOR_YELLOW); mprintf (ev, "Secret chat "); print_encr_chat_name (ev, U->id, (void *)U); if (!(flags & TGL_UPDATE_DELETED)) { mprintf (ev, " updated"); print_peer_updates (ev, flags); } else { mprintf (ev, " deleted"); } mprintf (ev, "\n"); mpop_color (ev); } else { json_peer_update (ev, (void *)U, flags); } mprint_end (ev); } } void channel_update_gw (struct tgl_state *TLSR, struct tgl_channel *U, unsigned flags) { assert (TLSR == TLS); peer_update_username ((void *)U, U->username); if (disable_output && !notify_ev) { return; } if (!binlog_read) { return; } } void print_card_gw (struct tgl_state *TLSR, void *extra, int success, int size, int *card) { assert (TLSR == TLS); struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } mprint_start (ev); if (!enable_json) { mprintf (ev, "Card: "); int i; for (i = 0; i < size; i++) { mprintf (ev, "%08x%c", card[i], i == size - 1 ? '\n' : ':'); } } else { #ifdef USE_JSON static char q[1000]; int pos = 0; int i; for (i = 0; i < size; i++) { pos += sprintf (q + pos, "%08x%s", card[i], i == size - 1 ? "" : ":"); } json_t *res = json_object (); assert (json_object_set (res, "result", json_string (q)) >= 0); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void callback_extf (struct tgl_state *TLS, void *extra, int success, const char *buf) { struct in_ev *ev = extra; if (ev && !--ev->refcnt) { free (ev); return; } if (!success) { print_fail (ev); return; } mprint_start (ev); if (!enable_json) { mprintf (ev, "%s\n", buf); } else { #ifdef USE_JSON json_t *res = json_object (); assert (json_object_set (res, "result", json_string (buf)) >= 0); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void user_status_upd (struct tgl_state *TLS, struct tgl_user *U) { if (disable_output && !notify_ev) { return; } if (!binlog_read) { return; } if (log_level < 3) { return; } struct in_ev *ev = notify_ev; mprint_start (ev); if (!enable_json) { mpush_color (ev, COLOR_YELLOW); mprintf (ev, "User "); print_user_name(ev, U->id, (void *) U); mprintf (ev, " "); print_user_status(&U->status, ev); mprintf (ev, "\n"); mpop_color (ev); } else { #ifdef USE_JSON json_t *res = json_pack_user_status(U); char *s = json_dumps (res, 0); mprintf (ev, "%s\n", s); json_decref (res); free (s); #endif } mprint_end (ev); } void on_login (struct tgl_state *TLS); void on_failed_login (struct tgl_state *TLS); void on_started (struct tgl_state *TLS); void do_get_values (struct tgl_state *TLS, enum tgl_value_type type, const char *prompt, int num_values, void (*callback)(struct tgl_state *TLS, const char *string[], void *arg), void *arg); struct tgl_update_callback upd_cb = { .new_msg = print_message_gw, .marked_read = mark_read_upd, .logprintf = logprintf, .get_values = do_get_values, .logged_in = on_login, .started = on_started, .type_notification = type_notification_upd, .type_in_chat_notification = type_in_chat_notification_upd, .type_in_secret_chat_notification = 0, .status_notification = 0, .user_registered = 0, .user_activated = 0, .new_authorization = 0, .user_update = user_update_gw, .chat_update = chat_update_gw, .secret_chat_update = secret_chat_update_gw, .channel_update = channel_update_gw, .msg_receive = print_message_gw, .our_id = our_id_gw, .user_status_update = user_status_upd, .on_failed_login = on_failed_login }; void interpreter_ex (char *line, void *ex) { force_end_mode = 1; assert (!in_readline); in_readline = 1; if (in_chat_mode) { interpreter_chat_mode (line); in_readline = 0; return; } do_html = 0; line_ptr = line; offline_mode = 0; reply_id = 0; disable_msg_preview = 0; count = 1; if (!line) { do_safe_quit (NULL, 0, NULL, NULL); in_readline = 0; return; } if (!*line) { in_readline = 0; return; } if (line && *line) { add_history (line); } if (*line == '(') { struct in_ev *ev = ex; if (ev) { ev->refcnt ++; } tgl_do_send_extf (TLS, line, strlen (line), callback_extf, ev); in_readline = 0; return; } while (1) { next_token (); if (cur_token_quoted) { in_readline = 0; fail_interface (TLS, ex, ENOSYS, "can not parse modifier"); return; } if (cur_token_len <= 0) { in_readline = 0; fail_interface (TLS, ex, ENOSYS, "can not parse modifier"); return; } if (*cur_token == '[') { if (cur_token_end_str) { in_readline = 0; fail_interface (TLS, ex, ENOSYS, "can not parse modifier"); return; } if (cur_token[cur_token_len - 1] != ']') { in_readline = 0; fail_interface (TLS, ex, ENOSYS, "can not parse modifier"); return; } work_modifier (cur_token, cur_token_len); continue; } break; } if (cur_token_quoted || cur_token_end_str) { fail_interface (TLS, ex, ENOSYS, "can not parse command name"); in_readline = 0; return; } struct command *command = commands; int n = 0; struct tgl_command; while (command->name) { if (is_same_word (cur_token, cur_token_len, command->name)) { break; } n ++; command ++; } if (!command->name) { fail_interface (TLS, ex, ENOSYS, "can not find command '%.*s'", cur_token_len, cur_token); in_readline = 0; return; } enum command_argument *flags = command->args; void (*fun)(struct command *, int, struct arg[], struct in_ev *) = command->fun; int args_num = 0; static struct arg args[1000]; while (1) { assert (args_num < 1000); args[args_num].flags = 0; int period = 0; if (*flags == ca_period) { flags --; } if (*flags != ca_none && *(flags + 1) == ca_period) { period = 1; } enum command_argument op = (*flags) & 255; int opt = (*flags) & ca_optional; if (op == ca_none) { next_token (); if (cur_token_end_str) { int z; for (z = 0; z < count; z ++) { fun (command, args_num, args, ex); } } else { fail_interface (TLS, ex, ENOSYS, "too many args #%d", args_num); } break; } if (op == ca_string_end || op == ca_file_name_end || op == ca_msg_string_end) { next_token_end (); if (cur_token_len < 0) { fail_interface (TLS, ex, ENOSYS, "can not parse string_end arg #%d", args_num); break; } else { args[args_num].flags = 1; args[args_num ++].str = strndup (cur_token, cur_token_len); int z; for (z = 0; z < count; z ++) { fun (command, args_num, args, ex); } break; } } char *save = line_ptr; next_token (); if (period && cur_token_end_str) { int z; for (z = 0; z < count; z ++) { fun (command, args_num, args, ex); } break; } if (op == ca_user || op == ca_chat || op == ca_secret_chat || op == ca_peer || op == ca_number || op == ca_double || op == ca_msg_id || op == ca_channel) { if (cur_token_quoted) { if (opt) { if (op != ca_number && op != ca_double && op != ca_msg_id) { args[args_num ++].peer_id = TGL_PEER_NOT_FOUND; } else { if (op == ca_number) { args[args_num ++].num = NOT_FOUND; } else if (op == ca_msg_id) { args[args_num ++].msg_id.peer_type = 0; } else { args[args_num ++].dval = NOT_FOUND; } } line_ptr = save; flags ++; continue; } else if (period) { line_ptr = save; flags += 2; continue; } else { break; } } else { if (cur_token_end_str) { if (opt) { if (op != ca_number && op != ca_double && op != ca_msg_id) { args[args_num ++].peer_id = TGL_PEER_NOT_FOUND; } else { if (op == ca_number) { args[args_num ++].num = NOT_FOUND; } else if (op == ca_msg_id) { args[args_num ++].msg_id.peer_type = 0; } else { args[args_num ++].dval = NOT_FOUND; } } line_ptr = save; flags ++; continue; } else if (period) { line_ptr = save; flags += 2; continue; } else { break; } } int ok = 1; switch (op) { case ca_user: args[args_num ++].peer_id = cur_token_user (); ok = tgl_get_peer_id (args[args_num - 1].peer_id) != NOT_FOUND; break; case ca_chat: args[args_num ++].peer_id = cur_token_chat (); ok = tgl_get_peer_id (args[args_num - 1].peer_id) != NOT_FOUND; break; case ca_secret_chat: args[args_num ++].peer_id = cur_token_encr_chat (); ok = tgl_get_peer_id (args[args_num - 1].peer_id) != NOT_FOUND; break; case ca_channel: args[args_num ++].peer_id = cur_token_channel (); ok = tgl_get_peer_id (args[args_num - 1].peer_id) != NOT_FOUND; break; case ca_peer: args[args_num ++].peer_id = cur_token_peer (); ok = tgl_get_peer_id (args[args_num - 1].peer_id) != NOT_FOUND; break; case ca_number: args[args_num ++].num = cur_token_int (); ok = (args[args_num - 1].num != NOT_FOUND); break; case ca_msg_id: args[args_num ++].msg_id = cur_token_msg_id (); ok = (args[args_num - 1].msg_id.peer_type != 0); break; case ca_double: args[args_num ++].dval = cur_token_double (); ok = (args[args_num - 1].dval != NOT_FOUND); break; default: assert (0); } if (period && !ok) { line_ptr = save; flags += 2; args_num --; continue; } if (opt && !ok) { line_ptr = save; flags ++; continue; } if (!ok) { fail_interface (TLS, ex, ENOSYS, "can not parse arg #%d", args_num); break; } flags ++; continue; } } if (op == ca_string || op == ca_file_name || op == ca_command) { if (cur_token_end_str || cur_token_len < 0) { if (opt) { args[args_num ++].str = NULL; flags ++; continue; } fail_interface (TLS, ex, ENOSYS, "can not parse string arg #%d", args_num); break; } else { args[args_num].flags = 1; args[args_num ++].str = strndup (cur_token, cur_token_len); flags ++; continue; } } //assert (0); } int i; for (i = 0; i < args_num; i++) { if (args[i].flags & 1) { free (args[i].str); } } update_prompt (); in_readline = 0; } void interpreter (char *line) { interpreter_ex (line, 0); } int readline_active; /*void rprintf (const char *format, ...) { mprint_start (ev); va_list ap; va_start (ap, format); vfprintf (stdout, format, ap); va_end (ap); print_end(); }*/ int saved_point; char *saved_line; static int prompt_was; void deactivate_readline (void) { if (read_one_string) { printf ("\033[2K\r"); fflush (stdout); } else { saved_point = rl_point; saved_line = malloc (rl_end + 1); assert (saved_line); saved_line[rl_end] = 0; memcpy (saved_line, rl_line_buffer, rl_end); rl_save_prompt(); rl_replace_line("", 0); rl_redisplay(); } } void reactivate_readline (void) { if (read_one_string) { printf ("%s ", one_string_prompt); if (!(one_string_flags & 1)) { printf ("%.*s", one_string_len, one_string); } fflush (stdout); } else { set_prompt (get_default_prompt ()); rl_replace_line(saved_line, 0); rl_point = saved_point; rl_redisplay(); free (saved_line); } } void print_start (void) { if (in_readline) { return; } if (readline_disabled) { return; } assert (!prompt_was); if (readline_active) { deactivate_readline (); } prompt_was = 1; } void print_end (void) { if (in_readline) { return; } if (readline_disabled) { fflush (stdout); return; } assert (prompt_was); if (readline_active) { reactivate_readline (); } prompt_was = 0; } /*void hexdump (int *in_ptr, int *in_end) { mprint_start (ev); int *ptr = in_ptr; while (ptr < in_end) { mprintf (ev, " %08x", *(ptr ++)); } mprintf (ev, "\n"); mprint_end (ev); }*/ void logprintf (const char *format, ...) { int x = 0; if (!prompt_was) { x = 1; print_start (); } if (!disable_colors) { printf (COLOR_GREY); } printf (" *** "); double T = tglt_get_double_time (); printf ("%.6lf ", T); va_list ap; va_start (ap, format); vfprintf (stdout, format, ap); va_end (ap); if (!disable_colors) { printf (COLOR_NORMAL); } if (x) { print_end (); } } int color_stack_pos; const char *color_stack[10]; void push_color (const char *color) { if (disable_colors) { return; } assert (color_stack_pos < 10); color_stack[color_stack_pos ++] = color; printf ("%s", color); } void pop_color (void) { if (disable_colors) { return; } assert (color_stack_pos > 0); color_stack_pos --; if (color_stack_pos >= 1) { printf ("%s", color_stack[color_stack_pos - 1]); } else { printf ("%s", COLOR_NORMAL); } } void print_media (struct in_ev *ev, struct tgl_message_media *M) { assert (M); switch (M->type) { case tgl_message_media_none: return; case tgl_message_media_photo: if (!M->photo) { mprintf (ev, "[photo bad]"); } else if (M->photo->caption && strlen (M->photo->caption)) { mprintf (ev, "[photo %s]", M->photo->caption); } else { mprintf (ev, "[photo]"); } if (M->caption) { mprintf (ev, " %s", M->caption); } return; case tgl_message_media_document: case tgl_message_media_audio: case tgl_message_media_video: mprintf (ev, "["); assert (M->document); if (M->document->flags & TGLDF_IMAGE) { mprintf (ev, "image"); } else if (M->document->flags & TGLDF_AUDIO) { mprintf (ev, "audio"); } else if (M->document->flags & TGLDF_VIDEO) { mprintf (ev, "video"); } else if (M->document->flags & TGLDF_STICKER) { mprintf (ev, "sticker"); } else { mprintf (ev, "document"); } if (M->document->caption && strlen (M->document->caption)) { mprintf (ev, " %s:", M->document->caption); } else { mprintf (ev, ":"); } if (M->document->mime_type) { mprintf (ev, " type=%s", M->document->mime_type); } if (M->document->w && M->document->h) { mprintf (ev, " size=%dx%d", M->document->w, M->document->h); } if (M->document->duration) { mprintf (ev, " duration=%d", M->document->duration); } mprintf (ev, " size="); if (M->document->size < (1 << 10)) { mprintf (ev, "%dB", M->document->size); } else if (M->document->size < (1 << 20)) { mprintf (ev, "%dKiB", M->document->size >> 10); } else if (M->document->size < (1 << 30)) { mprintf (ev, "%dMiB", M->document->size >> 20); } else { mprintf (ev, "%dGiB", M->document->size >> 30); } mprintf (ev, "]"); if (M->caption) { mprintf (ev, " %s", M->caption); } return; case tgl_message_media_document_encr: mprintf (ev, "["); if (M->encr_document->flags & TGLDF_IMAGE) { mprintf (ev, "image"); } else if (M->encr_document->flags & TGLDF_AUDIO) { mprintf (ev, "audio"); } else if (M->encr_document->flags & TGLDF_VIDEO) { mprintf (ev, "video"); } else if (M->encr_document->flags & TGLDF_STICKER) { mprintf (ev, "sticker"); } else { mprintf (ev, "document"); } if (M->encr_document->caption && strlen (M->encr_document->caption)) { mprintf (ev, " %s:", M->encr_document->caption); } else { mprintf (ev, ":"); } if (M->encr_document->mime_type) { mprintf (ev, " type=%s", M->encr_document->mime_type); } if (M->encr_document->w && M->encr_document->h) { mprintf (ev, " size=%dx%d", M->encr_document->w, M->encr_document->h); } if (M->encr_document->duration) { mprintf (ev, " duration=%d", M->encr_document->duration); } mprintf (ev, " size="); if (M->encr_document->size < (1 << 10)) { mprintf (ev, "%dB", M->encr_document->size); } else if (M->encr_document->size < (1 << 20)) { mprintf (ev, "%dKiB", M->encr_document->size >> 10); } else if (M->encr_document->size < (1 << 30)) { mprintf (ev, "%dMiB", M->encr_document->size >> 20); } else { mprintf (ev, "%dGiB", M->encr_document->size >> 30); } mprintf (ev, "]"); return; case tgl_message_media_geo: mprintf (ev, "[geo https://maps.google.com/?q=%.6lf,%.6lf]", M->geo.latitude, M->geo.longitude); return; case tgl_message_media_contact: mprintf (ev, "[contact] "); mpush_color (ev, COLOR_RED); mprintf (ev, "%s %s ", M->first_name, M->last_name); mpop_color (ev); mprintf (ev, "%s", M->phone); return; case tgl_message_media_unsupported: mprintf (ev, "[unsupported]"); return; case tgl_message_media_webpage: mprintf (ev, "[webpage:"); assert (M->webpage); if (M->webpage->url) { mprintf (ev, " url:'%s'", M->webpage->url); } if (M->webpage->title) { mprintf (ev, " title:'%s'", M->webpage->title); } if (M->webpage->description) { mprintf (ev, " description:'%s'", M->webpage->description); } if (M->webpage->author) { mprintf (ev, " author:'%s'", M->webpage->author); } mprintf (ev, "]"); break; case tgl_message_media_venue: mprintf (ev, "[geo https://maps.google.com/?q=%.6lf,%.6lf", M->venue.geo.latitude, M->venue.geo.longitude); if (M->venue.title) { mprintf (ev, " title:'%s'", M->venue.title); } if (M->venue.address) { mprintf (ev, " address:'%s'", M->venue.address); } if (M->venue.provider) { mprintf (ev, " provider:'%s'", M->venue.provider); } if (M->venue.venue_id) { mprintf (ev, " id:'%s'", M->venue.venue_id); } mprintf (ev, "]"); return; default: mprintf (ev, "x = %d\n", M->type); assert (0); } } int unknown_user_list_pos; int unknown_user_list[1000]; void print_peer_permanent_name (struct in_ev *ev, tgl_peer_id_t id) { mprintf (ev, "%s", print_permanent_peer_id (id)); } void print_user_name (struct in_ev *ev, tgl_peer_id_t id, tgl_peer_t *U) { assert (tgl_get_peer_type (id) == TGL_PEER_USER); mpush_color (ev, COLOR_RED); if (permanent_peer_id_mode) { print_peer_permanent_name (ev, id); mpop_color (ev); return; } if (!U) { mprintf (ev, "user#%d", tgl_get_peer_id (id)); int i; int ok = 1; for (i = 0; i < unknown_user_list_pos; i++) { if (unknown_user_list[i] == tgl_get_peer_id (id)) { ok = 0; break; } } if (ok) { assert (unknown_user_list_pos < 1000); unknown_user_list[unknown_user_list_pos ++] = tgl_get_peer_id (id); } } else { if (U->flags & (TGLUF_SELF | TGLUF_CONTACT)) { mpush_color (ev, COLOR_REDB); } if ((U->flags & TGLUF_DELETED)) { mprintf (ev, "deleted user#%d", tgl_get_peer_id (id)); } else if (!(U->flags & TGLUF_CREATED)) { mprintf (ev, "user#%d", tgl_get_peer_id (id)); } else if (use_ids) { mprintf (ev, "user#%d", tgl_get_peer_id (id)); } else if (!U->user.first_name || !strlen (U->user.first_name)) { mprintf (ev, "%s", U->user.last_name); } else if (!U->user.last_name || !strlen (U->user.last_name)) { mprintf (ev, "%s", U->user.first_name); } else { mprintf (ev, "%s %s", U->user.first_name, U->user.last_name); } if (U->flags & (TGLUF_SELF | TGLUF_CONTACT)) { mpop_color (ev); } } mpop_color (ev); } void print_chat_name (struct in_ev *ev, tgl_peer_id_t id, tgl_peer_t *C) { assert (tgl_get_peer_type (id) == TGL_PEER_CHAT); mpush_color (ev, COLOR_MAGENTA); if (permanent_peer_id_mode) { print_peer_permanent_name (ev, id); mpop_color (ev); return; } if (!C || use_ids) { mprintf (ev, "chat#%d", tgl_get_peer_id (id)); } else { mprintf (ev, "%s", C->chat.title); } mpop_color (ev); } void print_channel_name (struct in_ev *ev, tgl_peer_id_t id, tgl_peer_t *C) { assert (tgl_get_peer_type (id) == TGL_PEER_CHANNEL); mpush_color (ev, COLOR_CYAN); if (permanent_peer_id_mode) { print_peer_permanent_name (ev, id); mpop_color (ev); return; } if (!C || use_ids) { mprintf (ev, "channel#%d", tgl_get_peer_id (id)); } else { mprintf (ev, "%s", C->channel.title); } mpop_color (ev); } void print_encr_chat_name (struct in_ev *ev, tgl_peer_id_t id, tgl_peer_t *C) { assert (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT); mpush_color (ev, COLOR_MAGENTA); if (permanent_peer_id_mode) { print_peer_permanent_name (ev, id); mpop_color (ev); return; } if (!C || use_ids) { mprintf (ev, "encr_chat#%d", tgl_get_peer_id (id)); } else { mprintf (ev, "%s", C->print_name); } mpop_color (ev); } void print_peer_name (struct in_ev *ev, tgl_peer_id_t id, tgl_peer_t *C) { switch (tgl_get_peer_type (id)) { case TGL_PEER_USER: print_user_name (ev, id, C); return; case TGL_PEER_CHAT: print_chat_name (ev, id, C); return; case TGL_PEER_CHANNEL: print_channel_name (ev, id, C); return; case TGL_PEER_ENCR_CHAT: print_encr_chat_name (ev, id, C); return; default: assert (0); } } static char *monthes[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; void print_date (struct in_ev *ev, long t) { struct tm *tm = localtime ((void *)&t); if (time (0) - t < 12 * 60 * 60) { mprintf (ev, "[%02d:%02d] ", tm->tm_hour, tm->tm_min); } else if (time (0) - t < 24 * 60 * 60 * 180) { mprintf (ev, "[%02d %s]", tm->tm_mday, monthes[tm->tm_mon]); } else { mprintf (ev, "[%02d %s %d]", tm->tm_mday, monthes[tm->tm_mon], tm->tm_year + 1900); } } void print_date_full (struct in_ev *ev, long t) { struct tm *tm = localtime ((void *)&t); mprintf (ev, "[%04d/%02d/%02d %02d:%02d:%02d]", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); } void print_msg_id (struct in_ev *ev, tgl_message_id_t msg_id, struct tgl_message *M) { if (msg_num_mode) { if (!permanent_msg_id_mode) { if (M) { mprintf (ev, "%d", M->temp_id); } else { mprintf (ev, "???"); } } else { mprintf (ev, "%s", print_permanent_msg_id (msg_id)); } } } void print_service_message (struct in_ev *ev, struct tgl_message *M) { assert (M); //print_start (); mpush_color (ev, COLOR_GREY); if (tgl_get_peer_type (M->to_id) == TGL_PEER_CHANNEL) { mpush_color (ev, COLOR_CYAN); } else { mpush_color (ev, COLOR_MAGENTA); } print_msg_id (ev, M->permanent_id, M); mprintf (ev, " "); print_date (ev, M->date); mpop_color (ev); mprintf (ev, " "); if (tgl_get_peer_type (M->to_id) == TGL_PEER_CHAT) { print_chat_name (ev, M->to_id, tgl_peer_get (TLS, M->to_id)); } else if (tgl_get_peer_type (M->to_id) == TGL_PEER_CHANNEL) { print_channel_name (ev, M->to_id, tgl_peer_get (TLS, M->to_id)); } else { assert (tgl_get_peer_type (M->to_id) == TGL_PEER_ENCR_CHAT); print_encr_chat_name (ev, M->to_id, tgl_peer_get (TLS, M->to_id)); } if (tgl_get_peer_type (M->from_id) == TGL_PEER_USER) { mprintf (ev, " "); print_user_name (ev, M->from_id, tgl_peer_get (TLS, M->from_id)); } switch (M->action.type) { case tgl_message_action_none: mprintf (ev, "\n"); break; case tgl_message_action_geo_chat_create: mprintf (ev, "Created geo chat\n"); break; case tgl_message_action_geo_chat_checkin: mprintf (ev, "Checkin in geochat\n"); break; case tgl_message_action_chat_create: mprintf (ev, " created chat %s. %d users\n", M->action.title, M->action.user_num); break; case tgl_message_action_chat_edit_title: mprintf (ev, " changed title to %s\n", M->action.new_title); break; case tgl_message_action_chat_edit_photo: mprintf (ev, " changed photo\n"); break; case tgl_message_action_chat_delete_photo: mprintf (ev, " deleted photo\n"); break; case tgl_message_action_chat_add_users: mprintf (ev, " added users:"); { int i; for (i = 0; i < M->action.user_num; i++) { print_user_name (ev, tgl_set_peer_id (TGL_PEER_USER, M->action.users[i]), tgl_peer_get (TLS, tgl_set_peer_id (TGL_PEER_USER, M->action.users[i]))); } } mprintf (ev, "\n"); break; case tgl_message_action_chat_add_user_by_link: mprintf (ev, " added by link from "); print_user_name (ev, tgl_set_peer_id (TGL_PEER_USER, M->action.user), tgl_peer_get (TLS, tgl_set_peer_id (TGL_PEER_USER, M->action.user))); mprintf (ev, "\n"); break; case tgl_message_action_chat_delete_user: mprintf (ev, " deleted user "); print_user_name (ev, tgl_set_peer_id (TGL_PEER_USER, M->action.user), tgl_peer_get (TLS, tgl_set_peer_id (TGL_PEER_USER, M->action.user))); mprintf (ev, "\n"); break; case tgl_message_action_set_message_ttl: mprintf (ev, " set ttl to %d seconds. Unsupported yet\n", M->action.ttl); break; case tgl_message_action_read_messages: mprintf (ev, " %d messages marked read\n", M->action.read_cnt); break; case tgl_message_action_delete_messages: mprintf (ev, " %d messages deleted\n", M->action.delete_cnt); break; case tgl_message_action_screenshot_messages: mprintf (ev, " %d messages screenshoted\n", M->action.screenshot_cnt); break; case tgl_message_action_flush_history: mprintf (ev, " cleared history\n"); break; case tgl_message_action_resend: mprintf (ev, " resend query\n"); break; case tgl_message_action_notify_layer: mprintf (ev, " updated layer to %d\n", M->action.layer); break; case tgl_message_action_typing: mprintf (ev, " is "); print_typing (ev, M->action.typing); break; case tgl_message_action_noop: mprintf (ev, " noop\n"); break; case tgl_message_action_request_key: mprintf (ev, " request rekey #%016llx\n", M->action.exchange_id); break; case tgl_message_action_accept_key: mprintf (ev, " accept rekey #%016llx\n", M->action.exchange_id); break; case tgl_message_action_commit_key: mprintf (ev, " commit rekey #%016llx\n", M->action.exchange_id); break; case tgl_message_action_abort_key: mprintf (ev, " abort rekey #%016llx\n", M->action.exchange_id); break; case tgl_message_action_channel_create: mprintf (ev, " created channel %s\n", M->action.title); break; case tgl_message_action_migrated_to: mprintf (ev, " migrated to channel\n"); break; case tgl_message_action_migrated_from: mprintf (ev, " migrated from group '%s'\n", M->action.title); break; } mpop_color (ev); //print_end (); } tgl_peer_id_t last_from_id; tgl_peer_id_t last_to_id; void print_message (struct in_ev *ev, struct tgl_message *M) { assert (M); if (M->flags & (TGLMF_EMPTY | TGLMF_DELETED)) { return; } if (!(M->flags & TGLMF_CREATED)) { return; } if (M->flags & TGLMF_SERVICE) { print_service_message (ev, M); return; } if (!tgl_get_peer_type (M->to_id)) { logprintf ("Bad msg\n"); return; } last_from_id = M->from_id; last_to_id = M->to_id; //print_start (); if (tgl_get_peer_type (M->to_id) == TGL_PEER_USER) { if (M->flags & TGLMF_OUT) { mpush_color (ev, COLOR_GREEN); print_msg_id (ev, M->permanent_id, M); mprintf (ev, " "); print_date (ev, M->date); mpop_color (ev); mprintf (ev, " "); print_user_name (ev, M->to_id, tgl_peer_get (TLS, M->to_id)); mpush_color (ev, COLOR_GREEN); if (M->flags & TGLMF_UNREAD) { mprintf (ev, " <<< "); } else { mprintf (ev, " ««« "); } } else { mpush_color (ev, COLOR_BLUE); print_msg_id (ev, M->permanent_id, M); mprintf (ev, " "); print_date (ev, M->date); mpop_color (ev); mprintf (ev, " "); print_user_name (ev, M->from_id, tgl_peer_get (TLS, M->from_id)); mpush_color (ev, COLOR_BLUE); if (M->flags & TGLMF_UNREAD) { mprintf (ev, " >>> "); } else { mprintf (ev, " »»» "); } } } else if (tgl_get_peer_type (M->to_id) == TGL_PEER_ENCR_CHAT) { tgl_peer_t *P = tgl_peer_get (TLS, M->to_id); assert (P); if (M->flags & TGLMF_UNREAD) { mpush_color (ev, COLOR_GREEN); print_msg_id (ev, M->permanent_id, M); mprintf (ev, " "); print_date (ev, M->date); mprintf (ev, " "); mpush_color (ev, COLOR_CYAN); mprintf (ev, " %s", P->print_name); mpop_color (ev); if (M->flags & TGLMF_UNREAD) { mprintf (ev, " <<< "); } else { mprintf (ev, " ««« "); } } else { mpush_color (ev, COLOR_BLUE); print_msg_id (ev, M->permanent_id, M); mprintf (ev, " "); print_date (ev, M->date); mpush_color (ev, COLOR_CYAN); mprintf (ev, " %s", P->print_name); mpop_color (ev); if (M->flags & TGLMF_UNREAD) { mprintf (ev, " >>> "); } else { mprintf (ev, " »»» "); } } } else if (tgl_get_peer_type (M->to_id) == TGL_PEER_CHAT) { mpush_color (ev, COLOR_MAGENTA); print_msg_id (ev, M->permanent_id, M); mprintf (ev, " "); print_date (ev, M->date); mpop_color (ev); mprintf (ev, " "); print_chat_name (ev, M->to_id, tgl_peer_get (TLS, M->to_id)); mprintf (ev, " "); print_user_name (ev, M->from_id, tgl_peer_get (TLS, M->from_id)); if (!tgl_cmp_peer_id (M->from_id, TLS->our_id)) { mpush_color (ev, COLOR_GREEN); } else { mpush_color (ev, COLOR_BLUE); } if (M->flags & TGLMF_UNREAD) { mprintf (ev, " >>> "); } else { mprintf (ev, " »»» "); } } else { assert (tgl_get_peer_type (M->to_id) == TGL_PEER_CHANNEL); mpush_color (ev, COLOR_CYAN); print_msg_id (ev, M->permanent_id, M); mprintf (ev, " "); print_date (ev, M->date); mpop_color (ev); mprintf (ev, " "); print_channel_name (ev, M->to_id, tgl_peer_get (TLS, M->to_id)); if (tgl_get_peer_type (M->from_id) == TGL_PEER_USER) { mprintf (ev, " "); print_user_name (ev, M->from_id, tgl_peer_get (TLS, M->from_id)); if (!tgl_cmp_peer_id (M->from_id, TLS->our_id)) { mpush_color (ev, COLOR_GREEN); } else { mpush_color (ev, COLOR_BLUE); } } else { mpush_color (ev, COLOR_BLUE); } if (M->flags & TGLMF_UNREAD) { mprintf (ev, " >>> "); } else { mprintf (ev, " »»» "); } } if (tgl_get_peer_type (M->fwd_from_id) > 0) { mprintf (ev, "[fwd from "); print_peer_name (ev, M->fwd_from_id, tgl_peer_get (TLS, M->fwd_from_id)); mprintf (ev, " "); print_date (ev, M->date); mprintf (ev, "] "); } if (M->reply_id) { mprintf (ev, "[reply to "); tgl_message_id_t msg_id = M->permanent_id; msg_id.id = M->reply_id; struct tgl_message *N = tgl_message_get (TLS, &msg_id); print_msg_id (ev, msg_id, N); mprintf (ev, "] "); } if (M->flags & TGLMF_MENTION) { mprintf (ev, "[mention] "); } if (M->message && strlen (M->message)) { mprintf (ev, "%s", M->message); } if (M->media.type != tgl_message_media_none) { if (M->message && strlen (M->message)) { mprintf (ev, " "); } print_media (ev, &M->media); } mpop_color (ev); assert (!color_stack_pos); mprintf (ev, "\n"); //print_end(); } void play_sound (void) { printf ("\a"); } void set_interface_callbacks (void) { if (readline_disabled) { return; } readline_active = 1; rl_filename_quote_characters = strdup (" "); rl_basic_word_break_characters = strdup (" "); rl_callback_handler_install (get_default_prompt (), interpreter); rl_completion_entry_function = command_generator; } ================================================ FILE: interface.h ================================================ /* This file is part of telegram-cli. Telegram-cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Telegram-cli 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 telegram-cli. If not, see . Copyright Vitaly Valtman 2013-2015 */ #ifndef __INTERFACE_H__ #define __INTERFACE_H__ #include #include #define COLOR_RED "\033[0;31m" #define COLOR_REDB "\033[1;31m" #define COLOR_NORMAL "\033[0m" #define COLOR_GREEN "\033[32;1m" #define COLOR_GREY "\033[37;1m" #define COLOR_YELLOW "\033[33;1m" #define COLOR_BLUE "\033[34;1m" #define COLOR_MAGENTA "\033[35;1m" #define COLOR_CYAN "\033[36;1m" #define COLOR_LCYAN "\033[0;36m" #define COLOR_INVERSE "\033[7m" char *get_default_prompt (void); char *complete_none (const char *text, int state); char **complete_text (char *text, int start, int end); void interpreter (char *line); void interpreter_ex (char *line, void *ex); void rprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2))); void logprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2))); #define vlogprintf(v,...) \ do { \ if (TLS->verbosity >= (v)) {\ logprintf (__VA_ARGS__);\ }\ } while (0);\ //void hexdump (int *in_ptr, int *in_end); struct bufferevent; struct in_ev { struct bufferevent *bev; char in_buf[4096]; int in_buf_pos; int refcnt; int error; int fd; }; struct tgl_message; struct in_ev; void print_message (struct in_ev *ev, struct tgl_message *M); void print_chat_name (struct in_ev *ev, tgl_peer_id_t id, tgl_peer_t *C); void print_channel_name (struct in_ev *ev, tgl_peer_id_t id, tgl_peer_t *C); void print_user_name (struct in_ev *ev, tgl_peer_id_t id, tgl_peer_t *U); void print_encr_chat_name_full (struct in_ev *ev, tgl_peer_id_t id, tgl_peer_t *C); void print_encr_chat_name (struct in_ev *ev, tgl_peer_id_t id, tgl_peer_t *C); //void print_media (struct tgl_message_media *M); // void pop_color (void); void push_color (const char *color); void print_start (void); void print_end (void); void print_date_full (struct in_ev *ev, long t); void print_date (struct in_ev *ev, long t); void play_sound (void); void update_prompt (void); void set_interface_callbacks (void); char *print_permanent_msg_id (tgl_message_id_t id); char *print_permanent_peer_id (tgl_peer_id_t id); tgl_peer_id_t parse_input_peer_id (const char *s, int l, int mask); tgl_message_id_t parse_input_msg_id (const char *s, int l); #endif ================================================ FILE: json-tg.c ================================================ #include "config.h" #ifdef USE_JSON #include #include "json-tg.h" #include #include #include "interface.h" #include //format time: #include #ifndef json_boolean #define json_boolean(val) ((val) ? json_true() : json_false()) #endif extern struct tgl_state *TLS; void json_pack_peer_type (json_t *res, tgl_peer_id_t id) { int x = tgl_get_peer_type (id); switch (x) { case TGL_PEER_USER: assert (json_object_set (res, "peer_type", json_string ("user")) >= 0); break; case TGL_PEER_CHAT: assert (json_object_set (res, "peer_type", json_string ("chat")) >= 0); break; case TGL_PEER_ENCR_CHAT: assert (json_object_set (res, "peer_type", json_string ("encr_chat")) >= 0); break; case TGL_PEER_CHANNEL: assert (json_object_set (res, "peer_type", json_string ("channel")) >= 0); break; default: assert (0); } } int str_format_time(long when, char* string) { struct tm *tm = localtime ((void *)&when); return sprintf (string, "%04d-%02d-%02d %02d:%02d:%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); } void json_pack_user (json_t *res, tgl_peer_t *P) { if (P->user.first_name) { assert (json_object_set (res, "first_name", json_string (P->user.first_name)) >= 0); } if (P->user.status.when) { static char s[20]; str_format_time(P->user.status.when, s); assert (json_object_set (res, "when", json_string (s)) >= 0); } if (P->user.last_name) { assert (json_object_set (res, "last_name", json_string (P->user.last_name)) >= 0); } if (P->user.real_first_name) { assert (json_object_set (res, "real_first_name", json_string (P->user.real_first_name)) >= 0); } if (P->user.real_last_name) { assert (json_object_set (res, "real_last_name", json_string (P->user.real_last_name)) >= 0); } if (P->user.phone) { assert (json_object_set (res, "phone", json_string (P->user.phone)) >= 0); } if (P->user.username) { assert (json_object_set (res, "username", json_string (P->user.username)) >= 0); } } void json_pack_chat (json_t *res, tgl_peer_t *P) { assert (P->chat.title); assert (json_object_set (res, "title", json_string (P->chat.title)) >= 0); tgl_peer_id_t admin_id = TGL_MK_USER (P->chat.admin_id); assert (json_object_set (res, "admin", json_pack_peer (admin_id)) >= 0); assert (json_object_set (res, "members_num", json_integer (P->chat.users_num)) >= 0); if (P->chat.user_list) { json_t *m = json_array (); assert (m); int i; for (i = 0; i < P->chat.users_num; i++) { tgl_peer_id_t user_id = TGL_MK_USER (P->chat.user_list[i].user_id); tgl_peer_id_t inviter_id = TGL_MK_USER (P->chat.user_list[i].inviter_id); json_t *peer = json_pack_peer (user_id); assert (json_object_set (peer, "inviter", json_pack_peer (inviter_id)) >= 0); assert (json_array_append (m, peer) >= 0); } assert (json_object_set (res, "members", m) >= 0); } } void json_pack_channel (json_t *res, tgl_peer_t *P) { assert (P->channel.title); assert (json_object_set (res, "title", json_string (P->channel.title)) >= 0); assert (json_object_set (res, "participants_count", json_integer (P->channel.participants_count)) >= 0); assert (json_object_set (res, "admins_count", json_integer (P->channel.admins_count)) >= 0); assert (json_object_set (res, "kicked_count", json_integer (P->channel.kicked_count)) >= 0); } void json_pack_encr_chat (json_t *res, tgl_peer_t *P) { assert (json_object_set (res, "user", json_pack_peer (TGL_MK_USER (P->encr_chat.user_id))) >= 0); } json_t *json_pack_peer (tgl_peer_id_t id) { tgl_peer_t *P = tgl_peer_get (TLS, id); //assert (P); json_t *res = json_object (); assert (json_object_set (res, "id", json_string (print_permanent_peer_id (id))) >= 0); json_pack_peer_type (res, id); assert (json_object_set (res, "peer_id", json_integer (tgl_get_peer_id (id))) >= 0); assert (res); if (!P || !(P->flags & TGLPF_CREATED)) { static char s[100]; switch (tgl_get_peer_type (id)) { case TGL_PEER_USER: sprintf (s, "user#%d", tgl_get_peer_id (id)); break; case TGL_PEER_CHAT: sprintf (s, "chat#%d", tgl_get_peer_id (id)); break; case TGL_PEER_CHANNEL: sprintf (s, "channel#%d", tgl_get_peer_id (id)); break; case TGL_PEER_ENCR_CHAT: sprintf (s, "encr_chat#%d", tgl_get_peer_id (id)); break; default: assert (0); } assert (json_object_set (res, "print_name", json_string (s)) >= 0); return res; } if(P->print_name != NULL){ assert (json_object_set (res, "print_name", json_string (P->print_name)) >= 0); } else { assert (json_object_set (res, "print_name", json_string ("")) >= 0); } assert (json_object_set (res, "flags", json_integer (P->flags)) >= 0); switch (tgl_get_peer_type (id)) { case TGL_PEER_USER: json_pack_user (res, P); break; case TGL_PEER_CHAT: json_pack_chat (res, P); break; case TGL_PEER_ENCR_CHAT: json_pack_encr_chat (res, P); break; case TGL_PEER_CHANNEL: json_pack_channel (res, P); break; default: assert (0); } return res; } json_t *json_pack_updates (unsigned flags) { json_t *a = json_array (); if (flags & TGL_UPDATE_CREATED) { assert (json_array_append (a, json_string ("created")) >= 0); } if (flags & TGL_UPDATE_DELETED) { assert (json_array_append (a, json_string ("deleted")) >= 0); } if (flags & TGL_UPDATE_PHONE) { assert (json_array_append (a, json_string ("phone")) >= 0); } if (flags & TGL_UPDATE_CONTACT) { assert (json_array_append (a, json_string ("contact")) >= 0); } if (flags & TGL_UPDATE_PHOTO) { assert (json_array_append (a, json_string ("photo")) >= 0); } if (flags & TGL_UPDATE_BLOCKED) { assert (json_array_append (a, json_string ("blocked")) >= 0); } if (flags & TGL_UPDATE_REAL_NAME) { assert (json_array_append (a, json_string ("real_name")) >= 0); } if (flags & TGL_UPDATE_NAME) { assert (json_array_append (a, json_string ("name")) >= 0); } if (flags & TGL_UPDATE_REQUESTED) { assert (json_array_append (a, json_string ("requested")) >= 0); } if (flags & TGL_UPDATE_WORKING) { assert (json_array_append (a, json_string ("working")) >= 0); } if (flags & TGL_UPDATE_FLAGS) { assert (json_array_append (a, json_string ("flags")) >= 0); } if (flags & TGL_UPDATE_TITLE) { assert (json_array_append (a, json_string ("title")) >= 0); } if (flags & TGL_UPDATE_ADMIN) { assert (json_array_append (a, json_string ("admin")) >= 0); } if (flags & TGL_UPDATE_MEMBERS) { assert (json_array_append (a, json_string ("members")) >= 0); } if (flags & TGL_UPDATE_USERNAME) { assert (json_array_append (a, json_string ("username")) >= 0); } return a; } json_t *json_pack_media (struct tgl_message_media *M) { json_t *res = json_object (); switch (M->type) { case tgl_message_media_photo: assert (json_object_set (res, "type", json_string ("photo")) >= 0); if (M->caption) { assert (json_object_set (res, "caption", json_string (M->caption)) >= 0); } break; case tgl_message_media_document: case tgl_message_media_audio: case tgl_message_media_video: case tgl_message_media_document_encr: assert (json_object_set (res, "type", json_string ("document")) >= 0); break; case tgl_message_media_unsupported: assert (json_object_set (res, "type", json_string ("unsupported")) >= 0); break; case tgl_message_media_geo: assert (json_object_set (res, "type", json_string ("geo")) >= 0); assert (json_object_set (res, "longitude", json_real (M->geo.longitude)) >= 0); assert (json_object_set (res, "latitude", json_real (M->geo.latitude)) >= 0); break; case tgl_message_media_contact: assert (json_object_set (res, "type", json_string ("contact")) >= 0); assert (json_object_set (res, "phone", json_string (M->phone)) >= 0); assert (json_object_set (res, "first_name", json_string (M->first_name)) >= 0); assert (json_object_set (res, "last_name", json_string (M->last_name)) >= 0); assert (json_object_set (res, "user_id", json_integer (M->user_id)) >= 0); break; case tgl_message_media_webpage: assert (json_object_set (res, "type", json_string ("webpage")) >= 0); if (M->webpage->url) { assert (json_object_set (res, "url", json_string (M->webpage->url)) >= 0); } if (M->webpage->title) { assert (json_object_set (res, "title", json_string (M->webpage->title)) >= 0); } if (M->webpage->description) { assert (json_object_set (res, "description", json_string (M->webpage->description)) >= 0); } if (M->webpage->author) { assert (json_object_set (res, "author", json_string (M->webpage->author)) >= 0); } break; case tgl_message_media_venue: assert (json_object_set (res, "type", json_string ("venue")) >= 0); assert (json_object_set (res, "longitude", json_real (M->venue.geo.longitude)) >= 0); assert (json_object_set (res, "latitude", json_real (M->venue.geo.latitude)) >= 0); if (M->venue.title) { assert (json_object_set (res, "type", json_string (M->venue.title)) >= 0); } if (M->venue.address) { assert (json_object_set (res, "address", json_string (M->venue.address)) >= 0); } if (M->venue.provider) { assert (json_object_set (res, "provider", json_string (M->venue.provider)) >= 0); } if (M->venue.venue_id) { assert (json_object_set (res, "venue_id", json_string (M->venue.venue_id)) >= 0); } break; default: assert (json_object_set (res, "type", json_string ("???")) >= 0); } return res; } json_t *json_pack_typing (enum tgl_typing_status status) { json_t *res = json_object (); switch (status) { case tgl_typing_none: assert (json_object_set (res, "status", json_string ("doing nothing")) >= 0); break; case tgl_typing_typing: assert (json_object_set (res, "status", json_string ("typing")) >= 0); break; case tgl_typing_cancel: assert (json_object_set (res, "status", json_string ("deleting typed message")) >= 0); break; case tgl_typing_record_video: assert (json_object_set (res, "status", json_string ("recording video")) >= 0); break; case tgl_typing_upload_video: assert (json_object_set (res, "status", json_string ("uploading video")) >= 0); break; case tgl_typing_record_audio: assert (json_object_set (res, "status", json_string ("recording audio")) >= 0); break; case tgl_typing_upload_audio: assert (json_object_set (res, "status", json_string ("uploading audio")) >= 0); break; case tgl_typing_upload_photo: assert (json_object_set (res, "status", json_string ("uploading photo")) >= 0); break; case tgl_typing_upload_document: assert (json_object_set (res, "status", json_string ("uploading document")) >= 0); break; case tgl_typing_geo: assert (json_object_set (res, "status", json_string ("choosing location")) >= 0); break; case tgl_typing_choose_contact: assert (json_object_set (res, "status", json_string ("choosing contact")) >= 0); break; default: assert (json_object_set (res, "status", json_string ("???")) >= 0); break; } return res; } json_t *json_pack_service (struct tgl_message *M) { json_t *res = json_object (); switch (M->action.type) { case tgl_message_action_geo_chat_create: assert (json_object_set (res, "type", json_string ("geo_created")) >= 0); break; case tgl_message_action_geo_chat_checkin: assert (json_object_set (res, "type", json_string ("geo_checkin")) >= 0); break; case tgl_message_action_chat_create: assert (json_object_set (res, "type", json_string ("chat_created")) >= 0); assert (json_object_set (res, "title", json_string (M->action.title)) >= 0); break; case tgl_message_action_chat_edit_title: assert (json_object_set (res, "type", json_string ("chat_rename")) >= 0); assert (json_object_set (res, "title", json_string (M->action.title)) >= 0); break; case tgl_message_action_chat_edit_photo: assert (json_object_set (res, "type", json_string ("chat_change_photo")) >= 0); break; case tgl_message_action_chat_delete_photo: assert (json_object_set (res, "type", json_string ("chat_delete_photo")) >= 0); break; case tgl_message_action_chat_add_users: assert (json_object_set (res, "type", json_string ("chat_add_user")) >= 0); assert (json_object_set (res, "user", json_pack_peer (tgl_set_peer_id (TGL_PEER_USER, M->action.users[0]))) >= 0); break; case tgl_message_action_chat_add_user_by_link: assert (json_object_set (res, "type", json_string ("chat_add_user_link")) >= 0); assert (json_object_set (res, "user", json_pack_peer (tgl_set_peer_id (TGL_PEER_USER, M->action.user))) >= 0); break; case tgl_message_action_chat_delete_user: assert (json_object_set (res, "type", json_string ("chat_del_user")) >= 0); assert (json_object_set (res, "user", json_pack_peer (tgl_set_peer_id (TGL_PEER_USER, M->action.user))) >= 0); break; case tgl_message_action_set_message_ttl: assert (json_object_set (res, "type", json_string ("set_ttl")) >= 0); assert (json_object_set (res, "ttl", json_integer (M->action.ttl)) >= 0); break; case tgl_message_action_read_messages: assert (json_object_set (res, "type", json_string ("read")) >= 0); assert (json_object_set (res, "count", json_integer (M->action.read_cnt)) >= 0); break; case tgl_message_action_delete_messages: assert (json_object_set (res, "type", json_string ("delete")) >= 0); assert (json_object_set (res, "count", json_integer (M->action.delete_cnt)) >= 0); break; case tgl_message_action_screenshot_messages: assert (json_object_set (res, "type", json_string ("screenshot")) >= 0); assert (json_object_set (res, "count", json_integer (M->action.screenshot_cnt)) >= 0); break; case tgl_message_action_flush_history: assert (json_object_set (res, "type", json_string ("flush")) >= 0); break; case tgl_message_action_resend: assert (json_object_set (res, "type", json_string ("resend")) >= 0); break; case tgl_message_action_notify_layer: assert (json_object_set (res, "type", json_string ("notify_layer")) >= 0); assert (json_object_set (res, "layer", json_integer (M->action.layer)) >= 0); break; case tgl_message_action_typing: assert (json_object_set (res, "type", json_string ("typing")) >= 0); assert (json_array_append (res, json_pack_typing (M->action.typing)) >= 0); break; case tgl_message_action_noop: assert (json_object_set (res, "type", json_string ("noop")) >= 0); break; case tgl_message_action_request_key: assert (json_object_set (res, "type", json_string ("request_key")) >= 0); break; case tgl_message_action_accept_key: assert (json_object_set (res, "type", json_string ("accept_key")) >= 0); break; case tgl_message_action_commit_key: assert (json_object_set (res, "type", json_string ("commit_key")) >= 0); break; case tgl_message_action_abort_key: assert (json_object_set (res, "type", json_string ("abort_key")) >= 0); break; case tgl_message_action_channel_create: assert (json_object_set (res, "type", json_string ("channel_created")) >= 0); assert (json_object_set (res, "title", json_string (M->action.title)) >= 0); break; case tgl_message_action_migrated_to: assert (json_object_set (res, "type", json_string ("migrated_to")) >= 0); break; case tgl_message_action_migrated_from: assert (json_object_set (res, "type", json_string ("migrated_from")) >= 0); break; default: assert (json_object_set (res, "type", json_string ("???")) >= 0); break; } return res; } json_t *json_pack_message (struct tgl_message *M) { json_t *res = json_object (); assert (json_object_set (res, "event", json_string ("message")) >= 0); //will overwriten to service, if service. assert (json_object_set (res, "id", json_string (print_permanent_msg_id (M->permanent_id))) >= 0); if (!(M->flags & TGLMF_CREATED)) { return res; } assert (json_object_set (res, "flags", json_integer (M->flags)) >= 0); if (tgl_get_peer_type (M->fwd_from_id)) { assert (json_object_set (res, "fwd_from", json_pack_peer (M->fwd_from_id)) >= 0); assert (json_object_set (res, "fwd_date", json_integer (M->fwd_date)) >= 0); } if (M->reply_id) { tgl_message_id_t msg_id = M->permanent_id; msg_id.id = M->reply_id; assert (json_object_set (res, "reply_id", json_string (print_permanent_msg_id (msg_id))) >= 0); } if (M->flags & TGLMF_MENTION) { assert (json_object_set (res, "mention", json_true ()) >= 0); } assert (json_object_set (res, "from", json_pack_peer (M->from_id)) >= 0); assert (json_object_set (res, "to", json_pack_peer (M->to_id)) >= 0); assert (json_object_set (res, "out", json_boolean (M->flags & TGLMF_OUT)) >= 0); assert (json_object_set (res, "unread", json_boolean (M->flags & TGLMF_UNREAD)) >= 0); assert (json_object_set (res, "service", json_boolean (M->flags & TGLMF_SERVICE)) >= 0); assert (json_object_set (res, "date", json_integer (M->date)) >= 0); if (!(M->flags & TGLMF_SERVICE)) { if (M->message_len && M->message) { assert (json_object_set (res, "text", json_string (M->message)) >= 0); } if (M->media.type && M->media.type != tgl_message_media_none) { assert (json_object_set (res, "media", json_pack_media (&M->media)) >= 0); } } else { assert (json_object_set (res, "event", json_string ("service")) >= 0); assert (json_object_set (res, "action", json_pack_service (M)) >= 0); } return res; } json_t *json_pack_read (struct tgl_message *M) { json_t *res = json_pack_message (M); assert (json_object_set (res, "event", json_string ("read")) >= 0); //this will overwrite "event":"message" to "event":"read". return res; } json_t *json_pack_user_status (struct tgl_user *U) { json_t *res = json_object (); assert (json_object_set (res, "user", json_pack_peer (U->id)) >= 0); struct tgl_user_status *S = &U->status; assert (json_object_set (res, "online", json_boolean (S->online == 1)) >= 0); assert (json_object_set (res, "state", json_integer (S->online)) >= 0); if (S->online > 0 || S->online == -1) { static char s[20]; str_format_time(S->when, s); assert (json_object_set (res, "when", json_string (s)) >= 0); } else if (S->online == 0) { assert (json_object_set(res, "when", json_string("long time ago")) >= 0); } else if (S->online == -2) { assert (json_object_set(res, "when", json_string("recently")) >= 0); } else if (S->online == -3) { assert (json_object_set(res, "when", json_string("last week")) >= 0); } else if (S->online == -4) { assert (json_object_set (res, "when", json_string ("last month")) >= 0); } assert (json_object_set (res, "event", json_string ("online-status")) >= 0); //this will overwrite "event":"message" to "event":"read". return res; } #endif ================================================ FILE: json-tg.h ================================================ #ifndef __JSON_TG_H__ #define __JSON_TG_H__ #include "config.h" #ifdef USE_JSON #include #include #include json_t *json_pack_message (struct tgl_message *M); json_t *json_pack_updates (unsigned flags); json_t *json_pack_peer (tgl_peer_id_t id); json_t *json_pack_read (struct tgl_message *M); json_t *json_pack_user_status (struct tgl_user *U); #endif #endif ================================================ FILE: loop.c ================================================ /* This file is part of telegram-cli. Telegram-cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Telegram-cli 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 telegram-cli. If not, see . Copyright Vitaly Valtman 2013-2015 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #if USE_PYTHON #include "python-tg.h" #endif #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #define READLINE_CALLBACKS #include #include #include #include #ifdef READLINE_GNU #include #include #else #include #include #endif #include #include #include #include #include #include #include #include #ifdef EVENT_V2 #include #include #else #include #include "event-old.h" #endif #include "interface.h" #include "telegram.h" #include "loop.h" #if USE_LUA #include "lua-tg.h" #endif #include #include #include #include #include #include int verbosity; extern int readline_disabled; extern char *bot_hash; extern int bot_mode; int binlog_read; extern char *default_username; extern char *auth_token; void set_default_username (const char *s); extern int binlog_enabled; extern int unknown_user_list_pos; extern int unknown_user_list[]; int register_mode; extern int safe_quit; extern int sync_from_start; extern int disable_output; extern int reset_authorization; extern int sfd; extern int usfd; void got_it (char *line, int len); void write_state_file (void); static char *line_buffer; static int line_buffer_size; static int line_buffer_pos; static int delete_stdin_event; extern volatile int sigterm_cnt; extern char *start_command; extern struct tgl_state *TLS; extern int ipv6_enabled; struct event *term_ev = 0; int read_one_string; #define MAX_ONE_STRING_LEN 511 char one_string[MAX_ONE_STRING_LEN + 1]; int one_string_len; void (*one_string_cb)(struct tgl_state *TLS, const char *string[], void *arg); enum tgl_value_type one_string_type; int one_string_num; int one_string_total_args; char *one_string_results[10]; void *string_cb_arg; char *one_string_prompt; int one_string_flags; extern int disable_link_preview; void deactivate_readline (void); void reactivate_readline (void); void do_get_string (struct tgl_state *TLS); static void one_string_read_end (void) { printf ("\n"); fflush (stdout); read_one_string = 0; tfree_str (one_string_prompt); one_string_prompt = NULL; reactivate_readline (); one_string_results[one_string_num] = tstrdup (one_string); ++one_string_num; if (one_string_num < one_string_total_args) { do_get_string (TLS); } else { one_string_cb (TLS, (void *)one_string_results, string_cb_arg); int i; for (i = 0; i < one_string_total_args; i++) { tfree_str (one_string_results[i]); } } } void generate_prompt (enum tgl_value_type type, int num) { switch (type) { case tgl_phone_number: assert (!num); one_string_prompt = tstrdup ("phone number: "); one_string_flags = 0; return; case tgl_code: assert (!num); one_string_prompt = tstrdup ("code ('CALL' for phone code): "); one_string_flags = 0; return; case tgl_register_info: one_string_flags = 0; switch (num) { case 0: one_string_prompt = tstrdup ("register (Y/n): "); return; case 1: one_string_prompt = tstrdup ("first name: "); return; case 2: one_string_prompt = tstrdup ("last name: "); return; default: assert (0); } return; case tgl_new_password: one_string_flags = 1; switch (num) { case 0: one_string_prompt = tstrdup ("new password: "); return; case 1: one_string_prompt = tstrdup ("retype new password: "); return; default: assert (0); } return; case tgl_cur_and_new_password: one_string_flags = 1; switch (num) { case 0: one_string_prompt = tstrdup ("old password: "); return; case 1: one_string_prompt = tstrdup ("new password: "); return; case 2: one_string_prompt = tstrdup ("retype new password: "); return; default: assert (0); } return; case tgl_cur_password: one_string_flags = 1; assert (!num); one_string_prompt = tstrdup ("password: "); return; case tgl_bot_hash: one_string_flags = 0; assert (!num); one_string_prompt = tstrdup ("hash: "); return; default: assert (0); } } void do_get_string (struct tgl_state *TLS) { deactivate_readline (); generate_prompt (one_string_type, one_string_num); printf ("%s", one_string_prompt); fflush (stdout); read_one_string = 1; one_string_len = 0; } void do_get_values (struct tgl_state *TLS, enum tgl_value_type type, const char *prompt, int num_values, void (*callback)(struct tgl_state *TLS, const char *string[], void *arg), void *arg) { if (type == tgl_bot_hash && bot_hash) { assert (num_values == 1); one_string_results[0] = bot_hash; callback (TLS, (void *)one_string_results, arg); return; } one_string_cb = callback; one_string_num = 0; one_string_total_args = num_values; one_string_type = type; string_cb_arg = arg; do_get_string (TLS); } static void stdin_read_callback (evutil_socket_t fd, short what, void *arg) { if (!readline_disabled && !read_one_string) { rl_callback_read_char (); return; } if (read_one_string) { char c; int r = read (0, &c, 1); if (r <= 0) { perror ("read"); delete_stdin_event = 1; return; } if (c == '\n' || c == '\r') { one_string[one_string_len] = 0; one_string_read_end (); return; } if (one_string_len < MAX_ONE_STRING_LEN) { one_string[one_string_len ++] = c; if (!(one_string_flags & 1)) { printf ("%c", c); fflush (stdout); } } return; } if (line_buffer_pos == line_buffer_size) { line_buffer = realloc (line_buffer, line_buffer_size * 2 + 100); assert (line_buffer); line_buffer_size = line_buffer_size * 2 + 100; assert (line_buffer); } int r = read (0, line_buffer + line_buffer_pos, line_buffer_size - line_buffer_pos); if (r <= 0) { perror ("read"); delete_stdin_event = 1; return; } line_buffer_pos += r; while (1) { int p = 0; while (p < line_buffer_pos && line_buffer[p] != '\n') { p ++; } if (p < line_buffer_pos) { line_buffer[p] = 0; interpreter (line_buffer); memmove (line_buffer, line_buffer + p + 1, line_buffer_pos - p - 1); line_buffer_pos -= (p + 1); } else { break; } } } void net_loop (void) { delete_stdin_event = 0; if (verbosity >= E_DEBUG) { logprintf ("Starting netloop\n"); } term_ev = event_new (TLS->ev_base, 0, EV_READ | EV_PERSIST, stdin_read_callback, 0); event_add (term_ev, 0); int last_get_state = time (0); while (1) { event_base_loop (TLS->ev_base, EVLOOP_ONCE); if (term_ev && delete_stdin_event) { logprintf ("delete stdin\n"); event_free (term_ev); term_ev = 0; } #ifdef USE_LUA lua_do_all (); #endif #ifdef USE_PYTHON py_do_all (); #endif if (safe_quit && !TLS->active_queries) { printf ("All done. Exit\n"); do_halt (0); safe_quit = 0; } if (sigterm_cnt > 0) { do_halt (0); } if (time (0) - last_get_state > 3600) { tgl_do_lookup_state (TLS); last_get_state = time (0); } write_state_file (); update_prompt (); /* if (unknown_user_list_pos) { int i; for (i = 0; i < unknown_user_list_pos; i++) { tgl_do_get_user_info (TLS, TGL_MK_USER (unknown_user_list[i]), 0, 0, 0); } unknown_user_list_pos = 0; } */ } if (term_ev) { event_free (term_ev); term_ev = 0; } if (verbosity >= E_DEBUG) { logprintf ("End of netloop\n"); } } struct tgl_dc *cur_a_dc; int is_authorized (void) { return tgl_authorized_dc (TLS, cur_a_dc); } int all_authorized (void) { int i; for (i = 0; i <= TLS->max_dc_num; i++) if (TLS->DC_list[i]) { if (!tgl_authorized_dc (TLS, TLS->DC_list[i])) { return 0; } } return 1; } int zero[512]; int readline_active; int new_dc_num; int wait_dialog_list; extern struct tgl_update_callback upd_cb; #define DC_SERIALIZED_MAGIC 0x868aa81d #define STATE_FILE_MAGIC 0x28949a93 #define SECRET_CHAT_FILE_MAGIC 0x37a1988a char *get_auth_key_filename (void); char *get_state_filename (void); char *get_secret_chat_filename (void); void read_state_file (void) { if (binlog_enabled) { return; } int state_file_fd = open (get_state_filename (), O_CREAT | O_RDWR, 0600); if (state_file_fd < 0) { return; } int version, magic; if (read (state_file_fd, &magic, 4) < 4) { close (state_file_fd); return; } if (magic != (int)STATE_FILE_MAGIC) { close (state_file_fd); return; } if (read (state_file_fd, &version, 4) < 4) { close (state_file_fd); return; } assert (version >= 0); int x[4]; if (read (state_file_fd, x, 16) < 16) { close (state_file_fd); return; } int pts = x[0]; int qts = x[1]; int seq = x[2]; int date = x[3]; close (state_file_fd); bl_do_set_seq (TLS, seq); bl_do_set_pts (TLS, pts); bl_do_set_qts (TLS, qts); bl_do_set_date (TLS, date); } void write_state_file (void) { if (binlog_enabled) { return; } static int wseq; static int wpts; static int wqts; static int wdate; if (wseq >= TLS->seq && wpts >= TLS->pts && wqts >= TLS->qts && wdate >= TLS->date) { return; } wseq = TLS->seq; wpts = TLS->pts; wqts = TLS->qts; wdate = TLS->date; int state_file_fd = open (get_state_filename (), O_CREAT | O_RDWR, 0600); if (state_file_fd < 0) { logprintf ("Can not write state file '%s': %m\n", get_state_filename ()); do_halt (1); } int x[6]; x[0] = STATE_FILE_MAGIC; x[1] = 0; x[2] = wpts; x[3] = wqts; x[4] = wseq; x[5] = wdate; assert (write (state_file_fd, x, 24) == 24); close (state_file_fd); } void write_dc (struct tgl_dc *DC, void *extra) { int auth_file_fd = *(int *)extra; if (!DC) { int x = 0; assert (write (auth_file_fd, &x, 4) == 4); return; } else { int x = 1; assert (write (auth_file_fd, &x, 4) == 4); } assert (DC->flags & TGLDCF_LOGGED_IN); assert (write (auth_file_fd, &DC->options[0]->port, 4) == 4); int l = strlen (DC->options[0]->ip); assert (write (auth_file_fd, &l, 4) == 4); assert (write (auth_file_fd, DC->options[0]->ip, l) == l); assert (write (auth_file_fd, &DC->auth_key_id, 8) == 8); assert (write (auth_file_fd, DC->auth_key, 256) == 256); } void write_auth_file (void) { if (binlog_enabled) { return; } int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600); assert (auth_file_fd >= 0); int x = DC_SERIALIZED_MAGIC; assert (write (auth_file_fd, &x, 4) == 4); assert (write (auth_file_fd, &TLS->max_dc_num, 4) == 4); assert (write (auth_file_fd, &TLS->dc_working_num, 4) == 4); tgl_dc_iterator_ex (TLS, write_dc, &auth_file_fd); assert (write (auth_file_fd, &TLS->our_id.peer_id, 4) == 4); close (auth_file_fd); } void write_secret_chat (tgl_peer_t *Peer, void *extra) { struct tgl_secret_chat *P = (void *)Peer; if (tgl_get_peer_type (P->id) != TGL_PEER_ENCR_CHAT) { return; } if (P->state != sc_ok) { return; } int *a = extra; int fd = a[0]; a[1] ++; int id = tgl_get_peer_id (P->id); assert (write (fd, &id, 4) == 4); //assert (write (fd, &P->flags, 4) == 4); int l = strlen (P->print_name); assert (write (fd, &l, 4) == 4); assert (write (fd, P->print_name, l) == l); assert (write (fd, &P->user_id, 4) == 4); assert (write (fd, &P->admin_id, 4) == 4); assert (write (fd, &P->date, 4) == 4); assert (write (fd, &P->ttl, 4) == 4); assert (write (fd, &P->layer, 4) == 4); assert (write (fd, &P->access_hash, 8) == 8); assert (write (fd, &P->state, 4) == 4); assert (write (fd, &P->key_fingerprint, 8) == 8); assert (write (fd, &P->key, 256) == 256); assert (write (fd, &P->first_key_sha, 20) == 20); assert (write (fd, &P->in_seq_no, 4) == 4); assert (write (fd, &P->last_in_seq_no, 4) == 4); assert (write (fd, &P->out_seq_no, 4) == 4); } void write_secret_chat_file (void) { if (binlog_enabled) { return; } int secret_chat_fd = open (get_secret_chat_filename (), O_CREAT | O_RDWR, 0600); assert (secret_chat_fd >= 0); int x = SECRET_CHAT_FILE_MAGIC; assert (write (secret_chat_fd, &x, 4) == 4); x = 2; assert (write (secret_chat_fd, &x, 4) == 4); // version assert (write (secret_chat_fd, &x, 4) == 4); // num int y[2]; y[0] = secret_chat_fd; y[1] = 0; tgl_peer_iterator_ex (TLS, write_secret_chat, y); lseek (secret_chat_fd, 8, SEEK_SET); assert (write (secret_chat_fd, &y[1], 4) == 4); close (secret_chat_fd); } void read_dc (int auth_file_fd, int id, unsigned ver) { int port = 0; assert (read (auth_file_fd, &port, 4) == 4); int l = 0; assert (read (auth_file_fd, &l, 4) == 4); assert (l >= 0 && l < 100); char ip[100]; assert (read (auth_file_fd, ip, l) == l); ip[l] = 0; long long auth_key_id; static unsigned char auth_key[256]; assert (read (auth_file_fd, &auth_key_id, 8) == 8); assert (read (auth_file_fd, auth_key, 256) == 256); //bl_do_add_dc (id, ip, l, port, auth_key_id, auth_key); bl_do_dc_option (TLS, 0, id, "DC", 2, ip, l, port); bl_do_set_auth_key (TLS, id, auth_key); bl_do_dc_signed (TLS, id); } void empty_auth_file (void) { if (TLS->test_mode) { bl_do_dc_option (TLS, 0, 1, "", 0, TG_SERVER_TEST_1, strlen (TG_SERVER_TEST_1), 443); bl_do_dc_option (TLS, 0, 2, "", 0, TG_SERVER_TEST_2, strlen (TG_SERVER_TEST_2), 443); bl_do_dc_option (TLS, 0, 3, "", 0, TG_SERVER_TEST_3, strlen (TG_SERVER_TEST_3), 443); bl_do_set_working_dc (TLS, TG_SERVER_TEST_DEFAULT); } else { bl_do_dc_option (TLS, 0, 1, "", 0, TG_SERVER_1, strlen (TG_SERVER_1), 443); bl_do_dc_option (TLS, 0, 2, "", 0, TG_SERVER_2, strlen (TG_SERVER_2), 443); bl_do_dc_option (TLS, 0, 3, "", 0, TG_SERVER_3, strlen (TG_SERVER_3), 443); bl_do_dc_option (TLS, 0, 4, "", 0, TG_SERVER_4, strlen (TG_SERVER_4), 443); bl_do_dc_option (TLS, 0, 5, "", 0, TG_SERVER_5, strlen (TG_SERVER_5), 443); bl_do_set_working_dc (TLS, TG_SERVER_DEFAULT); } } int need_dc_list_update; void read_auth_file (void) { if (binlog_enabled) { return; } int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600); if (auth_file_fd < 0) { empty_auth_file (); return; } assert (auth_file_fd >= 0); unsigned x; unsigned m; if (read (auth_file_fd, &m, 4) < 4 || (m != DC_SERIALIZED_MAGIC)) { close (auth_file_fd); empty_auth_file (); return; } assert (read (auth_file_fd, &x, 4) == 4); assert (x > 0); int dc_working_num; assert (read (auth_file_fd, &dc_working_num, 4) == 4); int i; for (i = 0; i <= (int)x; i++) { int y; assert (read (auth_file_fd, &y, 4) == 4); if (y) { read_dc (auth_file_fd, i, m); } } bl_do_set_working_dc (TLS, dc_working_num); int our_id; int l = read (auth_file_fd, &our_id, 4); if (l < 4) { assert (!l); } if (our_id) { bl_do_set_our_id (TLS, TGL_MK_USER (our_id)); } close (auth_file_fd); } void read_secret_chat (int fd, int v) { int id, l, user_id, admin_id, date, ttl, layer, state; long long access_hash, key_fingerprint; static char s[1000]; static unsigned char key[256]; static unsigned char sha[20]; assert (read (fd, &id, 4) == 4); //assert (read (fd, &flags, 4) == 4); assert (read (fd, &l, 4) == 4); assert (l > 0 && l < 1000); assert (read (fd, s, l) == l); assert (read (fd, &user_id, 4) == 4); assert (read (fd, &admin_id, 4) == 4); assert (read (fd, &date, 4) == 4); assert (read (fd, &ttl, 4) == 4); assert (read (fd, &layer, 4) == 4); assert (read (fd, &access_hash, 8) == 8); assert (read (fd, &state, 4) == 4); assert (read (fd, &key_fingerprint, 8) == 8); assert (read (fd, &key, 256) == 256); assert (read (fd, sha, 20) == 20); int in_seq_no = 0, out_seq_no = 0, last_in_seq_no = 0; if (v >= 1) { assert (read (fd, &in_seq_no, 4) == 4); assert (read (fd, &last_in_seq_no, 4) == 4); assert (read (fd, &out_seq_no, 4) == 4); } bl_do_encr_chat (TLS, id, &access_hash, &date, &admin_id, &user_id, key, NULL, sha, &state, &ttl, &layer, &in_seq_no, &last_in_seq_no, &out_seq_no, &key_fingerprint, TGLECF_CREATE | TGLECF_CREATED, NULL, 0 ); } void read_secret_chat_file (void) { if (binlog_enabled) { return; } int secret_chat_fd = open (get_secret_chat_filename (), O_RDWR, 0600); if (secret_chat_fd < 0) { return; } //assert (secret_chat_fd >= 0); int x; if (read (secret_chat_fd, &x, 4) < 4) { close (secret_chat_fd); return; } if (x != SECRET_CHAT_FILE_MAGIC) { close (secret_chat_fd); return; } int v = 0; assert (read (secret_chat_fd, &v, 4) == 4); assert (v == 0 || v == 1 || v == 2); // version assert (read (secret_chat_fd, &x, 4) == 4); assert (x >= 0); while (x --> 0) { read_secret_chat (secret_chat_fd, v); } close (secret_chat_fd); } static void read_incoming (struct bufferevent *bev, void *_arg) { vlogprintf (E_WARNING, "Read from incoming connection\n"); struct in_ev *ev = _arg; assert (ev->bev == bev); ev->in_buf_pos += bufferevent_read (bev, ev->in_buf + ev->in_buf_pos, 4096 - ev->in_buf_pos); while (1) { int pos = 0; int ok = 0; while (pos < ev->in_buf_pos) { if (ev->in_buf[pos] == '\n') { if (!ev->error) { ev->in_buf[pos] = 0; interpreter_ex (ev->in_buf, ev); } else { ev->error = 0; } ok = 1; ev->in_buf_pos -= (pos + 1); memmove (ev->in_buf, ev->in_buf + pos + 1, ev->in_buf_pos); pos = 0; } else { pos ++; } } if (ok) { ev->in_buf_pos += bufferevent_read (bev, ev->in_buf + ev->in_buf_pos, 4096 - ev->in_buf_pos); } else { if (ev->in_buf_pos == 4096) { ev->error = 1; } break; } } } void event_incoming (struct bufferevent *bev, short what, void *_arg) { struct in_ev *ev = _arg; if (what & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) { vlogprintf (E_WARNING, "Closing incoming connection\n"); assert (ev->fd >= 0); close (ev->fd); bufferevent_free (bev); ev->bev = 0; if (!--ev->refcnt) { free (ev); } } } static void accept_incoming (evutil_socket_t efd, short what, void *arg) { vlogprintf (E_WARNING, "Accepting incoming connection\n"); socklen_t clilen = 0; struct sockaddr_in cli_addr; int fd = accept (efd, (struct sockaddr *)&cli_addr, &clilen); assert (fd >= 0); struct bufferevent *bev = bufferevent_socket_new (TLS->ev_base, fd, 0); struct in_ev *e = malloc (sizeof (*e)); e->bev = bev; e->refcnt = 1; e->in_buf_pos = 0; e->error = 0; e->fd = fd; bufferevent_setcb (bev, read_incoming, 0, event_incoming, e); bufferevent_enable (bev, EV_READ | EV_WRITE); } char *get_downloads_directory (void); void on_login (struct tgl_state *TLS) { write_auth_file (); } void on_failed_login (struct tgl_state *TLS) { logprintf ("login failed\n"); logprintf ("login error #%d: %s\n", TLS->error_code, TLS->error); logprintf ("you can relogin by deleting auth file or running telegram-cli with '-q' flag\n"); exit (2); } void on_started (struct tgl_state *TLS); void clist_cb (struct tgl_state *TLSR, void *callback_extra, int success, int size, tgl_peer_id_t peers[], tgl_message_id_t *last_msg_id[], int unread_count[]) { on_started (TLS); } void dlist_cb (struct tgl_state *TLSR, void *callback_extra, int success, int size, tgl_peer_id_t peers[], tgl_message_id_t *last_msg_id[], int unread_count[]) { tgl_do_get_channels_dialog_list (TLS, 100, 0, clist_cb, 0); } void on_started (struct tgl_state *TLS) { if (wait_dialog_list) { wait_dialog_list = 0; tgl_do_get_dialog_list (TLS, 100, 0, dlist_cb, 0); return; } #ifdef USE_LUA lua_diff_end (); #endif #ifdef USE_PYTHON py_diff_end (); #endif if (start_command) { safe_quit = 1; while (*start_command) { char *start = start_command; while (*start_command && *start_command != '\n') { start_command ++; } if (*start_command) { *start_command = 0; start_command ++; } interpreter_ex (start, 0); } } } int loop (void) { tgl_set_callback (TLS, &upd_cb); struct event_base *ev = event_base_new (); tgl_set_ev_base (TLS, ev); tgl_set_net_methods (TLS, &tgl_conn_methods); tgl_set_timer_methods (TLS, &tgl_libevent_timers); assert (TLS->timer_methods); tgl_set_download_directory (TLS, get_downloads_directory ()); tgl_register_app_id (TLS, TELEGRAM_CLI_APP_ID, TELEGRAM_CLI_APP_HASH); tgl_set_app_version (TLS, "Telegram-cli " TELEGRAM_CLI_VERSION); if (ipv6_enabled) { tgl_enable_ipv6 (TLS); } if (bot_mode) { tgl_enable_bot (TLS); } if (disable_link_preview) { tgl_disable_link_preview (TLS); } assert (tgl_init (TLS) >= 0); /*if (binlog_enabled) { double t = tglt_get_double_time (); if (verbosity >= E_DEBUG) { logprintf ("replay log start\n"); } tgl_replay_log (TLS); if (verbosity >= E_DEBUG) { logprintf ("replay log end in %lf seconds\n", tglt_get_double_time () - t); } tgl_reopen_binlog_for_writing (TLS); } else {*/ read_auth_file (); read_state_file (); read_secret_chat_file (); //} binlog_read = 1; #ifdef USE_LUA lua_binlog_end (); #endif #ifdef USE_PYTHON py_binlog_end (); #endif if (sfd >= 0) { struct event *ev = event_new (TLS->ev_base, sfd, EV_READ | EV_PERSIST, accept_incoming, 0); event_add (ev, 0); } if (usfd >= 0) { struct event *ev = event_new (TLS->ev_base, usfd, EV_READ | EV_PERSIST, accept_incoming, 0); event_add (ev, 0); } update_prompt (); if (reset_authorization) { tgl_peer_t *P = tgl_peer_get (TLS, TLS->our_id); if (P && P->user.phone && reset_authorization == 1) { set_default_username (P->user.phone); } bl_do_reset_authorization (TLS); } set_interface_callbacks (); tgl_login (TLS); net_loop (); return 0; } ================================================ FILE: loop.h ================================================ /* This file is part of telegram-cli. Telegram-cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Telegram-cli 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 telegram-cli. If not, see . Copyright Vitaly Valtman 2013-2015 */ #ifndef __LOOP_H__ #define __LOOP_H__ #define TELEGRAM_CLI_APP_HASH "36722c72256a24c1225de00eb6a1ca74" #define TELEGRAM_CLI_APP_ID 2899 int loop (void); void do_halt (int error); void write_auth_file (void); void write_state_file (void); void write_secret_chat_file (void); #endif ================================================ FILE: lua-tg.c ================================================ /* This file is part of telegram-cli. Telegram-cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Telegram-cli 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 telegram-cli. If not, see . Copyright Vitaly Valtman 2013-2015 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef USE_LUA #include "lua-tg.h" #include #include #include #include #include #ifdef EVENT_V2 #include #else #include #include "event-old.h" #endif lua_State *luaState; //#include "interface.h" //#include "auto/constants.h" #include #include #include "interface.h" #include extern int verbosity; extern struct tgl_state *TLS; static int have_file; void print_start (void); void print_end (void); int ps_lua_pcall (lua_State *l, int a, int b, int c) { print_start (); int r = lua_pcall (l, a, b, c); print_end (); return r; } #define my_lua_checkstack(L,x) assert (lua_checkstack (L, x)) void push_user (tgl_peer_t *P); void push_peer (tgl_peer_id_t id, tgl_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_lstring_field (const char *name, const char *value, int len) { assert (name && strlen (name)); if (!value || !len) { return; } my_lua_checkstack (luaState, 3); lua_pushstring (luaState, name); lua_pushlstring (luaState, value, len); lua_settable (luaState, -3); } void lua_add_string_field_arr (int num, const char *value) { if (!value || !strlen (value)) { return; } my_lua_checkstack (luaState, 3); lua_pushnumber (luaState, num); 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_tgl_peer_type (int x) { switch (x) { case TGL_PEER_USER: lua_pushstring (luaState, "user"); break; case TGL_PEER_CHAT: lua_pushstring (luaState, "chat"); break; case TGL_PEER_ENCR_CHAT: lua_pushstring (luaState, "encr_chat"); break; case TGL_PEER_CHANNEL: lua_pushstring (luaState, "channel"); break; default: assert (0); } } void push_user (tgl_peer_t *P) { 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); lua_add_string_field ("username", P->user.username); if (P->user.access_hash) { lua_add_num_field ("access_hash", 1); } } void push_chat (tgl_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); if (P->chat.user_list) { lua_pushstring (luaState, "members"); lua_newtable (luaState); int i; for (i = 0; i < P->chat.users_num; i++) { lua_pushnumber (luaState, i); tgl_peer_id_t id = TGL_MK_USER (P->chat.user_list[i].user_id); push_peer (id, tgl_peer_get (TLS, id)); lua_settable (luaState, -3); } lua_settable (luaState, -3); } } void push_encr_chat (tgl_peer_t *P) { my_lua_checkstack (luaState, 4); lua_pushstring (luaState, "user"); push_peer (TGL_MK_USER (P->encr_chat.user_id), tgl_peer_get (TLS, TGL_MK_USER (P->encr_chat.user_id))); lua_settable (luaState, -3); } void push_channel (tgl_peer_t *P) { my_lua_checkstack (luaState, 4); lua_add_string_field ("title", P->channel.title); lua_add_string_field ("about", P->channel.about); lua_add_num_field ("participants_count", P->channel.participants_count); lua_add_num_field ("admins_count", P->channel.admins_count); lua_add_num_field ("kicked_count", P->channel.kicked_count); } void push_update_types (unsigned flags) { my_lua_checkstack (luaState, 4); lua_newtable (luaState); int cc = 0; if (flags & TGL_UPDATE_CREATED) { lua_add_string_field_arr (cc++, "created"); } if (flags & TGL_UPDATE_DELETED) { lua_add_string_field_arr (cc++, "deleted"); } if (flags & TGL_UPDATE_PHONE) { lua_add_string_field_arr (cc++, "phone"); } if (flags & TGL_UPDATE_CONTACT) { lua_add_string_field_arr (cc++, "contact"); } if (flags & TGL_UPDATE_PHOTO) { lua_add_string_field_arr (cc++, "photo"); } if (flags & TGL_UPDATE_BLOCKED) { lua_add_string_field_arr (cc++, "blocked"); } if (flags & TGL_UPDATE_REAL_NAME) { lua_add_string_field_arr (cc++, "real_name"); } if (flags & TGL_UPDATE_NAME) { lua_add_string_field_arr (cc++, "name"); } if (flags & TGL_UPDATE_REQUESTED) { lua_add_string_field_arr (cc++, "requested"); } if (flags & TGL_UPDATE_WORKING) { lua_add_string_field_arr (cc++, "working"); } if (flags & TGL_UPDATE_FLAGS) { lua_add_string_field_arr (cc++, "flags"); } if (flags & TGL_UPDATE_TITLE) { lua_add_string_field_arr (cc++, "title"); } if (flags & TGL_UPDATE_ADMIN) { lua_add_string_field_arr (cc++, "admin"); } if (flags & TGL_UPDATE_MEMBERS) { lua_add_string_field_arr (cc++, "members"); } if (flags & TGL_UPDATE_ACCESS_HASH) { lua_add_string_field_arr (cc++, "access_hash"); } if (flags & TGL_UPDATE_USERNAME) { lua_add_string_field_arr (cc++, "username"); } } void push_peer (tgl_peer_id_t id, tgl_peer_t *P) { lua_newtable (luaState); lua_add_string_field ("id", print_permanent_peer_id (P ? P->id : id)); lua_pushstring (luaState, "peer_type"); push_tgl_peer_type (tgl_get_peer_type (id)); lua_settable (luaState, -3); lua_add_num_field ("peer_id", tgl_get_peer_id (id)); if (!P || !(P->flags & TGLPF_CREATED)) { lua_pushstring (luaState, "print_name"); static char s[100]; switch (tgl_get_peer_type (id)) { case TGL_PEER_USER: sprintf (s, "user#%d", tgl_get_peer_id (id)); break; case TGL_PEER_CHAT: sprintf (s, "chat#%d", tgl_get_peer_id (id)); break; case TGL_PEER_ENCR_CHAT: sprintf (s, "encr_chat#%d", tgl_get_peer_id (id)); break; case TGL_PEER_CHANNEL: sprintf (s, "channel#%d", tgl_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 (tgl_get_peer_type (id)) { case TGL_PEER_USER: push_user (P); break; case TGL_PEER_CHAT: push_chat (P); break; case TGL_PEER_ENCR_CHAT: push_encr_chat (P); break; case TGL_PEER_CHANNEL: push_channel (P); break; default: assert (0); } } void push_media (struct tgl_message_media *M) { my_lua_checkstack (luaState, 4); switch (M->type) { case tgl_message_media_photo: lua_newtable (luaState); lua_add_string_field ("type", "photo"); lua_add_string_field ("caption", M->caption); break; case tgl_message_media_document: case tgl_message_media_audio: case tgl_message_media_video: case tgl_message_media_document_encr: lua_newtable (luaState); lua_add_string_field ("type", "document"); break; case tgl_message_media_unsupported: lua_newtable (luaState); lua_add_string_field ("type", "unsupported"); break; case tgl_message_media_geo: lua_newtable (luaState); lua_add_string_field ("type", "geo"); lua_add_num_field ("longitude", M->geo.longitude); lua_add_num_field ("latitude", M->geo.latitude); break; case tgl_message_media_contact: lua_newtable (luaState); lua_add_string_field ("type", "contact"); 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; case tgl_message_media_webpage: lua_newtable (luaState); lua_add_string_field ("type", "webpage"); lua_add_string_field ("url", M->webpage->url); lua_add_string_field ("title", M->webpage->title); lua_add_string_field ("description", M->webpage->description); lua_add_string_field ("author", M->webpage->author); break; case tgl_message_media_venue: lua_newtable (luaState); lua_add_string_field ("type", "venue"); lua_add_num_field ("longitude", M->venue.geo.longitude); lua_add_num_field ("latitude", M->venue.geo.latitude); lua_add_string_field ("title", M->venue.title); lua_add_string_field ("address", M->venue.address); lua_add_string_field ("provider", M->venue.provider); lua_add_string_field ("venue_id", M->venue.venue_id); break; default: lua_pushstring (luaState, "???"); } } void push_service (struct tgl_message *M) { my_lua_checkstack (luaState, 4); switch (M->action.type) { case tgl_message_action_geo_chat_create: lua_newtable (luaState); lua_add_string_field ("type", "geo_created"); break; case tgl_message_action_geo_chat_checkin: lua_newtable (luaState); lua_add_string_field ("type", "geo_checkin"); break; case tgl_message_action_chat_create: lua_newtable (luaState); lua_add_string_field ("type", "chat_created"); lua_add_string_field ("title", M->action.title); break; case tgl_message_action_chat_edit_title: lua_newtable (luaState); lua_add_string_field ("type", "chat_rename"); lua_add_string_field ("title", M->action.title); break; case tgl_message_action_chat_edit_photo: lua_newtable (luaState); lua_add_string_field ("type", "chat_change_photo"); break; case tgl_message_action_chat_delete_photo: lua_newtable (luaState); lua_add_string_field ("type", "chat_delete_photo"); break; case tgl_message_action_chat_add_users: lua_newtable (luaState); lua_add_string_field ("type", "chat_add_user"); lua_pushstring (luaState, "user"); push_peer (tgl_set_peer_id (TGL_PEER_USER, M->action.users[0]), tgl_peer_get (TLS, tgl_set_peer_id (TGL_PEER_USER, M->action.users[0]))); lua_settable (luaState, -3); break; case tgl_message_action_chat_add_user_by_link: lua_newtable (luaState); lua_add_string_field ("type", "chat_add_user_link"); lua_pushstring (luaState, "link_issuer"); push_peer (tgl_set_peer_id (TGL_PEER_USER, M->action.user), tgl_peer_get (TLS, tgl_set_peer_id (TGL_PEER_USER, M->action.user))); lua_settable (luaState, -3); break; case tgl_message_action_chat_delete_user: lua_newtable (luaState); lua_add_string_field ("type", "chat_del_user"); lua_pushstring (luaState, "user"); push_peer (tgl_set_peer_id (TGL_PEER_USER, M->action.user), tgl_peer_get (TLS, tgl_set_peer_id (TGL_PEER_USER, M->action.user))); lua_settable (luaState, -3); break; case tgl_message_action_set_message_ttl: lua_newtable (luaState); lua_add_string_field ("type", "set_ttl"); lua_add_num_field ("ttl", M->action.ttl); break; case tgl_message_action_read_messages: lua_newtable (luaState); lua_add_string_field ("type", "read"); lua_add_num_field ("count", M->action.read_cnt); break; case tgl_message_action_delete_messages: lua_newtable (luaState); lua_add_string_field ("type", "delete"); lua_add_num_field ("count", M->action.delete_cnt); break; case tgl_message_action_screenshot_messages: lua_newtable (luaState); lua_add_string_field ("type", "screenshot"); lua_add_num_field ("count", M->action.screenshot_cnt); break; case tgl_message_action_flush_history: lua_newtable (luaState); lua_add_string_field ("type", "flush"); break; case tgl_message_action_resend: lua_newtable (luaState); lua_add_string_field ("type", "resend"); break; case tgl_message_action_notify_layer: lua_newtable (luaState); lua_add_string_field ("type", "set_layer"); lua_add_num_field ("layer", M->action.layer); break; case tgl_message_action_typing: lua_newtable (luaState); lua_add_string_field ("type", "typing"); break; case tgl_message_action_noop: lua_newtable (luaState); lua_add_string_field ("type", "nop"); break; case tgl_message_action_request_key: lua_newtable (luaState); lua_add_string_field ("type", "request_rekey"); break; case tgl_message_action_accept_key: lua_newtable (luaState); lua_add_string_field ("type", "accept_rekey"); break; case tgl_message_action_commit_key: lua_newtable (luaState); lua_add_string_field ("type", "commit_rekey"); break; case tgl_message_action_abort_key: lua_newtable (luaState); lua_add_string_field ("type", "abort_rekey"); break; case tgl_message_action_channel_create: lua_newtable (luaState); lua_add_string_field ("type", "channel_created"); lua_add_string_field ("title", M->action.title); break; case tgl_message_action_migrated_to: lua_newtable (luaState); lua_add_string_field ("type", "migrated_to"); break; case tgl_message_action_migrated_from: lua_newtable (luaState); lua_add_string_field ("type", "migrated_from"); break; default: lua_pushstring (luaState, "???"); break; } } void push_message (struct tgl_message *M) { assert (M); my_lua_checkstack (luaState, 10); lua_newtable (luaState); lua_add_string_field ("id", print_permanent_msg_id (M->permanent_id)); if (!(M->flags & TGLMF_CREATED)) { return; } lua_add_num_field ("flags", M->flags); if (tgl_get_peer_type (M->fwd_from_id)) { lua_pushstring (luaState, "fwd_from"); push_peer (M->fwd_from_id, tgl_peer_get (TLS, M->fwd_from_id)); lua_settable (luaState, -3); // fwd_from lua_add_num_field ("fwd_date", M->fwd_date); } if (M->reply_id) { tgl_message_id_t msg_id = M->permanent_id; msg_id.id = M->reply_id; lua_add_string_field ("reply_id", print_permanent_msg_id (msg_id)); } if (M->flags & TGLMF_MENTION) { lua_pushstring (luaState, "mention"); lua_pushboolean (luaState, 1); lua_settable (luaState, -3); } lua_pushstring (luaState, "from"); push_peer (M->from_id, tgl_peer_get (TLS, M->from_id)); lua_settable (luaState, -3); lua_pushstring (luaState, "to"); push_peer (M->to_id, tgl_peer_get (TLS, M->to_id)); lua_settable (luaState, -3); lua_pushstring (luaState, "out"); lua_pushboolean (luaState, (M->flags & TGLMF_OUT) != 0); lua_settable (luaState, -3); lua_pushstring (luaState, "unread"); lua_pushboolean (luaState, (M->flags & TGLMF_UNREAD) != 0); 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->flags & TGLMF_SERVICE) != 0); lua_settable (luaState, -3); if (!(M->flags & TGLMF_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 != tgl_message_media_none) { lua_pushstring (luaState, "media"); push_media (&M->media); lua_settable (luaState, -3); } } else { lua_pushstring (luaState, "action"); push_service (M); 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 = ps_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 = ps_lua_pcall (luaState, 0, 0, 0); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } } void lua_our_id (tgl_peer_id_t 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, tgl_get_peer_id (id)); assert (lua_gettop (luaState) == 2); int r = ps_lua_pcall (luaState, 1, 0, 0); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } } void lua_new_msg (struct tgl_message *M) { 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 = ps_lua_pcall (luaState, 1, 0, 0); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } } void lua_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { if (!have_file) { return; } lua_settop (luaState, 0); //lua_checkstack (luaState, 20); my_lua_checkstack (luaState, 20); lua_getglobal (luaState, "on_secret_chat_update"); push_peer (C->id, (void *)C); push_update_types (flags); assert (lua_gettop (luaState) == 3); int r = ps_lua_pcall (luaState, 2, 0, 0); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } } void lua_user_update (struct tgl_user *U, unsigned flags) { 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); push_update_types (flags); assert (lua_gettop (luaState) == 3); int r = ps_lua_pcall (luaState, 2, 0, 0); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } } void lua_chat_update (struct tgl_chat *C, unsigned flags) { 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); push_update_types (flags); assert (lua_gettop (luaState) == 3); int r = ps_lua_pcall (luaState, 2, 0, 0); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } } //extern tgl_peer_t *Peers[]; //extern int peer_num; #define MAX_LUA_COMMANDS 1000 struct lua_arg { int flags; union { tgl_message_id_t msg_id; tgl_peer_id_t peer_id; char *str; long long num; double dnum; void *ptr; }; }; struct lua_arg lua_ptr[MAX_LUA_COMMANDS]; static int pos; static inline tgl_peer_t *get_peer (const char *s) { return tgl_peer_get_by_name (TLS, s); } enum lua_query_type { lq_contact_list, lq_dialog_list, lq_msg, lq_msg_channel, lq_send_typing, lq_send_typing_abort, lq_rename_chat, lq_send_photo, lq_chat_set_photo, lq_set_profile_photo, lq_set_profile_name, lq_send_video, lq_send_text, lq_reply, lq_fwd, lq_fwd_media, lq_load_photo, lq_load_video_thumb, lq_load_video, lq_chat_info, lq_channel_info, lq_user_info, lq_history, lq_chat_add_user, lq_chat_del_user, lq_add_contact, lq_del_contact, lq_rename_contact, lq_search, lq_global_search, lq_mark_read, lq_create_secret_chat, lq_create_group_chat, lq_send_audio, lq_send_document, lq_send_file, lq_load_audio, lq_load_document, lq_load_document_thumb, lq_delete_msg, lq_restore_msg, lq_accept_secret_chat, lq_send_contact, lq_status_online, lq_status_offline, lq_send_location, lq_extf, lq_import_chat_link, lq_export_chat_link, lq_channel_invite_user, lq_channel_kick_user, lq_channel_get_admins, lq_channel_get_users }; struct lua_query_extra { int func; int param; }; void lua_empty_cb (struct tgl_state *TLSR, void *cb_extra, int success) { assert (TLSR == TLS); struct lua_query_extra *cb = cb_extra; lua_settop (luaState, 0); //lua_checkstack (luaState, 20); my_lua_checkstack (luaState, 20); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); lua_pushnumber (luaState, success); assert (lua_gettop (luaState) == 3); int r = ps_lua_pcall (luaState, 2, 0, 0); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } free (cb); } void lua_contact_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_user **UL) { assert (TLSR == TLS); struct lua_query_extra *cb = cb_extra; lua_settop (luaState, 0); //lua_checkstack (luaState, 20); my_lua_checkstack (luaState, 20); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); lua_pushnumber (luaState, success); if (success) { lua_newtable (luaState); int i; for (i = 0; i < num; i++) { lua_pushnumber (luaState, i); push_peer (UL[i]->id, (void *)UL[i]); lua_settable (luaState, -3); } } else { lua_pushboolean (luaState, 0); } assert (lua_gettop (luaState) == 4); int r = ps_lua_pcall (luaState, 3, 0, 0); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } free (cb); } void lua_dialog_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, tgl_peer_id_t peers[], tgl_message_id_t *msgs[], int unread[]) { assert (TLSR == TLS); struct lua_query_extra *cb = cb_extra; lua_settop (luaState, 0); //lua_checkstack (luaState, 20); my_lua_checkstack (luaState, 20); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); lua_pushnumber (luaState, success); if (success) { lua_newtable (luaState); int i; for (i = 0; i < num; i++) { lua_pushnumber (luaState, i); lua_newtable (luaState); lua_pushstring (luaState, "peer"); push_peer (peers[i], tgl_peer_get (TLS, peers[i])); lua_settable (luaState, -3); struct tgl_message *M = tgl_message_get (TLS, msgs[i]); if (M && (M->flags & TGLMF_CREATED)) { lua_pushstring (luaState, "message"); push_message (M); lua_settable (luaState, -3); } lua_pushstring (luaState, "unread"); lua_pushnumber (luaState, unread[i]); lua_settable (luaState, -3); lua_settable (luaState, -3); } } else { lua_pushboolean (luaState, 0); } assert (lua_gettop (luaState) == 4); int r = ps_lua_pcall (luaState, 3, 0, 0); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } free (cb); } void lua_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_message *M) { assert (TLSR == TLS); struct lua_query_extra *cb = cb_extra; lua_settop (luaState, 0); //lua_checkstack (luaState, 20); my_lua_checkstack (luaState, 20); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); lua_pushnumber (luaState, success); if (success && M && (M->flags & TGLMF_CREATED)) { push_message (M); } else { lua_pushboolean (luaState, 0); } assert (lua_gettop (luaState) == 4); int r = ps_lua_pcall (luaState, 3, 0, 0); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } free (cb); } void lua_one_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, int size, struct tgl_message *M[]) { assert (TLSR == TLS); struct lua_query_extra *cb = cb_extra; lua_settop (luaState, 0); //lua_checkstack (luaState, 20); my_lua_checkstack (luaState, 20); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); lua_pushnumber (luaState, success); if (success && size > 0 && M[0] && (M[0]->flags & TGLMF_CREATED)) { push_message (M[0]); } else { lua_pushboolean (luaState, 0); } assert (lua_gettop (luaState) == 4); int r = ps_lua_pcall (luaState, 3, 0, 0); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } free (cb); } void lua_msg_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_message *M[]) { assert (TLSR == TLS); struct lua_query_extra *cb = cb_extra; lua_settop (luaState, 0); //lua_checkstack (luaState, 20); my_lua_checkstack (luaState, 20); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); lua_pushnumber (luaState, success); if (success) { lua_newtable (luaState); int i; for (i = 0; i < num; i++) { lua_pushnumber (luaState, i); push_message (M[i]); lua_settable (luaState, -3); } } else { lua_pushboolean (luaState, 0); } assert (lua_gettop (luaState) == 4); int r = ps_lua_pcall (luaState, 3, 0, 0); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } free (cb); } void lua_file_cb (struct tgl_state *TLSR, void *cb_extra, int success, const char *file_name) { assert (TLSR == TLS); struct lua_query_extra *cb = cb_extra; lua_settop (luaState, 0); //lua_checkstack (luaState, 20); my_lua_checkstack (luaState, 20); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); lua_pushnumber (luaState, success); if (success) { lua_pushstring (luaState, file_name); } else { lua_pushboolean (luaState, 0); } assert (lua_gettop (luaState) == 4); int r = ps_lua_pcall (luaState, 3, 0, 0); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } free (cb); } void lua_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_chat *C) { assert (TLSR == TLS); struct lua_query_extra *cb = cb_extra; lua_settop (luaState, 0); //lua_checkstack (luaState, 20); my_lua_checkstack (luaState, 20); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); lua_pushnumber (luaState, success); if (success) { push_peer (C->id, (void *)C); } else { lua_pushboolean (luaState, 0); } assert (lua_gettop (luaState) == 4); int r = ps_lua_pcall (luaState, 3, 0, 0); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } free (cb); } void lua_secret_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_secret_chat *C) { assert (TLSR == TLS); struct lua_query_extra *cb = cb_extra; lua_settop (luaState, 0); //lua_checkstack (luaState, 20); my_lua_checkstack (luaState, 20); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); lua_pushnumber (luaState, success); if (success) { push_peer (C->id, (void *)C); } else { lua_pushboolean (luaState, 0); } assert (lua_gettop (luaState) == 4); int r = ps_lua_pcall (luaState, 3, 0, 0); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } free (cb); } void lua_channel_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_channel *C) { assert (TLSR == TLS); struct lua_query_extra *cb = cb_extra; lua_settop (luaState, 0); //lua_checkstack (luaState, 20); my_lua_checkstack (luaState, 20); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); lua_pushnumber (luaState, success); if (success) { push_peer (C->id, (void *)C); } else { lua_pushboolean (luaState, 0); } assert (lua_gettop (luaState) == 4); int r = ps_lua_pcall (luaState, 3, 0, 0); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } free (cb); } void lua_user_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_user *C) { assert (TLSR == TLS); struct lua_query_extra *cb = cb_extra; lua_settop (luaState, 0); //lua_checkstack (luaState, 20); my_lua_checkstack (luaState, 20); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); lua_pushnumber (luaState, success); if (success) { push_peer (C->id, (void *)C); } else { lua_pushboolean (luaState, 0); } assert (lua_gettop (luaState) == 4); int r = ps_lua_pcall (luaState, 3, 0, 0); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } free (cb); } void lua_str_cb (struct tgl_state *TLSR, void *cb_extra, int success, const char *data) { assert (TLSR == TLS); struct lua_query_extra *cb = cb_extra; lua_settop (luaState, 0); //lua_checkstack (luaState, 20); my_lua_checkstack (luaState, 20); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func); lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param); lua_pushnumber (luaState, success); if (success) { lua_pushstring (luaState, data); } else { lua_pushboolean (luaState, 0); } assert (lua_gettop (luaState) == 4); int r = ps_lua_pcall (luaState, 3, 0, 0); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func); luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } free (cb); } #define LUA_STR_ARG(n) lua_ptr[n].str, strlen (lua_ptr[n].str) void lua_do_all (void) { int p = 0; while (p < pos) { int l = lua_ptr[p ++].num; assert (p + l + 1 <= pos); enum lua_query_type f = lua_ptr[p ++].num; struct tgl_message *M; int q = p; tgl_message_id_t *tmp_msg_id; switch (f) { case lq_contact_list: tgl_do_update_contact_list (TLS, lua_contact_list_cb, lua_ptr[p ++].ptr); break; case lq_dialog_list: tgl_do_get_dialog_list (TLS, 100, 0, lua_dialog_list_cb, lua_ptr[p ++].ptr); break; case lq_msg: tgl_do_send_message (TLS, lua_ptr[p + 1].peer_id, LUA_STR_ARG (p + 2), 0, NULL, lua_msg_cb, lua_ptr[p].ptr); p += 3; break; case lq_msg_channel: tgl_do_send_message (TLS, lua_ptr[p + 1].peer_id, LUA_STR_ARG (p + 2), 256, NULL, lua_msg_cb, lua_ptr[p].ptr); p += 3; break; case lq_send_typing: tgl_do_send_typing (TLS, lua_ptr[p + 1].peer_id, tgl_typing_typing, lua_empty_cb, lua_ptr[p].ptr); p += 2; break; case lq_send_typing_abort: tgl_do_send_typing (TLS, lua_ptr[p + 1].peer_id, tgl_typing_cancel, lua_empty_cb, lua_ptr[p].ptr); p += 2; break; case lq_rename_chat: tgl_do_rename_chat (TLS, lua_ptr[p + 1].peer_id, LUA_STR_ARG (p + 2), lua_empty_cb, lua_ptr[p].ptr); p += 3; break; case lq_send_photo: tgl_do_send_document (TLS, lua_ptr[p + 1].peer_id, lua_ptr[p + 2].str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO, lua_msg_cb, lua_ptr[p].ptr); p += 3; break; case lq_send_video: tgl_do_send_document (TLS, lua_ptr[p + 1].peer_id, lua_ptr[p + 2].str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_VIDEO, lua_msg_cb, lua_ptr[p].ptr); p += 3; break; case lq_send_audio: tgl_do_send_document (TLS, lua_ptr[p + 1].peer_id, lua_ptr[p + 2].str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_AUDIO, lua_msg_cb, lua_ptr[p].ptr); p += 3; break; case lq_send_document: tgl_do_send_document (TLS, lua_ptr[p + 1].peer_id, lua_ptr[p + 2].str, NULL, 0, 0, lua_msg_cb, lua_ptr[p].ptr); p += 3; break; case lq_send_file: tgl_do_send_document (TLS, lua_ptr[p + 1].peer_id, lua_ptr[p + 2].str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_AUTO, lua_msg_cb, lua_ptr[p].ptr); p += 3; break; case lq_send_text: tgl_do_send_text (TLS, lua_ptr[p + 1].peer_id, lua_ptr[p + 2].str, 0, lua_msg_cb, lua_ptr[p].ptr); p += 3; break; case lq_chat_set_photo: tgl_do_set_chat_photo (TLS, lua_ptr[p + 1].peer_id, lua_ptr[p + 2].str, lua_empty_cb, lua_ptr[p].ptr); p += 3; break; case lq_load_photo: case lq_load_video: case lq_load_audio: case lq_load_document: M = tgl_message_get (TLS, &lua_ptr[p + 1].msg_id); if (!M || (M->media.type != tgl_message_media_photo && M->media.type != tgl_message_media_document && M->media.type != tgl_message_media_document_encr)) { lua_file_cb (TLS, lua_ptr[p].ptr, 0, 0); } else { if (M->media.type == tgl_message_media_photo) { assert (M->media.photo); tgl_do_load_photo (TLS, M->media.photo, lua_file_cb, lua_ptr[p].ptr); } else if (M->media.type == tgl_message_media_document) { assert (M->media.document); tgl_do_load_document (TLS, M->media.document, lua_file_cb, lua_ptr[p].ptr); } else { tgl_do_load_encr_document (TLS, M->media.encr_document, lua_file_cb, lua_ptr[p].ptr); } } p += 2; break; case lq_load_video_thumb: case lq_load_document_thumb: M = tgl_message_get (TLS, &lua_ptr[p + 1].msg_id); if (!M || (M->media.type != tgl_message_media_document)) { lua_file_cb (TLS, lua_ptr[p].ptr, 0, 0); } else { tgl_do_load_document_thumb (TLS, M->media.document, lua_file_cb, lua_ptr[p].ptr); } p += 2; break; case lq_reply: tgl_do_reply_message (TLS, &lua_ptr[p + 1].msg_id, LUA_STR_ARG (p + 2), 0, lua_msg_cb, lua_ptr[p].ptr); p += 3; break; case lq_fwd: tmp_msg_id = &lua_ptr[p + 2].msg_id; tgl_do_forward_messages (TLS, lua_ptr[p + 1].peer_id, 1, (void *)&tmp_msg_id, 0, lua_one_msg_cb, lua_ptr[p].ptr); p += 3; break; case lq_fwd_media: tgl_do_forward_media (TLS, lua_ptr[p + 1].peer_id, &lua_ptr[p + 2].msg_id, 0, lua_msg_cb, lua_ptr[p].ptr); p += 3; break; case lq_chat_info: tgl_do_get_chat_info (TLS, lua_ptr[p + 1].peer_id, 0, lua_chat_cb, lua_ptr[p].ptr); p += 2; break; case lq_channel_info: tgl_do_get_channel_info (TLS, lua_ptr[p + 1].peer_id, 0, lua_channel_cb, lua_ptr[p].ptr); p += 2; break; case lq_user_info: tgl_do_get_user_info (TLS, lua_ptr[p + 1].peer_id, 0, lua_user_cb, lua_ptr[p].ptr); p += 2; break; case lq_history: tgl_do_get_history (TLS, lua_ptr[p + 1].peer_id, 0, lua_ptr[p + 2].num, 0, lua_msg_list_cb, lua_ptr[p].ptr); p += 3; break; case lq_chat_add_user: tgl_do_add_user_to_chat (TLS, lua_ptr[p + 1].peer_id, lua_ptr[p + 2].peer_id, 10, lua_empty_cb, lua_ptr[p].ptr); p += 3; break; case lq_chat_del_user: tgl_do_del_user_from_chat (TLS, lua_ptr[p + 1].peer_id, lua_ptr[p + 2].peer_id, lua_empty_cb, lua_ptr[p].ptr); p += 3; break; case lq_add_contact: tgl_do_add_contact (TLS, LUA_STR_ARG (p + 1), LUA_STR_ARG (p + 2), LUA_STR_ARG (p + 3), 0, lua_contact_list_cb, lua_ptr[p].ptr); p += 4; break; case lq_del_contact: tgl_do_del_contact (TLS, lua_ptr[p + 1].peer_id, lua_empty_cb, lua_ptr[p].ptr); p += 2; break; case lq_rename_contact: tgl_do_add_contact (TLS, LUA_STR_ARG (p + 1), LUA_STR_ARG (p + 2), LUA_STR_ARG (p + 3), 1, lua_contact_list_cb, lua_ptr[p].ptr); p += 4; break; case lq_search: tgl_do_msg_search (TLS, lua_ptr[p + 1].peer_id, 0, 0, 40, 0, LUA_STR_ARG (p + 2), lua_msg_list_cb, lua_ptr[p].ptr); p += 3; break; case lq_global_search: tgl_do_msg_search (TLS, tgl_set_peer_id (TGL_PEER_UNKNOWN, 0), 0, 0, 40, 0, LUA_STR_ARG (p + 1), lua_msg_list_cb, lua_ptr[p].ptr); p += 2; break; case lq_mark_read: tgl_do_mark_read (TLS, lua_ptr[p + 1].peer_id, lua_empty_cb, lua_ptr[p].ptr); p += 2; break; case lq_set_profile_photo: tgl_do_set_profile_photo (TLS, lua_ptr[p + 1].str, lua_empty_cb, lua_ptr[p].ptr); p += 2; break; case lq_set_profile_name: tgl_do_set_profile_name (TLS, LUA_STR_ARG (p + 1), LUA_STR_ARG (p + 2), lua_user_cb, lua_ptr[p].ptr); p += 3; break; case lq_create_secret_chat: tgl_do_create_secret_chat (TLS, lua_ptr[p + 1].peer_id, lua_secret_chat_cb, lua_ptr[p].ptr); p += 2; break; case lq_create_group_chat: tgl_do_create_group_chat (TLS, 1, &lua_ptr[p + 1].peer_id, LUA_STR_ARG (p + 2), lua_empty_cb, lua_ptr[p].ptr); p += 3; break; case lq_delete_msg: tgl_do_delete_msg (TLS, &lua_ptr[p + 1].msg_id, lua_empty_cb, lua_ptr[p].ptr); p += 2; break; case lq_accept_secret_chat: tgl_do_accept_encr_chat_request (TLS, (void *)tgl_peer_get (TLS, lua_ptr[p + 1].peer_id), lua_secret_chat_cb, lua_ptr[p].ptr); p += 2; break; case lq_send_contact: tgl_do_send_contact (TLS, lua_ptr[p + 1].peer_id, LUA_STR_ARG (p + 2), LUA_STR_ARG (p + 3), LUA_STR_ARG (p + 4), 0, lua_msg_cb, lua_ptr[p].ptr); p += 5; break; case lq_status_online: tgl_do_update_status (TLS, 1, lua_empty_cb, lua_ptr[p].ptr); p ++; break; case lq_status_offline: tgl_do_update_status (TLS, 0, lua_empty_cb, lua_ptr[p].ptr); p ++; break; case lq_extf: tgl_do_send_extf (TLS, LUA_STR_ARG (p + 1), lua_str_cb, lua_ptr[p].ptr); p += 2; break; case lq_import_chat_link: tgl_do_import_chat_link (TLS, LUA_STR_ARG (p + 1), lua_empty_cb, lua_ptr[p].ptr); p += 2; break; case lq_export_chat_link: tgl_do_export_chat_link (TLS, lua_ptr[p + 1].peer_id, lua_str_cb, lua_ptr[p].ptr); p += 2; break; case lq_send_location: tgl_do_send_location (TLS, lua_ptr[p + 1].peer_id, lua_ptr[p + 2].dnum, lua_ptr[p + 3].dnum, 0, lua_msg_cb, lua_ptr[p].ptr); p += 4; break; case lq_channel_invite_user: tgl_do_channel_invite_user (TLS, lua_ptr[p + 1].peer_id, lua_ptr[p + 2].peer_id, lua_empty_cb, lua_ptr[p].ptr); p += 3; break; case lq_channel_kick_user: tgl_do_channel_kick_user (TLS, lua_ptr[p + 1].peer_id, lua_ptr[p + 2].peer_id, lua_empty_cb, lua_ptr[p].ptr); p += 3; break; case lq_channel_get_admins: tgl_do_channel_get_members (TLS, lua_ptr[p + 1].peer_id, 100, 0, 1, lua_contact_list_cb, lua_ptr[p].ptr); p += 2; break; case lq_channel_get_users: tgl_do_channel_get_members (TLS, lua_ptr[p + 1].peer_id, 100, 0, 0, lua_contact_list_cb, lua_ptr[p].ptr); p += 2; break; /* lq_delete_msg, lq_restore_msg, case 0: tgl_do_send_message (((tgl_peer_t *)lua_ptr[p])->id, lua_ptr[p + 1], strlen (lua_ptr[p + 1]), 0, 0); free (lua_ptr[p + 1]); p += 2; break; case 1: tgl_do_forward_message (((tgl_peer_t *)lua_ptr[p])->id, (long)lua_ptr[p + 1], 0, 0); p += 2; break; case 2: tgl_do_mark_read (((tgl_peer_t *)lua_ptr[p])->id, 0, 0); p += 1; break;*/ default: assert (0); } while (q < p) { if (lua_ptr[q].flags & 1) { tfree_str (lua_ptr[q].str); } q ++; } } pos = 0; } enum lua_function_param { lfp_none, lfp_peer, lfp_chat, lfp_channel, lfp_user, lfp_secret_chat, lfp_string, lfp_number, lfp_positive_number, lfp_nonnegative_number, lfp_msg, lfp_double }; struct lua_function { char *name; enum lua_query_type type; enum lua_function_param params[10]; }; struct lua_function functions[] = { {"get_contact_list", lq_contact_list, { lfp_none }}, {"get_dialog_list", lq_dialog_list, { lfp_none }}, {"rename_chat", lq_rename_chat, { lfp_chat, lfp_string, lfp_none }}, {"send_msg", lq_msg, { lfp_peer, lfp_string, lfp_none }}, {"post_msg", lq_msg_channel, { lfp_channel, lfp_string, lfp_none }}, {"send_typing", lq_send_typing, { lfp_peer, lfp_none }}, {"send_typing_abort", lq_send_typing_abort, { lfp_peer, lfp_none }}, {"send_photo", lq_send_photo, { lfp_peer, lfp_string, lfp_none }}, {"send_video", lq_send_video, { lfp_peer, lfp_string, lfp_none }}, {"send_audio", lq_send_audio, { lfp_peer, lfp_string, lfp_none }}, {"send_document", lq_send_document, { lfp_peer, lfp_string, lfp_none }}, {"send_file", lq_send_file, { lfp_peer, lfp_string, lfp_none }}, {"send_text", lq_send_text, { lfp_peer, lfp_string, lfp_none }}, {"chat_set_photo", lq_chat_set_photo, { lfp_chat, lfp_string, lfp_none }}, {"load_photo", lq_load_photo, { lfp_msg, lfp_none }}, {"load_video", lq_load_video, { lfp_msg, lfp_none }}, {"load_video_thumb", lq_load_video_thumb, { lfp_msg, lfp_none }}, {"load_audio", lq_load_audio, { lfp_msg, lfp_none }}, {"load_document", lq_load_document, { lfp_msg, lfp_none }}, {"load_document_thumb", lq_load_document_thumb, { lfp_msg, lfp_none }}, {"reply_msg", lq_reply, { lfp_msg, lfp_string, lfp_none }}, {"fwd_msg", lq_fwd, { lfp_peer, lfp_msg, lfp_none }}, {"fwd_media", lq_fwd_media, { lfp_peer, lfp_msg, lfp_none }}, {"chat_info", lq_chat_info, { lfp_chat, lfp_none }}, {"channel_info", lq_channel_info, { lfp_channel, lfp_none }}, {"user_info", lq_user_info, { lfp_user, lfp_none }}, {"get_history", lq_history, { lfp_peer, lfp_nonnegative_number, lfp_none }}, {"chat_add_user", lq_chat_add_user, { lfp_chat, lfp_user, lfp_none }}, {"chat_del_user", lq_chat_del_user, { lfp_chat, lfp_user, lfp_none }}, {"add_contact", lq_add_contact, { lfp_string, lfp_string, lfp_string, lfp_none }}, {"del_contact", lq_del_contact, { lfp_user, lfp_none }}, {"rename_contact", lq_rename_contact, { lfp_string, lfp_string, lfp_string, lfp_none }}, {"msg_search", lq_search, { lfp_peer, lfp_string, lfp_none }}, {"msg_global_search", lq_global_search, { lfp_string, lfp_none }}, {"mark_read", lq_mark_read, { lfp_peer, lfp_none }}, {"set_profile_photo", lq_set_profile_photo, { lfp_string, lfp_none }}, {"set_profile_name", lq_set_profile_name, { lfp_string, lfp_none }}, {"create_secret_chat", lq_create_secret_chat, { lfp_user, lfp_none }}, {"create_group_chat", lq_create_group_chat, { lfp_user, lfp_string, lfp_none }}, {"delete_msg", lq_delete_msg, { lfp_msg, lfp_none }}, {"restore_msg", lq_restore_msg, { lfp_positive_number, lfp_none }}, {"accept_secret_chat", lq_accept_secret_chat, { lfp_secret_chat, lfp_none }}, {"send_contact", lq_send_contact, { lfp_peer, lfp_string, lfp_string, lfp_string, lfp_none }}, {"status_online", lq_status_online, { lfp_none }}, {"status_offline", lq_status_offline, { lfp_none }}, {"send_location", lq_send_location, { lfp_peer, lfp_double, lfp_double, lfp_none }}, {"ext_function", lq_extf, { lfp_string, lfp_none }}, {"import_chat_link", lq_import_chat_link, { lfp_string, lfp_none }}, {"export_chat_link", lq_export_chat_link, { lfp_chat, lfp_none }}, {"channel_invite_user", lq_channel_invite_user, { lfp_channel, lfp_user, lfp_none }}, {"channel_kick_user", lq_channel_kick_user, { lfp_channel, lfp_user, lfp_none }}, {"channel_get_admins", lq_channel_get_admins, { lfp_channel, lfp_none }}, {"channel_get_users", lq_channel_get_users, { lfp_channel, lfp_none }}, { 0, 0, { lfp_none}} }; static int parse_lua_function (lua_State *L, struct lua_function *F) { int p = 0; while (F->params[p] != lfp_none) { p ++; } if (lua_gettop (L) != p + 2) { lua_pushboolean (L, 0); return 1; } int a1 = luaL_ref (L, LUA_REGISTRYINDEX); int a2 = luaL_ref (L, LUA_REGISTRYINDEX); struct lua_query_extra *e = malloc (sizeof (*e)); assert (e); e->func = a2; e->param = a1; assert (pos + 3 + p < MAX_LUA_COMMANDS); lua_ptr[pos ++].num = (p + 1); lua_ptr[pos ++].num = F->type; lua_ptr[pos ++].ptr = e; int sp = p; int ok = 1; int cc = 0; while (p > 0) { p --; cc ++; const char *s; long long num; double dval; tgl_peer_id_t peer_id; lua_ptr[pos + p].flags = 0; switch (F->params[p]) { case lfp_none: assert (0); break; case lfp_peer: case lfp_user: case lfp_chat: case lfp_channel: case lfp_secret_chat: s = lua_tostring (L, -cc); if (!s) { ok = 0; break; } if (F->params[p] == lfp_user) { peer_id = parse_input_peer_id (s, strlen (s), TGL_PEER_USER); } else if (F->params[p] == lfp_chat) { peer_id = parse_input_peer_id (s, strlen (s), TGL_PEER_CHAT); } else if (F->params[p] == lfp_secret_chat) { peer_id = parse_input_peer_id (s, strlen (s), TGL_PEER_ENCR_CHAT); } else if (F->params[p] == lfp_channel) { peer_id = parse_input_peer_id (s, strlen (s), TGL_PEER_CHANNEL); } else { peer_id = parse_input_peer_id (s, strlen (s), 0); } if (!peer_id.peer_type) { ok = 0; break; } lua_ptr[pos + p].peer_id = peer_id; break; case lfp_string: s = lua_tostring (L, -cc); if (!s) { ok = 0; break; } lua_ptr[pos + p].str = (void *)s; lua_ptr[pos + p].flags |= 1; break; case lfp_number: num = lua_tonumber (L, -cc); lua_ptr[pos + p].num = num; break; case lfp_double: dval = lua_tonumber (L, -cc); lua_ptr[pos + p].dnum = dval; break; case lfp_msg: s = lua_tostring (L, -cc); if (!s) { ok = 0; break; } lua_ptr[pos + p].msg_id = parse_input_msg_id (s, strlen (s)); if (lua_ptr[pos + p].msg_id.peer_type == 0) { ok = 0; break; } break; case lfp_positive_number: num = lua_tonumber (L, -cc); if (num <= 0) { ok = 0; break; } lua_ptr[pos + p].num = num; break; case lfp_nonnegative_number: num = lua_tonumber (L, -cc); if (num < 0) { ok = 0; break; } lua_ptr[pos + p].num = num; break; default: assert (0); } } if (!ok) { luaL_unref (luaState, LUA_REGISTRYINDEX, a1); luaL_unref (luaState, LUA_REGISTRYINDEX, a2); free (e); pos -= 3; lua_pushboolean (L, 0); return 1; } for (p = 0; p < sp; p++) { if (F->params[p] == lfp_string) { lua_ptr[pos + p].str = tstrdup (lua_ptr[pos + p].str); } } pos += p; lua_pushboolean (L, 1); return 1; } static void lua_postpone_alarm (evutil_socket_t fd, short what, void *arg) { int *t = arg; lua_settop (luaState, 0); //lua_checkstack (luaState, 20); my_lua_checkstack (luaState, 20); lua_rawgeti (luaState, LUA_REGISTRYINDEX, t[1]); lua_rawgeti (luaState, LUA_REGISTRYINDEX, t[0]); assert (lua_gettop (luaState) == 2); int r = ps_lua_pcall (luaState, 1, 0, 0); luaL_unref (luaState, LUA_REGISTRYINDEX, t[0]); luaL_unref (luaState, LUA_REGISTRYINDEX, t[1]); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } } static int postpone_from_lua (lua_State *L) { int n = lua_gettop (L); if (n != 3) { lua_pushboolean (L, 0); return 1; } double timeout = lua_tonumber (L, -1); if (timeout < 0) { lua_pushboolean (L, 0); return 1; } lua_pop (L, 1); int a1 = luaL_ref (L, LUA_REGISTRYINDEX); int a2 = luaL_ref (L, LUA_REGISTRYINDEX); int *t = malloc (16); assert (t); struct event *ev = evtimer_new (TLS->ev_base, lua_postpone_alarm, t); t[0] = a1; t[1] = a2; *(void **)(t + 2) = ev; struct timeval ts= { .tv_sec = (long)timeout, .tv_usec = (timeout - ((long)timeout)) * 1000000 }; event_add (ev, &ts); lua_pushboolean (L, 1); return 1; } extern int safe_quit; static int safe_quit_from_lua (lua_State *L) { int n = lua_gettop (L); if (n != 0) { lua_pushboolean (L, 0); return 1; } safe_quit = 1; lua_pushboolean (L, 1); return 1; } static int universal_from_lua (lua_State *L) { const char *s = lua_tostring(L, lua_upvalueindex(1)); if (!s) { lua_pushboolean (L, 0); return 1; } int i = 0; while (functions[i].name) { if (!strcmp (functions[i].name, s)) { return parse_lua_function (L, &functions[i]); } i ++; } lua_pushboolean (L, 0); return 1; } static void my_lua_register (lua_State *L, const char *name, lua_CFunction f) { lua_pushstring(L, name); lua_pushcclosure(L, f, 1); lua_setglobal(L, name); } enum command_argument { ca_none, ca_user, ca_chat, ca_secret_chat, ca_channel, ca_peer, ca_file_name, ca_file_name_end, ca_period, ca_number, ca_double, ca_string_end, ca_string, ca_modifier, ca_command, ca_extf, ca_optional = 256 }; struct arg { int flags; struct { tgl_peer_t *P; struct tgl_message *M; char *str; long long num; double dval; }; }; struct in_ev; struct command { char *name; enum command_argument args[10]; void (*fun)(struct command *command, int arg_num, struct arg args[], struct in_ev *ev); char *desc; void *arg; }; #define NOT_FOUND (int)0x80000000 static void do_interface_from_lua (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) { lua_settop (luaState, 0); my_lua_checkstack (luaState, 20); struct lua_query_extra *e = command->arg; lua_rawgeti (luaState, LUA_REGISTRYINDEX, e->func); lua_rawgeti (luaState, LUA_REGISTRYINDEX, e->param); int i; for (i = 0; i < arg_num; i ++) { int j = i; if (j > 9) { j = 9; } while (j >= 0) { if (command->args[j] == ca_period) { j --; continue; } if (command->args[j] == ca_none) { j --; continue; } break; } assert (j >= 0); switch (command->args[j] & 0xff) { case ca_none: case ca_period: assert (0); break; case ca_user: case ca_chat: case ca_secret_chat: case ca_peer: if (args[i].P) { push_peer (args[i].P->id, args[i].P); } else { lua_pushnil (luaState); } break; case ca_file_name: case ca_file_name_end: case ca_string_end: case ca_string: if (args[i].str) { lua_pushstring (luaState, args[i].str); } else { lua_pushnil (luaState); } break; case ca_number: if (args[i].num != NOT_FOUND) { lua_pushnumber (luaState, args[i].num); } else { lua_pushnil (luaState); } break; case ca_double: if (args[i].dval != NOT_FOUND) { lua_pushnumber (luaState, args[i].dval); } else { lua_pushnil (luaState); } break; } } int r = ps_lua_pcall (luaState, 1 + arg_num, 0, 0); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); } } void register_new_command (struct command *cmd); static int register_interface_from_lua (lua_State *L) { int n = lua_gettop (L); if (n <= 4 || n >= 13) { lua_pushboolean (L, 0); return 1; } static struct command cmd; memset (&cmd, 0, sizeof (struct command)); int i; for (i = 0; i < n - 4; i++) { const char *s = lua_tostring (L, -1); lua_pop (L, 1); if (!s || !strlen (s)) { lua_pushboolean (L, 0); return 1; } int len = strlen (s); int optional = 0; if (len > 9 && !strcmp (s + len - 9, " optional")) { optional = ca_optional; len -= 9; } int ok = 0; #define VARIANT(name) \ if (len == strlen (#name) && !strncmp (s, #name, len)) {\ cmd.args[n - 5 - i] = ca_ ## name | optional; \ ok = 1; \ } VARIANT (user) VARIANT (chat) VARIANT (secret_chat) VARIANT (peer) VARIANT (file_name) VARIANT (file_name_end) VARIANT (period) VARIANT (number) VARIANT (double) VARIANT (string_end) VARIANT (string) #undef VARTIANT if (!ok) { lua_pushboolean (L, 0); return 1; } } const char *s = lua_tostring (L, -1); lua_pop (L, 1); cmd.desc = s ? tstrdup (s) : tstrdup ("no help provided"); int a1 = luaL_ref (L, LUA_REGISTRYINDEX); int a2 = luaL_ref (L, LUA_REGISTRYINDEX); struct lua_query_extra *e = malloc (sizeof (*e)); assert (e); e->func = a2; e->param = a1; cmd.arg = e; cmd.fun = do_interface_from_lua; s = lua_tostring (L, -1); lua_pop (L, 1); cmd.name = tstrdup (s ? s : "none"); register_new_command (&cmd); lua_pushboolean (L, 1); return 1; } void lua_init (const char *file) { if (!file) { return; } have_file = 1; luaState = luaL_newstate (); luaL_openlibs (luaState); int i = 0; while (functions[i].name) { my_lua_register (luaState, functions[i].name, universal_from_lua); i ++; } lua_register (luaState, "postpone", postpone_from_lua); lua_register (luaState, "safe_quit", safe_quit_from_lua); lua_register (luaState, "register_interface_function", register_interface_from_lua); print_start (); int r = luaL_dofile (luaState, file); print_end (); if (r) { logprintf ("lua: %s\n", lua_tostring (luaState, -1)); exit (1); } } #endif ================================================ FILE: lua-tg.h ================================================ /* This file is part of telegram-cli. Telegram-cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Telegram-cli 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 telegram-cli. If not, see . Copyright Vitaly Valtman 2013-2015 */ #ifndef __LUA_TG_H__ #define __LUA_TG_H__ #include #include void lua_init (const char *file); void lua_new_msg (struct tgl_message *M); void lua_our_id (tgl_peer_id_t id); void lua_secret_chat_update (struct tgl_secret_chat *U, unsigned flags); void lua_user_update (struct tgl_user *U, unsigned flags); void lua_chat_update (struct tgl_chat *C, unsigned flags); void lua_binlog_end (void); void lua_diff_end (void); void lua_do_all (void); #endif ================================================ FILE: m4-ax_gcc_builtin.m4 ================================================ # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_gcc_builtin.html # =========================================================================== # # SYNOPSIS # # AX_GCC_BUILTIN(BUILTIN) # # DESCRIPTION # # This macro checks if the compiler supports one of GCC's built-in # functions; many other compilers also provide those same built-ins. # # The BUILTIN parameter is the name of the built-in function. # # If BUILTIN is supported define HAVE_. Keep in mind that since # builtins usually start with two underscores they will be copied over # into the HAVE_ definition (e.g. HAVE___BUILTIN_EXPECT for # __builtin_expect()). # # The macro caches its result in the ax_cv_have_ variable (e.g. # ax_cv_have___builtin_expect). # # The macro currently supports the following built-in functions: # # __builtin_assume_aligned # __builtin_bswap32 # __builtin_bswap64 # __builtin_choose_expr # __builtin___clear_cache # __builtin_clrsb # __builtin_clrsbl # __builtin_clrsbll # __builtin_clz # __builtin_clzl # __builtin_clzll # __builtin_complex # __builtin_constant_p # __builtin_ctz # __builtin_ctzl # __builtin_ctzll # __builtin_expect # __builtin_ffs # __builtin_ffsl # __builtin_ffsll # __builtin_fpclassify # __builtin_huge_val # __builtin_huge_valf # __builtin_huge_vall # __builtin_inf # __builtin_infd128 # __builtin_infd32 # __builtin_infd64 # __builtin_inff # __builtin_infl # __builtin_isinf_sign # __builtin_nan # __builtin_nand128 # __builtin_nand32 # __builtin_nand64 # __builtin_nanf # __builtin_nanl # __builtin_nans # __builtin_nansf # __builtin_nansl # __builtin_object_size # __builtin_parity # __builtin_parityl # __builtin_parityll # __builtin_popcount # __builtin_popcountl # __builtin_popcountll # __builtin_powi # __builtin_powif # __builtin_powil # __builtin_prefetch # __builtin_trap # __builtin_types_compatible_p # __builtin_unreachable # # Unsuppored built-ins will be tested with an empty parameter set and the # result of the check might be wrong or meaningless so use with care. # # LICENSE # # Copyright (c) 2013 Gabriele Svelto # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 2 AC_DEFUN([AX_GCC_BUILTIN], [ AS_VAR_PUSHDEF([ac_var], [ax_cv_have_$1]) AC_CACHE_CHECK([for $1], [ac_var], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([], [ m4_case([$1], [__builtin_assume_aligned], [$1("", 0)], [__builtin_bswap32], [$1(0)], [__builtin_bswap64], [$1(0)], [__builtin_choose_expr], [$1(0, 0, 0)], [__builtin___clear_cache], [$1("", "")], [__builtin_clrsb], [$1(0)], [__builtin_clrsbl], [$1(0)], [__builtin_clrsbll], [$1(0)], [__builtin_clz], [$1(0)], [__builtin_clzl], [$1(0)], [__builtin_clzll], [$1(0)], [__builtin_complex], [$1(0.0, 0.0)], [__builtin_constant_p], [$1(0)], [__builtin_ctz], [$1(0)], [__builtin_ctzl], [$1(0)], [__builtin_ctzll], [$1(0)], [__builtin_expect], [$1(0, 0)], [__builtin_ffs], [$1(0)], [__builtin_ffsl], [$1(0)], [__builtin_ffsll], [$1(0)], [__builtin_fpclassify], [$1(0, 1, 2, 3, 4, 0.0)], [__builtin_huge_val], [$1()], [__builtin_huge_valf], [$1()], [__builtin_huge_vall], [$1()], [__builtin_inf], [$1()], [__builtin_infd128], [$1()], [__builtin_infd32], [$1()], [__builtin_infd64], [$1()], [__builtin_inff], [$1()], [__builtin_infl], [$1()], [__builtin_isinf_sign], [$1(0.0)], [__builtin_nan], [$1("")], [__builtin_nand128], [$1("")], [__builtin_nand32], [$1("")], [__builtin_nand64], [$1("")], [__builtin_nanf], [$1("")], [__builtin_nanl], [$1("")], [__builtin_nans], [$1("")], [__builtin_nansf], [$1("")], [__builtin_nansl], [$1("")], [__builtin_object_size], [$1("", 0)], [__builtin_parity], [$1(0)], [__builtin_parityl], [$1(0)], [__builtin_parityll], [$1(0)], [__builtin_popcount], [$1(0)], [__builtin_popcountl], [$1(0)], [__builtin_popcountll], [$1(0)], [__builtin_powi], [$1(0, 0)], [__builtin_powif], [$1(0, 0)], [__builtin_powil], [$1(0, 0)], [__builtin_prefetch], [$1("")], [__builtin_trap], [$1()], [__builtin_types_compatible_p], [$1(int, int)], [__builtin_unreachable], [$1()], [m4_warn([syntax], [Unsupported built-in $1, the test may fail]) $1()] ) ])], [AS_VAR_SET([ac_var], [yes])], [AS_VAR_SET([ac_var], [no])]) ]) AS_IF([test yes = AS_VAR_GET([ac_var])], [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1), 1, [Define to 1 if the system has the `$1' built-in function])], []) AS_VAR_POPDEF([ac_var]) ]) ================================================ FILE: m4_ax_check_openssl.m4 ================================================ # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_check_openssl.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]]) # # DESCRIPTION # # Look for OpenSSL in a number of default spots, or in a user-selected # spot (via --with-openssl). Sets # # OPENSSL_INCLUDES to the include directives required # OPENSSL_LIBS to the -l directives required # OPENSSL_LDFLAGS to the -L or -R flags required # # and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately # # This macro sets OPENSSL_INCLUDES such that source files should use the # openssl/ directory in include directives: # # #include # # LICENSE # # Copyright (c) 2009,2010 Zmanda Inc. # Copyright (c) 2009,2010 Dustin J. Mitchell # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 8 AU_ALIAS([CHECK_SSL], [AX_CHECK_OPENSSL]) AC_DEFUN([AX_CHECK_OPENSSL], [ found=false AC_ARG_WITH([openssl], [AS_HELP_STRING([--with-openssl=DIR], [root of the OpenSSL directory])], [ case "$withval" in "" | y | ye | yes | n | no) AC_MSG_ERROR([Invalid --with-openssl value]) ;; *) ssldirs="$withval" ;; esac ], [ # if pkg-config is installed and openssl has installed a .pc file, # then use that information and don't search ssldirs AC_PATH_PROG([PKG_CONFIG], [pkg-config]) if test x"$PKG_CONFIG" != x""; then OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null` if test $? = 0; then OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null` OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null` found=true fi fi # no such luck; use some default ssldirs if ! $found; then ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" fi ] ) # note that we #include , so the OpenSSL headers have to be in # an 'openssl' subdirectory if ! $found; then OPENSSL_INCLUDES= for ssldir in $ssldirs; do AC_MSG_CHECKING([for openssl/ssl.h in $ssldir]) if test -f "$ssldir/include/openssl/ssl.h"; then OPENSSL_INCLUDES="-I$ssldir/include" OPENSSL_LDFLAGS="-L$ssldir/lib" OPENSSL_LIBS="-lssl -lcrypto" found=true AC_MSG_RESULT([yes]) break else AC_MSG_RESULT([no]) fi done # if the file wasn't found, well, go ahead and try the link anyway -- maybe # it will just work! fi # try the preprocessor and linker with our new flags, # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS AC_MSG_CHECKING([whether compiling and linking against OpenSSL works]) echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \ "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&AS_MESSAGE_LOG_FD save_LIBS="$LIBS" save_LDFLAGS="$LDFLAGS" save_CPPFLAGS="$CPPFLAGS" LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" LIBS="$OPENSSL_LIBS $LIBS" CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS" AC_LINK_IFELSE( [AC_LANG_PROGRAM([#include ], [SSL_new(NULL)])], [ AC_MSG_RESULT([yes]) $1 ], [ AC_MSG_RESULT([no]) $2 ]) CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" AC_SUBST([OPENSSL_INCLUDES]) AC_SUBST([OPENSSL_LIBS]) AC_SUBST([OPENSSL_LDFLAGS]) ]) ================================================ FILE: m4_ax_check_zlib.m4 ================================================ # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_check_zlib.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_ZLIB([action-if-found], [action-if-not-found]) # # DESCRIPTION # # This macro searches for an installed zlib library. If nothing was # specified when calling configure, it searches first in /usr/local and # then in /usr, /opt/local and /sw. If the --with-zlib=DIR is specified, # it will try to find it in DIR/include/zlib.h and DIR/lib/libz.a. If # --without-zlib is specified, the library is not searched at all. # # If either the header file (zlib.h) or the library (libz) is not found, # shell commands 'action-if-not-found' is run. If 'action-if-not-found' is # not specified, the configuration exits on error, asking for a valid zlib # installation directory or --without-zlib. # # If both header file and library are found, shell commands # 'action-if-found' is run. If 'action-if-found' is not specified, the # default action appends '-I${ZLIB_HOME}/include' to CPFLAGS, appends # '-L$ZLIB_HOME}/lib' to LDFLAGS, prepends '-lz' to LIBS, and calls # AC_DEFINE(HAVE_LIBZ). You should use autoheader to include a definition # for this symbol in a config.h file. Sample usage in a C/C++ source is as # follows: # # #ifdef HAVE_LIBZ # #include # #endif /* HAVE_LIBZ */ # # LICENSE # # Copyright (c) 2008 Loic Dachary # Copyright (c) 2010 Bastien Chevreux # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # 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 14 AU_ALIAS([CHECK_ZLIB], [AX_CHECK_ZLIB]) AC_DEFUN([AX_CHECK_ZLIB], # # Handle user hints # [AC_MSG_CHECKING(if zlib is wanted) zlib_places="/usr/local /usr /opt/local /sw" AC_ARG_WITH([zlib], [ --with-zlib=DIR root directory path of zlib installation @<:@defaults to /usr/local or /usr if not found in /usr/local@:>@ --without-zlib to disable zlib usage completely], [if test "$withval" != no ; then AC_MSG_RESULT(yes) if test -d "$withval" then zlib_places="$withval $zlib_places" else AC_MSG_WARN([Sorry, $withval does not exist, checking usual places]) fi else zlib_places= AC_MSG_RESULT(no) fi], [AC_MSG_RESULT(yes)]) # # Locate zlib, if wanted # if test -n "${zlib_places}" then # check the user supplied or any other more or less 'standard' place: # Most UNIX systems : /usr/local and /usr # MacPorts / Fink on OSX : /opt/local respectively /sw for ZLIB_HOME in ${zlib_places} ; do if test -f "${ZLIB_HOME}/include/zlib.h"; then break; fi ZLIB_HOME="" done ZLIB_OLD_LDFLAGS=$LDFLAGS ZLIB_OLD_CPPFLAGS=$CPPFLAGS if test -n "${ZLIB_HOME}"; then LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" fi AC_LANG_SAVE AC_LANG_C AC_CHECK_LIB([z], [inflateEnd], [zlib_cv_libz=yes], [zlib_cv_libz=no]) AC_CHECK_HEADER([zlib.h], [zlib_cv_zlib_h=yes], [zlib_cv_zlib_h=no]) AC_LANG_RESTORE if test "$zlib_cv_libz" = "yes" && test "$zlib_cv_zlib_h" = "yes" then # # If both library and header were found, action-if-found # m4_ifblank([$1],[ CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" LIBS="-lz $LIBS" AC_DEFINE([HAVE_LIBZ], [1], [Define to 1 if you have `z' library (-lz)]) ],[ # Restore variables LDFLAGS="$ZLIB_OLD_LDFLAGS" CPPFLAGS="$ZLIB_OLD_CPPFLAGS" $1 ]) else # # If either header or library was not found, action-if-not-found # m4_default([$2],[ AC_MSG_ERROR([either specify a valid zlib installation with --with-zlib=DIR or disable zlib usage with --without-zlib]) ]) fi fi ]) ================================================ FILE: main.c ================================================ /* This file is part of telegram-cli. Telegram-cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Telegram-cli 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 telegram-cli. If not, see . Copyright Vitaly Valtman 2013-2015 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef USE_PYTHON # include "python-tg.h" #endif #include #include #include #include #include #include #include #include #ifdef __FreeBSD__ #include #include #endif #include #include #include #include #include #include #ifdef HAVE_EXECINFO_H #include #endif #include #ifdef HAVE_LIBCONFIG #include #endif #include #include #include #include "telegram.h" #include "loop.h" #include "interface.h" #include #include #include #ifdef USE_LUA # include "lua-tg.h" #endif #include #define PROGNAME "telegram-cli" #define VERSION "0.07" #define CONFIG_DIRECTORY "." PROG_NAME #define CONFIG_FILE "config" #define AUTH_KEY_FILE "auth" #define STATE_FILE "state" #define SECRET_CHAT_FILE "secret" #define DOWNLOADS_DIRECTORY "downloads" #define BINLOG_FILE "binlog" #define CONFIG_DIRECTORY_MODE 0700 #define DEFAULT_CONFIG_CONTENTS \ "# This is an empty config file\n" \ "# Feel free to put something here\n" int bot_mode; int verbosity; int msg_num_mode; char *default_username; char *config_filename; char *prefix; char *auth_file_name; char *state_file_name; char *secret_chat_file_name; char *downloads_directory; char *config_directory; char *binlog_file_name; char *lua_file; char *python_file; int binlog_enabled; extern int log_level; int sync_from_start; int allow_weak_random; int disable_colors; int readline_disabled; int disable_output; int reset_authorization; int port; int use_ids; int ipv6_enabled; char *start_command; int disable_link_preview; int enable_json; int alert_sound; int exit_code; int permanent_msg_id_mode; int permanent_peer_id_mode; char *home_directory; struct tgl_state *TLS; void set_default_username (const char *s) { if (default_username) { tfree_str (default_username); } default_username = tstrdup (s); } /* {{{ TERMINAL */ static struct termios term_in, term_out; static int term_set_in; static int term_set_out; void get_terminal_attributes (void) { if (tcgetattr (STDIN_FILENO, &term_in) < 0) { } else { term_set_in = 1; } if (tcgetattr (STDOUT_FILENO, &term_out) < 0) { } else { term_set_out = 1; } } void set_terminal_attributes (void) { if (term_set_in) { if (tcsetattr (STDIN_FILENO, 0, &term_in) < 0) { perror ("tcsetattr()"); } } if (term_set_out) { if (tcsetattr (STDOUT_FILENO, 0, &term_out) < 0) { perror ("tcsetattr()"); } } } /* }}} */ int str_empty (char *str) { return ((str == NULL) || (strlen(str) < 1)); } char *get_home_directory (void) { if (home_directory) { return home_directory; } home_directory = getenv("TELEGRAM_HOME"); if (!str_empty (home_directory)) { return home_directory = tstrdup (home_directory); } home_directory = getenv("HOME"); if (!str_empty (home_directory)) { return home_directory = tstrdup (home_directory); } struct passwd *current_passwd; uid_t user_id; setpwent (); user_id = getuid (); while ((current_passwd = getpwent ())) { if (current_passwd->pw_uid == user_id) { home_directory = tstrdup (current_passwd->pw_dir); break; } } endpwent (); if (str_empty (home_directory)) { home_directory = tstrdup ("."); } return home_directory; } char *get_config_directory (void) { char *config_directory; config_directory = getenv("TELEGRAM_CONFIG_DIR"); if (!str_empty (config_directory)) { return tstrdup (config_directory); } // XDG: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html config_directory = getenv("XDG_CONFIG_HOME"); if (!str_empty (config_directory)) { tasprintf (&config_directory, "%s/" PROG_NAME, config_directory); // :TODO: someone check whether it could be required to pass tasprintf // a tstrdup()ed config_directory instead; works for me without. // should work b/c this scope's lifespan encompasses tasprintf() return config_directory; } tasprintf (&config_directory, "%s/" CONFIG_DIRECTORY, get_home_directory ()); return config_directory; } char *get_config_filename (void) { return config_filename; } char *get_auth_key_filename (void) { return auth_file_name; } char *get_state_filename (void) { return state_file_name; } char *get_secret_chat_filename (void) { return secret_chat_file_name; } char *get_downloads_directory (void) { return downloads_directory; } char *get_binlog_file_name (void) { return binlog_file_name; } char *make_full_path (char *s) { if (*s != '/') { char *t = s; tasprintf (&s, "%s/%s", get_home_directory (), s); tfree_str (t); } return s; } void check_type_sizes (void) { if (sizeof (int) != 4u) { logprintf ("sizeof (int) isn't equal 4.\n"); exit (1); } if (sizeof (char) != 1u) { logprintf ("sizeof (char) isn't equal 1.\n"); exit (1); } } void running_for_first_time (void) { check_type_sizes (); if (!str_empty (config_filename)) { return; // Do not create custom config file } if (str_empty (config_directory)) { config_directory = get_config_directory (); } tasprintf (&config_filename, "%s/%s", config_directory, CONFIG_FILE); config_filename = make_full_path (config_filename); if (!disable_output) { printf ("I: config dir=[%s]\n", config_directory); } // printf ("I: config file=[%s]\n", config_filename); int config_file_fd; //char *config_directory = get_config_directory (); //char *downloads_directory = get_downloads_directory (); if (!mkdir (config_directory, CONFIG_DIRECTORY_MODE)) { if (!disable_output) { printf ("[%s] created\n", config_directory); } } tfree_str (config_directory); config_directory = NULL; // see if config file is there if (access (config_filename, R_OK) != 0) { // config file missing, so touch it config_file_fd = open (config_filename, O_CREAT | O_RDWR, 0600); if (config_file_fd == -1) { perror ("open[config_file]"); printf ("I: config_file=[%s]\n", config_filename); exit (EXIT_FAILURE); } if (write (config_file_fd, DEFAULT_CONFIG_CONTENTS, strlen (DEFAULT_CONFIG_CONTENTS)) <= 0) { perror ("write[config_file]"); exit (EXIT_FAILURE); } close (config_file_fd); } } #ifdef HAVE_LIBCONFIG void parse_config_val (config_t *conf, char **s, char *param_name, const char *default_name, const char *path) { static char buf[1000]; int l = 0; if (prefix) { l = strlen (prefix); memcpy (buf, prefix, l); buf[l ++] = '.'; } *s = 0; const char *r = 0; strcpy (buf + l, param_name); config_lookup_string (conf, buf, &r); if (r) { if (path && *r != '/') { tasprintf (s, "%s/%s", path, r); } else { *s = tstrdup (r); } } else { if (path && default_name) { tasprintf (s, "%s/%s", path, default_name); } else { *s = default_name ? tstrdup (default_name) : 0; } } } void parse_config (void) { //config_filename = make_full_path (config_filename); config_t conf; config_init (&conf); if (config_read_file (&conf, config_filename) != CONFIG_TRUE) { fprintf (stderr, "Can not read config '%s': error '%s' on the line %d\n", config_filename, config_error_text (&conf), config_error_line (&conf)); exit (2); } if (!prefix) { config_lookup_string (&conf, "default_profile", (void *)&prefix); } static char buf[1000]; int l = 0; if (prefix) { l = strlen (prefix); memcpy (buf, prefix, l); buf[l ++] = '.'; } int test_mode = 0; strcpy (buf + l, "test"); config_lookup_bool (&conf, buf, &test_mode); if (test_mode) { tgl_set_test_mode (TLS); } strcpy (buf + l, "log_level"); long long t = log_level; config_lookup_int (&conf, buf, (void *)&t); log_level = t; if (!msg_num_mode) { strcpy (buf + l, "msg_num"); config_lookup_bool (&conf, buf, &msg_num_mode); } parse_config_val (&conf, &config_directory, "config_directory", CONFIG_DIRECTORY, 0); config_directory = make_full_path (config_directory); parse_config_val (&conf, &auth_file_name, "auth_file", AUTH_KEY_FILE, config_directory); parse_config_val (&conf, &downloads_directory, "downloads", DOWNLOADS_DIRECTORY, config_directory); if (!lua_file) { parse_config_val (&conf, &lua_file, "lua_script", 0, config_directory); } if (!python_file) { parse_config_val (&conf, &python_file, "python_script", 0, config_directory); } #if 0 strcpy (buf + l, "binlog_enabled"); config_lookup_bool (&conf, buf, &binlog_enabled); #else binlog_enabled = 0; #endif int pfs_enabled = 0; strcpy (buf + l, "pfs_enabled"); config_lookup_bool (&conf, buf, &pfs_enabled); if (pfs_enabled) { tgl_enable_pfs (TLS); } if (binlog_enabled) { parse_config_val (&conf, &binlog_file_name, "binlog", BINLOG_FILE, config_directory); tgl_set_binlog_mode (TLS, 1); tgl_set_binlog_path (TLS, binlog_file_name); } else { tgl_set_binlog_mode (TLS, 0); parse_config_val (&conf, &state_file_name, "state_file", STATE_FILE, config_directory); parse_config_val (&conf, &secret_chat_file_name, "secret", SECRET_CHAT_FILE, config_directory); //tgl_set_auth_file_path (auth_file_name); } tgl_set_download_directory (TLS, downloads_directory); if (!mkdir (config_directory, CONFIG_DIRECTORY_MODE)) { if (!disable_output) { printf ("[%s] created\n", config_directory); } } if (!mkdir (downloads_directory, CONFIG_DIRECTORY_MODE)) { if (!disable_output) { printf ("[%s] created\n", downloads_directory); } } tfree_str (config_directory); config_directory = NULL; config_destroy (&conf); } #else void parse_config (void) { if (!disable_output) { printf ("libconfig not enabled\n"); } tasprintf (&downloads_directory, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, DOWNLOADS_DIRECTORY); if (binlog_enabled) { tasprintf (&binlog_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, BINLOG_FILE); tgl_set_binlog_mode (TLS, 1); tgl_set_binlog_path (TLS, binlog_file_name); } else { tgl_set_binlog_mode (TLS, 0); //tgl_set_auth_file_path (auth_file_name; tasprintf (&auth_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, AUTH_KEY_FILE); tasprintf (&state_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, STATE_FILE); tasprintf (&secret_chat_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, SECRET_CHAT_FILE); } tgl_set_download_directory (TLS, downloads_directory); if (!mkdir (downloads_directory, CONFIG_DIRECTORY_MODE)) { if (!disable_output) { printf ("[%s] created\n", downloads_directory); } } } #endif void inner_main (void) { loop (); } void usage (void) { printf ("%s Usage\n", PROGNAME); printf (" --phone/-u specify username (would not be asked during authorization)\n"); printf (" --rsa-key/-k specify location of public key (possible multiple entries)\n"); printf (" --verbosity/-v increase verbosity (0-ERROR 1-WARNIN 2-NOTICE 3+-DEBUG-levels)\n"); printf (" --enable-msg-id/-N message num mode\n"); #ifdef HAVE_LIBCONFIG printf (" --config/-c config file name\n"); printf (" --profile/-p use specified profile\n"); #else #if 0 printf (" --enable-binlog/-B enable binlog\n"); #endif #endif printf (" --log-level/-l log level\n"); printf (" --sync-from-start/-f during authorization fetch all messages since registration\n"); printf (" --disable-auto-accept/-E disable auto accept of encrypted chats\n"); #ifdef USE_LUA printf (" --lua-script/-s lua script file\n"); #endif printf (" --wait-dialog-list/-W send dialog_list query and wait for answer before reading input\n"); printf (" --disable-colors/-C disable color output\n"); printf (" --disable-readline/-R disable readline\n"); printf (" --alert/-A enable bell notifications\n"); printf (" --daemonize/-d daemon mode\n"); printf (" --logname/-L log file name\n"); printf (" --username/-U change uid after start\n"); printf (" --groupname/-G change gid after start\n"); printf (" --disable-output/-D disable output\n"); printf (" --tcp-port/-P port to listen for input commands\n"); printf (" --udp-socket/-S unix socket to create\n"); printf (" --exec/-e make commands end exit\n"); printf (" --disable-names/-I use user and chat IDs in updates instead of names\n"); printf (" --enable-ipv6/-6 use ipv6 (may be unstable)\n"); printf (" --help/-h prints this help\n"); printf (" --accept-any-tcp accepts tcp connections from any src (only loopback by default)\n"); printf (" --disable-link-preview disables server-side previews to links\n"); printf (" --bot/-b bot mode\n"); #ifdef USE_JSON printf (" --json prints answers and values in json format\n"); #endif #ifdef USE_PYTHON printf (" --python-script/-Z python script file\n"); #endif printf (" --permanent-msg-ids use permanent msg ids\n"); printf (" --permanent-peer-ids use permanent peer ids\n"); exit (1); } //extern char *rsa_public_key_name; //extern int default_dc_num; char *log_net_file; FILE *log_net_f; int register_mode; int disable_auto_accept; int wait_dialog_list; char *logname; int daemonize=0; void reopen_logs (void) { int fd; fflush (stdout); fflush (stderr); if ((fd = open ("/dev/null", O_RDWR, 0)) != -1) { dup2 (fd, 0); dup2 (fd, 1); dup2 (fd, 2); if (fd > 2) { close (fd); } } if (logname && (fd = open (logname, O_WRONLY|O_APPEND|O_CREAT, 0640)) != -1) { dup2 (fd, 1); dup2 (fd, 2); if (fd > 2) { close (fd); } } } static void sigusr1_handler (const int sig) { fprintf(stderr, "got SIGUSR1, rotate logs.\n"); reopen_logs (); signal (SIGUSR1, sigusr1_handler); } static void sighup_handler (const int sig) { fprintf(stderr, "got SIGHUP.\n"); signal (SIGHUP, sighup_handler); } char *set_user_name; char *set_group_name; int accept_any_tcp; char *bot_hash; int change_user_group () { char *username = set_user_name; char *groupname = set_group_name; struct passwd *pw; /* lose root privileges if we have them */ if (getuid() == 0 || geteuid() == 0) { if (username == 0 || *username == '\0') { username = "telegramd"; } if ((pw = getpwnam (username)) == 0) { fprintf (stderr, "change_user_group: can't find the user %s to switch to\n", username); return -1; } gid_t gid = pw->pw_gid; if (setgroups (1, &gid) < 0) { fprintf (stderr, "change_user_group: failed to clear supplementary groups list: %m\n"); return -1; } if (groupname) { struct group *g = getgrnam (groupname); if (g == NULL) { fprintf (stderr, "change_user_group: can't find the group %s to switch to\n", groupname); return -1; } gid = g->gr_gid; } if (setgid (gid) < 0) { fprintf (stderr, "change_user_group: setgid (%d) failed. %m\n", (int) gid); return -1; } if (setuid (pw->pw_uid) < 0) { fprintf (stderr, "change_user_group: failed to assume identity of user %s\n", username); return -1; } else { pw = getpwuid(getuid()); setenv("USER", pw->pw_name, 1); setenv("HOME", pw->pw_dir, 1); setenv("SHELL", pw->pw_shell, 1); } } return 0; } char *unix_socket; void args_parse (int argc, char **argv) { TLS = tgl_state_alloc (); static struct option long_options[] = { {"debug-allocator", no_argument, 0, 1000 }, {"phone", required_argument, 0, 'u'}, {"rsa-key", required_argument, 0, 'k'}, {"verbosity", no_argument, 0, 'v'}, {"enable-msg-id", no_argument, 0, 'N'}, #ifdef HAVE_LIBCONFIG {"config", required_argument, 0, 'c'}, {"profile", required_argument, 0, 'p'}, #else #if 0 {"enable-binlog", no_argument, 0, 'B'}, #endif #endif {"log-level", required_argument, 0, 'l'}, {"sync-from-start", no_argument, 0, 'f'}, {"disable-auto-accept", no_argument, 0, 'E'}, {"allow-weak-random", no_argument, 0, 'w'}, #ifdef USE_LUA {"lua-script", required_argument, 0, 's'}, #endif {"wait-dialog-list", no_argument, 0, 'W'}, {"disable-colors", no_argument, 0, 'C'}, {"disable-readline", no_argument, 0, 'R'}, {"alert", no_argument, 0, 'A'}, {"daemonize", no_argument, 0, 'd'}, {"logname", required_argument, 0, 'L'}, {"username", required_argument, 0, 'U'}, {"groupname", required_argument, 0, 'G'}, {"disable-output", no_argument, 0, 'D'}, {"reset-authorization", no_argument, 0, 'q'}, {"tcp-port", required_argument, 0, 'P'}, {"unix-socket", required_argument, 0, 'S'}, {"exec", required_argument, 0, 'e'}, {"disable-names", no_argument, 0, 'I'}, {"enable-ipv6", no_argument, 0, '6'}, {"bot", optional_argument, 0, 'b'}, {"help", no_argument, 0, 'h'}, {"accept-any-tcp", no_argument, 0, 1001}, {"disable-link-preview", no_argument, 0, 1002}, {"json", no_argument, 0, 1003}, {"python-script", required_argument, 0, 'Z'}, {"permanent-msg-ids", no_argument, 0, 1004}, {"permanent-peer-ids", no_argument, 0, 1005}, {0, 0, 0, 0 } }; int opt = 0; while ((opt = getopt_long (argc, argv, "u:hk:vNl:fEwWCRAdL:DU:G:qP:S:e:I6b" #ifdef HAVE_LIBCONFIG "c:p:" #else #if 0 "B" #endif #endif #ifdef USE_LUA "s:" #endif #ifdef USE_PYTHON "Z:" #endif , long_options, NULL )) != -1) { switch (opt) { case 'b': bot_mode ++; if (optarg) { bot_hash = optarg; } break; case 1000: tgl_allocator = &tgl_allocator_debug; break; case 1001: accept_any_tcp = 1; break; case 'u': set_default_username (optarg); break; case 'k': //rsa_public_key_name = tstrdup (optarg); tgl_set_rsa_key (TLS, optarg); break; case 'v': tgl_incr_verbosity (TLS); verbosity ++; break; case 'N': msg_num_mode ++; break; #ifdef HAVE_LIBCONFIG case 'c': config_filename = tstrdup (optarg); break; case 'p': prefix = optarg; assert (strlen (prefix) <= 100); break; #else #if 0 case 'B': binlog_enabled = 1; break; #endif #endif case 'l': log_level = atoi (optarg); break; case 'f': sync_from_start = 1; break; case 'E': disable_auto_accept = 1; break; case 'w': allow_weak_random = 1; break; #ifdef USE_LUA case 's': lua_file = strdup (optarg); break; #endif case 'W': wait_dialog_list = 1; break; #ifdef USE_PYTHON case 'Z': python_file = strdup (optarg); break; #endif case 'C': disable_colors ++; break; case 'R': readline_disabled ++; break; case 'A': alert_sound = 1; break; case 'd': daemonize ++; break; case 'L': logname = optarg; break; case 'U': set_user_name = optarg; break; case 'G': set_group_name = optarg; break; case 'D': disable_output ++; break; case 'q': reset_authorization ++; break; case 'P': port = atoi (optarg); break; case 'S': unix_socket = optarg; break; case 'e': start_command = optarg; break; case 'I': use_ids ++; break; case '6': ipv6_enabled = 1; break; case 1002: disable_link_preview = 2; break; case 1003: enable_json = 1; break; case 1004: permanent_msg_id_mode = 1; break; case 1005: permanent_peer_id_mode = 1; break; case 'h': default: usage (); break; } } } #ifdef HAVE_EXECINFO_H void print_backtrace (void) { void *buffer[255]; const int calls = backtrace (buffer, sizeof (buffer) / sizeof (void *)); backtrace_symbols_fd (buffer, calls, 1); } #else void print_backtrace (void) { if (write (1, "No libexec. Backtrace disabled\n", 32) < 0) { // Sad thing } } #endif int sfd; int usfd; void termination_signal_handler (int signum) { if (!readline_disabled) { rl_free_line_state (); rl_cleanup_after_signal (); } if (write (1, "SIGNAL received\n", 18) < 0) { // Sad thing } if (unix_socket) { unlink (unix_socket); } if (usfd > 0) { close (usfd); } if (sfd > 0) { close (sfd); } print_backtrace (); exit (EXIT_FAILURE); } volatile int sigterm_cnt; void sig_term_handler (int signum __attribute__ ((unused))) { signal (signum, termination_signal_handler); //set_terminal_attributes (); if (write (1, "SIGTERM/SIGINT received\n", 25) < 0) { // Sad thing } //if (TLS && TLS->ev_base) { // event_base_loopbreak (TLS->ev_base); //} sigterm_cnt ++; } void do_halt (int error) { int retval; if (daemonize) { return; } if (!readline_disabled) { rl_free_line_state (); rl_cleanup_after_signal (); } if (write (1, "halt\n", 5) < 0) { // Sad thing } if (unix_socket) { unlink (unix_socket); } if (usfd > 0) { close (usfd); } if (sfd > 0) { close (sfd); } if (exit_code) { retval = exit_code; } else { retval = error ? EXIT_FAILURE : EXIT_SUCCESS; } exit (retval); } int main (int argc, char **argv) { signal (SIGSEGV, termination_signal_handler); signal (SIGABRT, termination_signal_handler); signal (SIGBUS, termination_signal_handler); signal (SIGQUIT, termination_signal_handler); signal (SIGFPE, termination_signal_handler); signal (SIGPIPE, SIG_IGN); signal (SIGTERM, sig_term_handler); signal (SIGINT, sig_term_handler); rl_catch_signals = 0; log_level = 10; args_parse (argc, argv); change_user_group (); if (port > 0) { struct sockaddr_in serv_addr; int yes = 1; sfd = socket (AF_INET, SOCK_STREAM, 0); if (sfd < 0) { perror ("socket"); exit(1); } if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0) { perror("setsockopt"); exit(1); } memset (&serv_addr, 0, sizeof (serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = accept_any_tcp ? INADDR_ANY : htonl (0x7f000001); serv_addr.sin_port = htons (port); if (bind (sfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) { perror ("bind"); exit(1); } listen (sfd, 5); } else { sfd = -1; } if (unix_socket) { assert (strlen (unix_socket) < 100); struct sockaddr_un serv_addr; usfd = socket (AF_UNIX, SOCK_STREAM, 0); if (usfd < 0) { perror ("socket"); exit(1); } memset (&serv_addr, 0, sizeof (serv_addr)); serv_addr.sun_family = AF_UNIX; snprintf (serv_addr.sun_path, sizeof(serv_addr.sun_path), "%s", unix_socket); if (bind (usfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) { perror ("bind"); exit(1); } listen (usfd, 5); } else { usfd = -1; } if (daemonize) { signal (SIGHUP, sighup_handler); reopen_logs (); } signal (SIGUSR1, sigusr1_handler); if (!disable_output) { printf ( "Telegram-cli version " TELEGRAM_CLI_VERSION ", Copyright (C) 2013-2015 Vitaly Valtman\n" "Telegram-cli comes with ABSOLUTELY NO WARRANTY; for details type `show_license'.\n" "This is free software, and you are welcome to redistribute it\n" "under certain conditions; type `show_license' for details.\n" "Telegram-cli uses libtgl version " TGL_VERSION "\n" #ifndef TGL_AVOID_OPENSSL "Telegram-cli includes software developed by the OpenSSL Project\n" "for use in the OpenSSL Toolkit. (http://www.openssl.org/)\n" #endif #ifdef USE_PYTHON "Telegram-cli uses libpython version " PY_VERSION "\n" #endif ); } running_for_first_time (); parse_config (); #ifdef __FreeBSD__ tgl_set_rsa_key (TLS, "/usr/local/etc/" PROG_NAME "/server.pub"); #else tgl_set_rsa_key (TLS, "/etc/" PROG_NAME "/server.pub"); #endif tgl_set_rsa_key (TLS, "tg-server.pub"); tgl_set_rsa_key_direct (TLS, tglmp_get_default_e (), tglmp_get_default_key_len (), tglmp_get_default_key ()); get_terminal_attributes (); #ifdef USE_LUA if (lua_file) { lua_init (lua_file); } #endif #ifdef USE_PYTHON if (python_file) { py_init (python_file); } #endif inner_main (); return 0; } ================================================ FILE: python-tg.c ================================================ /* This file is part of telegram-cli. Telegram-cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Telegram-cli 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 telegram-cli. If not, see . Copyright Vitaly Valtman 2013-2015 Copyright Vincent Castellano 2015 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef USE_PYTHON #include "python-tg.h" #include #include #include #include #include "bytesobject.h" // Python 2/3 compat macros #if PY_MAJOR_VERSION >= 3 #define MOD_ERROR_VAL NULL #define MOD_SUCCESS_VAL(val) val #define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void) #define MOD_DEF(ob, name, doc, methods) \ static struct PyModuleDef moduledef = { \ PyModuleDef_HEAD_INIT, name, doc, -1, methods, NULL, NULL, NULL, NULL,}; \ ob = PyModule_Create(&moduledef); #define PyInt_FromLong PyLong_FromLong #else #define MOD_ERROR_VAL #define MOD_SUCCESS_VAL(val) #define MOD_INIT(name) void init##name(void) #define MOD_DEF(ob, name, doc, methods) \ ob = Py_InitModule3(name, methods, doc); #endif #define TGL_PYTHON_CALLBACK(name, func) \ PyObject *set##func(PyObject *dummy, PyObject *args) { \ PyObject *result = NULL; \ PyObject *temp; \ if (PyArg_ParseTuple(args, "O:set_##name", &temp)) { \ if (!PyCallable_Check(temp)) { \ PyErr_SetString(PyExc_TypeError, "parameter must be callable");\ return NULL;\ }\ Py_XINCREF(temp);\ Py_XDECREF(func);\ func = temp;\ Py_INCREF(Py_None);\ result = Py_None;\ }\ return result;\ } // Python Imports #include "datetime.h" // Custom Types #include "python-types.h" extern PyTypeObject tgl_PeerType; extern PyTypeObject tgl_MsgType; //#include "interface.h" //#include "auto/constants.h" #include #include "interface.h" #include extern int verbosity; extern struct tgl_state *TLS; static int python_loaded; // TGL Python Exceptions PyObject *TglError; PyObject *PeerError; PyObject *MsgError; // Python update function callables PyObject *_py_binlog_end; PyObject *_py_diff_end; PyObject *_py_our_id; PyObject *_py_new_msg; PyObject *_py_secret_chat_update; PyObject *_py_user_update; PyObject *_py_chat_update; PyObject *_py_on_loop; PyObject* get_peer (tgl_peer_id_t id, tgl_peer_t *P); void py_add_string_field (PyObject* dict, char *name, const char *value) { assert (PyDict_Check(dict)); assert (name && strlen (name)); if (!value || !strlen (value)) { return; } PyObject *str = PyUnicode_FromString(value); if(PyUnicode_Check(str)) PyDict_SetItemString (dict, name, str); } void py_add_string_field_arr (PyObject* list, int num, const char *value) { assert(PyList_Check(list)); if (!value || !strlen (value)) { return; } if(num >= 0) PyList_SetItem (list, num, PyUnicode_FromString (value)); else // Append PyList_Append (list, PyUnicode_FromString (value)); } void py_add_num_field (PyObject* dict, const char *name, double value) { assert (PyDict_Check(dict)); assert (name && strlen (name)); PyDict_SetItemString (dict, name, PyFloat_FromDouble(value)); } PyObject* get_tgl_peer_type (int x) { PyObject *type; switch (x) { case TGL_PEER_USER: type = PyUnicode_FromString("user"); break; case TGL_PEER_CHAT: type = PyUnicode_FromString("chat"); break; case TGL_PEER_ENCR_CHAT: type = PyUnicode_FromString("encr_chat"); break; default: assert (0); } return type; } PyObject* get_update_types (unsigned flags) { PyObject* types; types = PyList_New(0); if(types == NULL) assert(0); // TODO handle python exception if (flags & TGL_UPDATE_CREATED) { py_add_string_field_arr(types, -1, "created"); } if (flags & TGL_UPDATE_DELETED) { py_add_string_field_arr(types, -1, "deleted"); } if (flags & TGL_UPDATE_PHONE) { py_add_string_field_arr(types, -1, "phone"); } if (flags & TGL_UPDATE_CONTACT) { py_add_string_field_arr(types, -1, "contact"); } if (flags & TGL_UPDATE_PHOTO) { py_add_string_field_arr(types, -1, "photo"); } if (flags & TGL_UPDATE_BLOCKED) { py_add_string_field_arr(types, -1, "blocked"); } if (flags & TGL_UPDATE_REAL_NAME) { py_add_string_field_arr(types, -1, "real_name"); } if (flags & TGL_UPDATE_NAME) { py_add_string_field_arr(types, -1, "name"); } if (flags & TGL_UPDATE_REQUESTED) { py_add_string_field_arr(types, -1, "requested"); } if (flags & TGL_UPDATE_WORKING) { py_add_string_field_arr(types, -1, "working"); } if (flags & TGL_UPDATE_FLAGS) { py_add_string_field_arr(types, -1, "flags"); } if (flags & TGL_UPDATE_TITLE) { py_add_string_field_arr(types, -1, "title"); } if (flags & TGL_UPDATE_ADMIN) { py_add_string_field_arr(types, -1, "admin"); } if (flags & TGL_UPDATE_MEMBERS) { py_add_string_field_arr(types, -1, "members"); } if (flags & TGL_UPDATE_ACCESS_HASH) { py_add_string_field_arr(types, -1, "access_hash"); } if (flags & TGL_UPDATE_USERNAME) { py_add_string_field_arr(types, -1, "username"); } return types; } PyObject* get_peer (tgl_peer_id_t id, tgl_peer_t *P) { PyObject *peer; peer = tgl_Peer_FromTglPeer(P); return peer; } PyObject* get_message (struct tgl_message *M) { assert (M); PyObject *msg; msg = tgl_Msg_FromTglMsg(M); return msg; } void py_binlog_end (void) { if (!python_loaded) { return; } PyObject *arglist, *result; if(_py_binlog_end == NULL) { logprintf("Callback not set for on_binlog_end"); return; } arglist = Py_BuildValue("()"); result = PyEval_CallObject(_py_binlog_end, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); else if(PyUnicode_Check(result)) logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); Py_XDECREF(result); } void py_diff_end (void) { if (!python_loaded) { return; } PyObject *arglist, *result; if(_py_diff_end == NULL) { logprintf("Callback not set for on_diff_end"); return; } arglist = Py_BuildValue("()"); result = PyEval_CallObject(_py_diff_end, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); else if(PyUnicode_Check(result)) logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); Py_XDECREF(result); } void py_our_id (int id) { if (!python_loaded) { return; } PyObject *arglist, *result; if(_py_our_id == NULL) { logprintf("Callback not set for on_our_id"); return; } arglist = Py_BuildValue("(i)", id); result = PyEval_CallObject(_py_our_id, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); else if(PyUnicode_Check(result)) logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); Py_XDECREF(result); } void py_new_msg (struct tgl_message *M) { if (!python_loaded) { return; } PyObject *msg; PyObject *arglist, *result; if(_py_new_msg == NULL) { logprintf("Callback not set for on_new_msg"); return; } msg = get_message (M); arglist = Py_BuildValue("(O)", msg); result = PyEval_CallObject(_py_new_msg, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); else if(PyUnicode_Check(result)) logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); Py_XDECREF(result); } void py_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) { if (!python_loaded) { return; } PyObject *peer, *types; PyObject *arglist, *result; if(_py_secret_chat_update == NULL) { logprintf("Callback not set for on_secret_chat_update"); return; } peer = get_peer (C->id, (void *)C); types = get_update_types (flags); arglist = Py_BuildValue("(OO)", peer, types); result = PyEval_CallObject(_py_secret_chat_update, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); else if(PyUnicode_Check(result)) logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); Py_XDECREF(result); } void py_user_update (struct tgl_user *U, unsigned flags) { if (!python_loaded) { return; } PyObject *peer, *types; PyObject *arglist, *result; if(_py_user_update == NULL) { logprintf("Callback not set for on_user_update"); return; } peer = get_peer (U->id, (void *)U); types = get_update_types (flags); arglist = Py_BuildValue("(OO)", peer, types); result = PyEval_CallObject(_py_user_update, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); else if(PyUnicode_Check(result)) logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); Py_XDECREF(result); } void py_chat_update (struct tgl_chat *C, unsigned flags) { if (!python_loaded) { return; } PyObject *peer, *types; PyObject *arglist, *result; if(_py_chat_update == NULL) { logprintf("Callback not set for on_chat_update"); return; } peer = get_peer (C->id, (void *)C); types = get_update_types (flags); arglist = Py_BuildValue("(OO)", peer, types); result = PyEval_CallObject(_py_chat_update, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); else if(PyUnicode_Check(result)) logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); Py_XDECREF(result); } void py_on_loop () { if (!python_loaded) { return; } PyObject *result; if(_py_on_loop == NULL) { logprintf("Callback not set for on_chat_update"); return; } result = PyEval_CallObject(_py_on_loop, Py_BuildValue("()")); if(result == NULL) PyErr_Print(); else if(PyUnicode_Check(result)) logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); Py_XDECREF(result); } ////extern tgl_peer_t *Peers[]; ////extern int peer_num; // #define MAX_PY_COMMANDS 1000 void *py_ptr[MAX_PY_COMMANDS]; static int pos; // //static inline tgl_peer_t *get_peer (const char *s) { // return tgl_peer_get_by_name (TLS, s); //} enum py_query_type { pq_contact_list, pq_dialog_list, pq_msg, pq_send_typing, pq_send_typing_abort, pq_rename_chat, pq_send_photo, pq_chat_set_photo, pq_set_profile_photo, pq_set_profile_name, pq_send_video, pq_send_text, pq_fwd, pq_fwd_media, pq_load_photo, pq_load_video_thumb, pq_load_video, pq_chat_info, pq_user_info, pq_history, pq_chat_add_user, pq_chat_del_user, pq_add_contact, pq_del_contact, pq_rename_contact, pq_search, pq_global_search, pq_mark_read, pq_create_secret_chat, pq_create_group_chat, pq_send_audio, pq_send_document, pq_send_file, pq_load_audio, pq_load_document, pq_load_document_thumb, pq_delete_msg, pq_restore_msg, pq_accept_secret_chat, pq_send_contact, pq_status_online, pq_status_offline, pq_send_location, pq_extf, pq_import_chat_link }; void py_empty_cb (struct tgl_state *TLSR, void *cb_extra, int success) { assert (TLSR == TLS); PyObject *callable = cb_extra; PyObject *arglist = NULL; PyObject *result = NULL; if(PyCallable_Check(callable)) { arglist = Py_BuildValue("(O)", success ? Py_True : Py_False); result = PyEval_CallObject(callable, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); Py_XDECREF(result); } Py_XDECREF(callable); } void py_contact_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_user **UL) { assert (TLSR == TLS); PyObject *callable = cb_extra; PyObject *arglist = NULL; PyObject *peers = NULL; PyObject *result = NULL; if(PyCallable_Check(callable)) { peers = PyList_New(0); if (success) { int i; for (i = 0; i < num; i++) { PyList_Append(peers, get_peer (UL[i]->id, (void *)UL[i])); } } arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, peers); result = PyEval_CallObject(callable, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); Py_XDECREF(result); } Py_XDECREF(callable); } void py_dialog_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, tgl_peer_id_t peers[], int msgs[], int unread[]) { assert (TLSR == TLS); PyObject *callable = cb_extra; PyObject *arglist = NULL; PyObject *dialog_list = NULL; PyObject *dialog = NULL; PyObject *result = NULL; if(PyCallable_Check(callable)) { dialog_list = PyList_New(0); if (success) { int i; for (i = 0; i < num; i++) { dialog = PyDict_New(); PyDict_SetItemString(dialog, "peer", get_peer(peers[i], tgl_peer_get (TLS, peers[i]))); struct tgl_message *M = tgl_message_get (TLS, msgs[i]); if (M && (M->flags & TGLMF_CREATED)) { PyDict_SetItemString(dialog, "message", get_message(M)); } PyDict_SetItemString(dialog, "unread", unread[i] ? Py_True : Py_False); PyList_Append(dialog_list, dialog); } } arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, dialog_list); result = PyEval_CallObject(callable, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); Py_XDECREF(result); } Py_XDECREF(callable); } void py_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_message *M) { assert (TLSR == TLS); PyObject *callable = cb_extra; PyObject *arglist = NULL; PyObject *msg = NULL; PyObject *result = NULL; if(PyCallable_Check(callable)) { if (success && M && (M->flags & TGLMF_CREATED)) { msg = get_message(M); } else { Py_INCREF(Py_None); msg = Py_None; } arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, msg); result = PyEval_CallObject(callable, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); Py_XDECREF(result); } Py_XDECREF(callable); } void py_msg_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_message *M[]) { assert (TLSR == TLS); PyObject *callable = cb_extra; PyObject *arglist = NULL; PyObject *msgs = NULL; PyObject *result = NULL; if(PyCallable_Check(callable)) { msgs = PyList_New(0); if (success) { int i; for (i = 0; i < num; i++) { PyList_Append(msgs, get_message (M[i])); } } arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, msgs); result = PyEval_CallObject(callable, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); Py_XDECREF(result); } Py_XDECREF(callable); } void py_file_cb (struct tgl_state *TLSR, void *cb_extra, int success, const char *file_name) { assert (TLSR == TLS); PyObject *callable = cb_extra; PyObject *arglist = NULL; PyObject *filename = NULL; PyObject *result = NULL; if(PyCallable_Check(callable)) { if(success) filename = PyUnicode_FromString(file_name); else { Py_INCREF(Py_None); filename = Py_None; } arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, filename); result = PyEval_CallObject(callable, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); Py_XDECREF(result); } Py_XDECREF(callable); } void py_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_chat *C) { assert (TLSR == TLS); PyObject *callable = cb_extra; PyObject *arglist = NULL; PyObject *peer = NULL; PyObject *result = NULL; if(PyCallable_Check(callable)) { if (success) { peer = get_peer(C->id, (void *)C); } else { Py_INCREF(Py_None); peer = Py_None; } arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, peer); result = PyEval_CallObject(callable, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); Py_XDECREF(result); } Py_XDECREF(callable); } void py_secret_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_secret_chat *C) { assert (TLSR == TLS); PyObject *callable = cb_extra; PyObject *arglist = NULL; PyObject *peer = NULL; PyObject *result = NULL; if(PyCallable_Check(callable)) { if (success) { peer = get_peer(C->id, (void *)C); } else { Py_INCREF(Py_None); peer = Py_None; } arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, peer); result = PyEval_CallObject(callable, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); Py_XDECREF(result); } Py_XDECREF(callable); } void py_user_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_user *C) { assert (TLSR == TLS); PyObject *callable = cb_extra; PyObject *arglist = NULL; PyObject *peer = NULL; PyObject *result = NULL; if(PyCallable_Check(callable)) { if (success) { peer = get_peer(C->id, (void *)C); } else { Py_INCREF(Py_None); peer = Py_None; } arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, peer); result = PyEval_CallObject(callable, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); Py_XDECREF(result); } Py_XDECREF(callable); } void py_str_cb (struct tgl_state *TLSR, void *cb_extra, int success, const char *data) { assert (TLSR == TLS); PyObject *callable = cb_extra; PyObject *arglist = NULL; PyObject *str = NULL; PyObject *result = NULL; if(PyCallable_Check(callable)) { if(success) str = PyUnicode_FromString(data); else { Py_INCREF(Py_None); str = Py_None; } arglist = Py_BuildValue("(OO)", success ? Py_True : Py_False, str); result = PyEval_CallObject(callable, arglist); Py_DECREF(arglist); if(result == NULL) PyErr_Print(); Py_XDECREF(result); } Py_XDECREF(callable); } #define PY_PEER_ID(x) (tgl_peer_id_t)((tgl_Peer*)x)->peer->id void py_do_all (void) { int p = 0; // ping the python thread that we're doing the loop py_on_loop(); while (p < pos) { assert (p + 2 <= pos); enum py_query_type f = (long)py_ptr[p ++]; PyObject *args = (PyObject *)py_ptr[p ++]; const char *str, *str1, *str2, *str3; int preview = 0; int reply_id = 0; unsigned long long flags = 0; Py_ssize_t i; tgl_user_id_t *ids; struct tgl_message *M; int len, len1, len2, len3; int limit, offset; long msg_id = 0; PyObject *pyObj1 = NULL; PyObject *pyObj2 = NULL; PyObject *cb_extra = NULL; PyObject *msg = NULL; PyObject *peer = NULL; PyObject *peer1 = NULL; switch (f) { case pq_contact_list: if(PyArg_ParseTuple(args, "|O", &cb_extra)) tgl_do_update_contact_list (TLS, py_contact_list_cb, cb_extra); else PyErr_Print(); break; case pq_dialog_list: if(PyArg_ParseTuple(args, "|O", &cb_extra)) tgl_do_get_dialog_list (TLS, 100, 0, py_dialog_list_cb, cb_extra); else PyErr_Print(); break; case pq_msg: if(PyArg_ParseTuple(args, "O!s#|OO", &tgl_PeerType, &peer, &str, &len, &cb_extra, &pyObj1)) { if(pyObj1 && PyArg_ParseTuple(pyObj1, "ii", &preview, &reply_id)) { if(preview != -1) { if(preview) flags |= TGL_SEND_MSG_FLAG_ENABLE_PREVIEW; else flags |= TGL_SEND_MSG_FLAG_DISABLE_PREVIEW; } flags |= TGL_SEND_MSG_FLAG_REPLY (reply_id); } tgl_do_send_message (TLS, PY_PEER_ID(peer), str, len, flags, NULL, py_msg_cb, cb_extra); } else PyErr_Print(); Py_XDECREF(pyObj1); break; case pq_send_typing: if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra)) tgl_do_send_typing (TLS, PY_PEER_ID(peer), tgl_typing_typing, py_empty_cb, cb_extra); else PyErr_Print(); break; case pq_send_typing_abort: if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra)) tgl_do_send_typing (TLS, PY_PEER_ID(peer), tgl_typing_cancel, py_empty_cb, cb_extra); else PyErr_Print(); break; case pq_rename_chat: if(PyArg_ParseTuple(args, "O!s#|O", &tgl_PeerType, &peer, &str, &len, &cb_extra)) tgl_do_rename_chat (TLS, PY_PEER_ID(peer), str, len, py_empty_cb, cb_extra); else PyErr_Print(); break; case pq_send_photo: if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra)) tgl_do_send_document (TLS, PY_PEER_ID(peer), str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO, py_msg_cb, cb_extra); else PyErr_Print(); break; case pq_send_video: if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra)) tgl_do_send_document (TLS, PY_PEER_ID(peer), str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_VIDEO, py_msg_cb, cb_extra); else PyErr_Print(); break; case pq_send_audio: if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra)) tgl_do_send_document (TLS, PY_PEER_ID(peer), str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_AUDIO, py_msg_cb, cb_extra); else PyErr_Print(); break; case pq_send_document: if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra)) tgl_do_send_document (TLS, PY_PEER_ID(peer), str, NULL, 0, 0, py_msg_cb, cb_extra); else PyErr_Print(); break; case pq_send_file: if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra)) tgl_do_send_document (TLS, PY_PEER_ID(peer), str, NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_AUTO, py_msg_cb, cb_extra); else PyErr_Print(); break; case pq_send_text: if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra)) tgl_do_send_text (TLS, PY_PEER_ID(peer), str, 0, py_msg_cb, cb_extra); else PyErr_Print(); break; case pq_chat_set_photo: if(PyArg_ParseTuple(args, "O!s|O", &tgl_PeerType, &peer, &str, &cb_extra)) tgl_do_set_chat_photo (TLS, PY_PEER_ID(peer), str, py_empty_cb, cb_extra); else PyErr_Print(); break; case pq_load_photo: case pq_load_video: case pq_load_audio: case pq_load_document: if(PyArg_ParseTuple(args, "O!O", &tgl_MsgType, &msg, &cb_extra)) { M = ((tgl_Msg*)msg)->msg; if (!M || (M->media.type != tgl_message_media_photo && M->media.type != tgl_message_media_document && M->media.type != tgl_message_media_document_encr)) { py_file_cb (TLS, cb_extra, 0, 0); } else { if (M->media.type == tgl_message_media_photo) { assert (M->media.photo); tgl_do_load_photo (TLS, M->media.photo, py_file_cb, cb_extra); } else if (M->media.type == tgl_message_media_document) { tgl_do_load_document (TLS, M->media.document, py_file_cb, cb_extra); } else { tgl_do_load_encr_document (TLS, M->media.encr_document, py_file_cb, cb_extra); } } } break; case pq_load_video_thumb: case pq_load_document_thumb: if(PyArg_ParseTuple(args, "O!O", &tgl_MsgType, &msg, &cb_extra)) { M = ((tgl_Msg*)msg)->msg; if (!M || (M->media.type != tgl_message_media_document)) { py_file_cb (TLS, cb_extra, 0, 0); } else { tgl_do_load_document_thumb (TLS, M->media.document, py_file_cb, cb_extra); } } break; case pq_fwd: if(PyArg_ParseTuple(args, "O!l|O", &tgl_PeerType, &peer, &msg_id, &cb_extra)) tgl_do_forward_message (TLS, PY_PEER_ID(peer), msg_id, 0, py_msg_cb, cb_extra); else PyErr_Print(); break; case pq_fwd_media: if(PyArg_ParseTuple(args, "O!l|O", &tgl_PeerType, &peer, &msg_id, &cb_extra)) tgl_do_forward_media (TLS, PY_PEER_ID(peer), msg_id, 0, py_msg_cb, cb_extra); else PyErr_Print(); break; case pq_chat_info: if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra)) tgl_do_get_chat_info (TLS, PY_PEER_ID(peer), 0, py_chat_cb, cb_extra); else PyErr_Print(); break; case pq_user_info: if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra)) tgl_do_get_user_info (TLS, PY_PEER_ID(peer), 0, py_user_cb, cb_extra); else PyErr_Print(); break; case pq_history: if(PyArg_ParseTuple(args, "O!ii|O", &tgl_PeerType, &peer, &offset, &limit, &cb_extra)) tgl_do_get_history (TLS, PY_PEER_ID(peer), offset, limit, 0, py_msg_list_cb, cb_extra); else PyErr_Print(); break; case pq_chat_add_user: if(PyArg_ParseTuple(args, "O!O!|O", &tgl_PeerType, &peer, &tgl_PeerType, &peer1, &cb_extra)) tgl_do_add_user_to_chat (TLS, PY_PEER_ID(peer), PY_PEER_ID(peer1), 100, py_empty_cb, cb_extra); else PyErr_Print(); break; case pq_chat_del_user: if(PyArg_ParseTuple(args, "O!O!|O", &tgl_PeerType, &peer, &tgl_PeerType, &peer1, &cb_extra)) tgl_do_del_user_from_chat (TLS, PY_PEER_ID(peer), PY_PEER_ID(peer1), py_empty_cb, cb_extra); else PyErr_Print(); break; case pq_add_contact: if(PyArg_ParseTuple(args, "s#s#s#|O", &str1, &len1, &str2, &len2, &str3, &len3, &cb_extra)) tgl_do_add_contact (TLS, str1, len1, str2, len2, str3, len3, 0, py_contact_list_cb, cb_extra); else PyErr_Print(); break; case pq_del_contact: if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra)) tgl_do_del_contact (TLS, PY_PEER_ID(peer), py_empty_cb, cb_extra); else PyErr_Print(); break; case pq_rename_contact: if(PyArg_ParseTuple(args, "s#s#s#|O", &str1, &len1, &str2, &len2, &str3, &len3, &cb_extra)) tgl_do_add_contact (TLS, str1, len1, str2, len2, str3, len3, 1, py_contact_list_cb, cb_extra); else PyErr_Print(); break; case pq_search: if(PyArg_ParseTuple(args, "O!s#|O", &tgl_PeerType, &peer, &str, &len, &cb_extra)) tgl_do_msg_search (TLS, PY_PEER_ID(peer), 0, 0, 40, 0, str, len, py_msg_list_cb, cb_extra); else PyErr_Print(); break; case pq_global_search: if(PyArg_ParseTuple(args, "s#|O", &str, &len, &cb_extra)) tgl_do_msg_search (TLS, tgl_set_peer_id (TGL_PEER_UNKNOWN, 0), 0, 0, 40, 0, str, len, py_msg_list_cb, cb_extra); else PyErr_Print(); break; case pq_mark_read: if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra)) tgl_do_mark_read (TLS, PY_PEER_ID(peer), py_empty_cb, cb_extra); else PyErr_Print(); break; case pq_set_profile_photo: if(PyArg_ParseTuple(args, "s|O", &str, &cb_extra)) tgl_do_set_profile_photo (TLS, str, py_empty_cb, cb_extra); else PyErr_Print(); break; case pq_set_profile_name: if(PyArg_ParseTuple(args, "s#s#|O", &str1, &len1, &str2, &len2, &cb_extra)) tgl_do_set_profile_name (TLS, str1, len1, str2, len2, py_user_cb, cb_extra); else PyErr_Print(); break; case pq_create_secret_chat: if(PyArg_ParseTuple(args, "O!|O", &tgl_PeerType, &peer, &cb_extra)) tgl_do_create_secret_chat (TLS, PY_PEER_ID(peer), py_secret_chat_cb, cb_extra); else PyErr_Print(); break; case pq_create_group_chat: if(PyArg_ParseTuple(args, "O!s#|O", &PyList_Type, &pyObj1, &str, &len, &cb_extra)) { if(PyList_GET_SIZE(pyObj1) > 2) { ids = (tgl_user_id_t *)malloc(PyList_GET_SIZE(pyObj1) * sizeof(tgl_user_id_t)); for(i = 0; i < PyList_GET_SIZE(pyObj1); i++) { peer = PyList_GetItem(pyObj1, i); *(ids+i) = PY_PEER_ID(peer); } tgl_do_create_group_chat (TLS, PyList_GET_SIZE(pyObj1), ids, str, len, py_empty_cb, cb_extra); tfree(ids, PyList_GET_SIZE(pyObj1) * sizeof(tgl_user_id_t)); } else { logprintf("create_group_chat: Argument 1 must be a list of at least 3 peers"); } } Py_XDECREF(pyObj1); break; case pq_delete_msg: case pq_restore_msg: if(PyArg_ParseTuple(args, "l|O", &msg_id, &cb_extra)) tgl_do_delete_msg (TLS, msg_id, py_empty_cb, cb_extra); else PyErr_Print(); break; /* case pq_accept_secret_chat: tgl_do_accept_encr_chat_request (TLS, py_ptr[p + 1], py_secret_chat_cb, py_ptr[p]); break; */ case pq_send_contact: if(PyArg_ParseTuple(args, "O!s#s#s#|O", &tgl_PeerType, &peer, &str1, &len1, &str2, &len2, &str3, &len3, &cb_extra)) tgl_do_send_contact (TLS, PY_PEER_ID(peer), str1, len1, str2, len2, str3, len3, 0, py_msg_cb, cb_extra); else PyErr_Print(); break; case pq_status_online: if(PyArg_ParseTuple(args, "|O", &cb_extra)) tgl_do_update_status (TLS, 1, py_empty_cb, cb_extra); else PyErr_Print(); break; case pq_status_offline: if(PyArg_ParseTuple(args, "|O", &cb_extra)) tgl_do_update_status (TLS, 0, py_empty_cb, cb_extra); else PyErr_Print(); break; case pq_extf: if(PyArg_ParseTuple(args, "s#|O", &str, &len, &cb_extra)) tgl_do_send_extf (TLS, str, len, py_str_cb, cb_extra); else PyErr_Print(); break; case pq_import_chat_link: if(PyArg_ParseTuple(args, "s#|O", &str, &len, &cb_extra)) tgl_do_import_chat_link (TLS, str, len, py_empty_cb, cb_extra); else PyErr_Print(); break; case pq_send_location: if(PyArg_ParseTuple(args, "O!O!O!|O", &tgl_PeerType, &peer, &PyFloat_Type, &pyObj1, &PyFloat_Type, &pyObj2, &cb_extra)){ tgl_do_send_location (TLS, PY_PEER_ID(peer), PyFloat_AsDouble(pyObj1), PyFloat_AsDouble(pyObj2), 0, py_msg_cb, cb_extra); Py_XDECREF(pyObj1); Py_XDECREF(pyObj2); } else PyErr_Print(); break; default: assert (0); } // Increment reference on cb_extra as it is passed on to the callback to use Py_XINCREF(cb_extra); // Clean up any arg variables we could have used. //Py_XDECREF(args); // TODO: this is going negative ref and causing segfaults Py_XDECREF(peer); Py_XDECREF(peer1); } pos = 0; } PyObject* push_py_func(enum py_query_type type, PyObject *args) { assert(pos + 2 < MAX_PY_COMMANDS); py_ptr[pos ++] = (void *)(long)type; py_ptr[pos ++] = (void *)args; Py_INCREF(args); Py_RETURN_TRUE; } // Register functions to push commands on the queue PyObject* py_contact_list(PyObject *self, PyObject *args) { return push_py_func(pq_contact_list, args); } PyObject* py_dialog_list(PyObject *self, PyObject *args) { return push_py_func(pq_dialog_list, args); } PyObject* py_rename_chat(PyObject *self, PyObject *args) { return push_py_func(pq_rename_chat, args); } PyObject* py_send_msg(PyObject *self, PyObject *args) { return push_py_func(pq_msg, args); } PyObject* py_send_typing(PyObject *self, PyObject *args) { return push_py_func(pq_send_typing, args); } PyObject* py_send_typing_abort(PyObject *self, PyObject *args) { return push_py_func(pq_send_typing_abort, args); } PyObject* py_send_photo(PyObject *self, PyObject *args) { return push_py_func(pq_send_photo, args); } PyObject* py_send_video(PyObject *self, PyObject *args) { return push_py_func(pq_send_video, args); } PyObject* py_send_audio(PyObject *self, PyObject *args) { return push_py_func(pq_send_audio, args); } PyObject* py_send_document(PyObject *self, PyObject *args) { return push_py_func(pq_send_document, args); } PyObject* py_send_file(PyObject *self, PyObject *args) { return push_py_func(pq_send_file, args); } PyObject* py_send_text(PyObject *self, PyObject *args) { return push_py_func(pq_send_text, args); } PyObject* py_chat_set_photo(PyObject *self, PyObject *args) { return push_py_func(pq_chat_set_photo, args); } PyObject* py_load_photo(PyObject *self, PyObject *args) { return push_py_func(pq_load_photo, args); } PyObject* py_load_video(PyObject *self, PyObject *args) { return push_py_func(pq_load_video, args); } PyObject* py_load_video_thumb(PyObject *self, PyObject *args) { return push_py_func(pq_load_video_thumb, args); } PyObject* py_load_audio(PyObject *self, PyObject *args) { return push_py_func(pq_load_audio, args); } PyObject* py_load_document(PyObject *self, PyObject *args) { return push_py_func(pq_load_document, args); } PyObject* py_load_document_thumb(PyObject *self, PyObject *args) { return push_py_func(pq_load_document_thumb, args); } PyObject* py_fwd(PyObject *self, PyObject *args) { return push_py_func(pq_fwd, args); } PyObject* py_fwd_media(PyObject *self, PyObject *args) { return push_py_func(pq_fwd_media, args); } PyObject* py_chat_info(PyObject *self, PyObject *args) { return push_py_func(pq_chat_info, args); } PyObject* py_user_info(PyObject *self, PyObject *args) { return push_py_func(pq_chat_info, args); } PyObject* py_history(PyObject *self, PyObject *args) { return push_py_func(pq_history, args); } PyObject* py_chat_add_user(PyObject *self, PyObject *args) { return push_py_func(pq_chat_add_user, args); } PyObject* py_chat_del_user(PyObject *self, PyObject *args) { return push_py_func(pq_chat_del_user, args); } PyObject* py_add_contact(PyObject *self, PyObject *args) { return push_py_func(pq_add_contact, args); } PyObject* py_del_contact(PyObject *self, PyObject *args) { return push_py_func(pq_del_contact, args); } PyObject* py_rename_contact(PyObject *self, PyObject *args) { return push_py_func(pq_rename_contact, args); } PyObject* py_search(PyObject *self, PyObject *args) { return push_py_func(pq_search, args); } PyObject* py_global_search(PyObject *self, PyObject *args) { return push_py_func(pq_global_search, args); } PyObject* py_mark_read(PyObject *self, PyObject *args) { return push_py_func(pq_mark_read, args); } PyObject* py_set_profile_photo(PyObject *self, PyObject *args) { return push_py_func(pq_set_profile_photo, args); } PyObject* py_set_profile_name(PyObject *self, PyObject *args) { return push_py_func(pq_set_profile_name, args); } PyObject* py_create_secret_chat(PyObject *self, PyObject *args) { return push_py_func(pq_create_secret_chat, args); } PyObject* py_create_group_chat(PyObject *self, PyObject *args) { return push_py_func(pq_create_group_chat, args); } PyObject* py_delete_msg(PyObject *self, PyObject *args) { return push_py_func(pq_delete_msg, args); } PyObject* py_restore_msg(PyObject *self, PyObject *args) { return push_py_func(pq_restore_msg, args); } PyObject* py_accept_secret_chat(PyObject *self, PyObject *args) { return push_py_func(pq_accept_secret_chat, args); } PyObject* py_send_contact(PyObject *self, PyObject *args) { return push_py_func(pq_send_contact, args); } PyObject* py_status_online(PyObject *self, PyObject *args) { return push_py_func(pq_status_online, args); } PyObject* py_status_offline(PyObject *self, PyObject *args) { return push_py_func(pq_status_offline, args); } PyObject* py_send_location(PyObject *self, PyObject *args) { return push_py_func(pq_send_location, args); } PyObject* py_extf(PyObject *self, PyObject *args) { return push_py_func(pq_extf, args); } PyObject* py_import_chat_link(PyObject *self, PyObject *args) { return push_py_func(pq_import_chat_link, args); } extern int safe_quit; extern int exit_code; PyObject* py_safe_quit(PyObject *self, PyObject *args) { int exit_val = 0; if(PyArg_ParseTuple(args, "|i", &exit_val)) { safe_quit = 1; exit_code = exit_val; } else { PyErr_Print(); } Py_RETURN_NONE; } PyObject* py_set_preview(PyObject *self, PyObject *args) { int preview = 0; if(PyArg_ParseTuple(args, "p", &preview)) { if(preview) TLS->disable_link_preview = 0; else TLS->disable_link_preview = 1; } else { PyErr_Print(); } Py_RETURN_NONE; } // Store callables for python functions TGL_PYTHON_CALLBACK("on_binlog_replay_end", _py_binlog_end); TGL_PYTHON_CALLBACK("on_get_difference_end", _py_diff_end); TGL_PYTHON_CALLBACK("on_our_id", _py_our_id); TGL_PYTHON_CALLBACK("on_msg_receive", _py_new_msg); TGL_PYTHON_CALLBACK("on_secret_chat_update", _py_secret_chat_update); TGL_PYTHON_CALLBACK("on_user_update", _py_user_update); TGL_PYTHON_CALLBACK("on_chat_update", _py_chat_update); TGL_PYTHON_CALLBACK("on_loop", _py_on_loop); static PyMethodDef py_tgl_methods[] = { {"get_contact_list", py_contact_list, METH_VARARGS, "retrieve contact list"}, {"get_dialog_list", py_dialog_list, METH_VARARGS, ""}, {"rename_chat", py_rename_chat, METH_VARARGS, ""}, {"send_msg", py_send_msg, METH_VARARGS, "send message to user or chat"}, {"send_typing", py_send_typing, METH_VARARGS, ""}, {"send_typing_abort", py_send_typing_abort, METH_VARARGS, ""}, {"send_photo", py_send_photo, METH_VARARGS, ""}, {"send_video", py_send_video, METH_VARARGS, ""}, {"send_audio", py_send_audio, METH_VARARGS, ""}, {"send_document", py_send_document, METH_VARARGS, ""}, {"send_file", py_send_file, METH_VARARGS, ""}, {"send_text", py_send_text, METH_VARARGS, ""}, {"chat_set_photo", py_chat_set_photo, METH_VARARGS, ""}, {"load_photo", py_load_photo, METH_VARARGS, ""}, {"load_video", py_load_video, METH_VARARGS, ""}, {"load_video_thumb", py_load_video_thumb, METH_VARARGS, ""}, {"load_audio", py_load_audio, METH_VARARGS, ""}, {"load_document", py_load_document, METH_VARARGS, ""}, {"load_document_thumb", py_load_document_thumb, METH_VARARGS, ""}, {"fwd_msg", py_fwd, METH_VARARGS, ""}, {"fwd_media", py_fwd_media, METH_VARARGS, ""}, {"chat_info", py_chat_info, METH_VARARGS, ""}, {"user_info", py_user_info, METH_VARARGS, ""}, {"get_history", py_history, METH_VARARGS, ""}, {"chat_add_user", py_chat_add_user, METH_VARARGS, ""}, {"chat_del_user", py_chat_del_user, METH_VARARGS, ""}, {"add_contact", py_add_contact, METH_VARARGS, ""}, {"del_contact", py_del_contact, METH_VARARGS, ""}, {"rename_contact", py_rename_contact, METH_VARARGS, ""}, {"msg_search", py_search, METH_VARARGS, ""}, {"msg_global_search", py_global_search, METH_VARARGS, ""}, {"mark_read", py_mark_read, METH_VARARGS, ""}, {"set_profile_photo", py_set_profile_photo, METH_VARARGS, ""}, {"set_profile_name", py_set_profile_name, METH_VARARGS, ""}, {"create_secret_chat", py_create_secret_chat, METH_VARARGS, ""}, {"create_group_chat", py_create_group_chat, METH_VARARGS, ""}, {"delete_msg", py_delete_msg, METH_VARARGS, ""}, {"restore_msg", py_restore_msg, METH_VARARGS, ""}, {"accept_secret_chat", py_accept_secret_chat, METH_VARARGS, ""}, {"send_contact", py_send_contact, METH_VARARGS, ""}, {"status_online", py_status_online, METH_VARARGS, ""}, {"status_offline", py_status_offline, METH_VARARGS, ""}, {"send_location", py_send_location, METH_VARARGS, ""}, {"ext_function", py_extf, METH_VARARGS, ""}, {"import_chat_link", py_import_chat_link, METH_VARARGS, ""}, {"set_on_binlog_replay_end", set_py_binlog_end, METH_VARARGS, ""}, {"set_on_get_difference_end", set_py_diff_end, METH_VARARGS, ""}, {"set_on_our_id", set_py_our_id, METH_VARARGS, ""}, {"set_on_msg_receive", set_py_new_msg, METH_VARARGS, ""}, {"set_on_secret_chat_update", set_py_secret_chat_update, METH_VARARGS, ""}, {"set_on_user_update", set_py_user_update, METH_VARARGS, ""}, {"set_on_chat_update", set_py_chat_update, METH_VARARGS, ""}, {"set_on_loop", set_py_on_loop, METH_VARARGS, ""}, {"set_link_preview", py_set_preview, METH_VARARGS, ""}, {"safe_quit", py_safe_quit, METH_VARARGS, ""}, {"safe_exit", py_safe_quit, METH_VARARGS, ""}, // Alias to safe_quit for naming consistancy in python. { NULL, NULL, 0, NULL } }; void py_add_action_enums(PyObject *m) { PyModule_AddIntConstant(m, "ACTION_NONE", tgl_message_action_none); PyModule_AddIntConstant(m, "ACTION_GEO_CHAT_CREATE", tgl_message_action_geo_chat_create); PyModule_AddIntConstant(m, "ACTION_GEO_CHAT_CHECKIN", tgl_message_action_geo_chat_checkin); PyModule_AddIntConstant(m, "ACTION_CHAT_CREATE", tgl_message_action_chat_create); PyModule_AddIntConstant(m, "ACTION_CHAT_EDIT_TITLE", tgl_message_action_chat_edit_title); PyModule_AddIntConstant(m, "ACTION_CHAT_EDIT_PHOTO", tgl_message_action_chat_edit_photo); PyModule_AddIntConstant(m, "ACTION_CHAT_DELETE_PHOTO", tgl_message_action_chat_delete_photo); PyModule_AddIntConstant(m, "ACTION_CHAT_ADD_USER", tgl_message_action_chat_add_user); PyModule_AddIntConstant(m, "ACTION_CHAT_ADD_USER_BY_LINK", tgl_message_action_chat_add_user_by_link); PyModule_AddIntConstant(m, "ACTION_CHAT_DELETE_USER", tgl_message_action_chat_delete_user); PyModule_AddIntConstant(m, "ACTION_SET_MESSAGE_TTL", tgl_message_action_set_message_ttl); PyModule_AddIntConstant(m, "ACTION_READ_MESSAGES", tgl_message_action_read_messages); PyModule_AddIntConstant(m, "ACTION_DELETE_MESSAGES", tgl_message_action_delete_messages); PyModule_AddIntConstant(m, "ACTION_SCREENSHOT_MESSAGES", tgl_message_action_screenshot_messages); PyModule_AddIntConstant(m, "ACTION_FLUSH_HISTORY", tgl_message_action_flush_history); PyModule_AddIntConstant(m, "ACTION_RESEND", tgl_message_action_resend); PyModule_AddIntConstant(m, "ACTION_NOTIFY_LAYER", tgl_message_action_notify_layer); PyModule_AddIntConstant(m, "ACTION_TYPING", tgl_message_action_typing); PyModule_AddIntConstant(m, "ACTION_NOOP", tgl_message_action_noop); PyModule_AddIntConstant(m, "ACTION_COMMIT_KEY", tgl_message_action_commit_key); PyModule_AddIntConstant(m, "ACTION_ABORT_KEY", tgl_message_action_abort_key); PyModule_AddIntConstant(m, "ACTION_REQUEST_KEY", tgl_message_action_request_key); PyModule_AddIntConstant(m, "ACTION_ACCEPT_KEY", tgl_message_action_accept_key); } void py_add_peer_type_enums(PyObject *m) { PyModule_AddIntConstant(m, "PEER_USER", TGL_PEER_USER); PyModule_AddIntConstant(m, "PEER_CHAT", TGL_PEER_CHAT); PyModule_AddIntConstant(m, "PEER_ENCR_CHAT", TGL_PEER_ENCR_CHAT); } MOD_INIT(tgl) { PyObject *m; MOD_DEF(m, "tgl", NULL, py_tgl_methods) if (m == NULL) return MOD_ERROR_VAL; py_add_action_enums(m); py_add_peer_type_enums(m); if (PyType_Ready(&tgl_PeerType) < 0) return MOD_ERROR_VAL; Py_INCREF(&tgl_PeerType); PyModule_AddObject(m, "Peer", (PyObject *)&tgl_PeerType); if (PyType_Ready(&tgl_MsgType) < 0) return MOD_ERROR_VAL; Py_INCREF(&tgl_MsgType); PyModule_AddObject(m, "Msg", (PyObject *)&tgl_MsgType); TglError = PyErr_NewException("tgl.Error", NULL, NULL); Py_INCREF(TglError); PyModule_AddObject(m, "TglError", TglError); PeerError = PyErr_NewException("tgl.PeerError", NULL, NULL); Py_INCREF(PeerError); PyModule_AddObject(m, "PeerError", PeerError); MsgError = PyErr_NewException("tgl.MsgError", NULL, NULL); Py_INCREF(MsgError); PyModule_AddObject(m, "MsgError", MsgError); return MOD_SUCCESS_VAL(m); } void py_init (const char *file) { if (!file) { return; } python_loaded = 0; PyObject *pModule; // Get a copy of the filename for dirname/basename, which may modify the string, and break const correctness char filename[1024]; strncpy(filename, file, 1024); #if PY_MAJOR_VERSION >= 3 PyImport_AppendInittab("tgl", &PyInit_tgl); Py_Initialize(); #else Py_Initialize(); inittgl(); #endif PyObject* sysPath = PySys_GetObject((char*)"path"); PyList_Append(sysPath, PyUnicode_FromString(dirname(filename))); // Recopy the string in, since dirname modified it. strncpy(filename, file, 1024); // remove .py extension from file, if any char* dot = strrchr(filename, '.'); if (dot && strcmp(dot, ".py") == 0) *dot = 0; pModule = PyImport_Import(PyUnicode_FromString(basename(filename))); if(pModule == NULL || PyErr_Occurred()) { // Error loading script logprintf("Failed to load python script\n"); PyErr_Print(); exit(1); } python_loaded = 1; PyDateTime_IMPORT; logprintf("Python Initialized\n"); } #endif ================================================ FILE: python-tg.h ================================================ /* This file is part of telegram-cli. Telegram-cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Telegram-cli 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 telegram-cli. If not, see . Copyright Vitaly Valtman 2013-2015 Copyright Vincent Castellano 2015 */ #ifndef __PYTHON_TG_H__ #define __PYTHON_TG_H__ #include #include #include // Python functions void py_init (const char *file); void py_new_msg (struct tgl_message *M); void py_our_id (int id); void py_secret_chat_update (struct tgl_secret_chat *U, unsigned flags); void py_user_update (struct tgl_user *U, unsigned flags); void py_chat_update (struct tgl_chat *C, unsigned flags); void py_binlog_end (void); void py_diff_end (void); void py_do_all (void); // Binding functions PyObject* py_contact_list(PyObject *self, PyObject *args); PyObject* py_dialog_list(PyObject *self, PyObject *args); PyObject* py_rename_chat(PyObject *self, PyObject *args); PyObject* py_send_msg(PyObject *self, PyObject *args); PyObject* py_send_typing(PyObject *self, PyObject *args); PyObject* py_send_typing_abort(PyObject *self, PyObject *args); PyObject* py_send_photo(PyObject *self, PyObject *args); PyObject* py_send_video(PyObject *self, PyObject *args); PyObject* py_send_audio(PyObject *self, PyObject *args); PyObject* py_send_document(PyObject *self, PyObject *args); PyObject* py_send_file(PyObject *self, PyObject *args); PyObject* py_send_text(PyObject *self, PyObject *args); PyObject* py_chat_set_photo(PyObject *self, PyObject *args); PyObject* py_load_photo(PyObject *self, PyObject *args); PyObject* py_load_video(PyObject *self, PyObject *args); PyObject* py_load_video_thumb(PyObject *self, PyObject *args); PyObject* py_load_audio(PyObject *self, PyObject *args); PyObject* py_load_document(PyObject *self, PyObject *args); PyObject* py_load_document_thumb(PyObject *self, PyObject *args); PyObject* py_fwd(PyObject *self, PyObject *args); PyObject* py_fwd_media(PyObject *self, PyObject *args); PyObject* py_chat_info(PyObject *self, PyObject *args); PyObject* py_user_info(PyObject *self, PyObject *args); PyObject* py_history(PyObject *self, PyObject *args); PyObject* py_chat_add_user(PyObject *self, PyObject *args); PyObject* py_chat_del_user(PyObject *self, PyObject *args); PyObject* py_add_contact(PyObject *self, PyObject *args); PyObject* py_del_contact(PyObject *self, PyObject *args); PyObject* py_rename_contact(PyObject *self, PyObject *args); PyObject* py_search(PyObject *self, PyObject *args); PyObject* py_global_search(PyObject *self, PyObject *args); PyObject* py_mark_read(PyObject *self, PyObject *args); PyObject* py_set_profile_photo(PyObject *self, PyObject *args); PyObject* py_set_profile_name(PyObject *self, PyObject *args); PyObject* py_create_secret_chat(PyObject *self, PyObject *args); PyObject* py_create_group_chat(PyObject *self, PyObject *args); PyObject* py_delete_msg(PyObject *self, PyObject *args); PyObject* py_restore_msg(PyObject *self, PyObject *args); PyObject* py_accept_secret_chat(PyObject *self, PyObject *args); PyObject* py_send_contact(PyObject *self, PyObject *args); PyObject* py_status_online(PyObject *self, PyObject *args); PyObject* py_status_offline(PyObject *self, PyObject *args); PyObject* py_send_location(PyObject *self, PyObject *args); PyObject* py_extf(PyObject *self, PyObject *args); // Util Functions void py_add_string_field (PyObject* dict, char *name, const char *value); void py_add_string_field_arr (PyObject* list, int num, const char *value); void py_add_num_field (PyObject* dict, const char *name, double value); #endif ================================================ FILE: python-types.c ================================================ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef USE_PYTHON #include #include #include #include #include #include #include "structmember.h" // Python Imports #include "datetime.h" #include "python-types.h" #include "python-tg.h" extern struct tgl_state *TLS; // TGL Python Exceptions extern PyObject *TglError; extern PyObject *PeerError; extern PyObject *MsgError; // Forward type declarations PyTypeObject tgl_PeerType; // Utility functions PyObject* get_datetime(long datetime) { return PyDateTime_FromTimestamp(Py_BuildValue("(O)", PyLong_FromLong(datetime))); } // // tgl_peer_t wrapper // static void tgl_Peer_dealloc(tgl_Peer* self) { Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject * tgl_Peer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { tgl_Peer *self; PyDateTime_IMPORT; self = (tgl_Peer *)type->tp_alloc(type, 0); return (PyObject *)self; } static int tgl_Peer_init(tgl_Peer *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"type", "id", NULL}; tgl_peer_id_t peer_id; if(!PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwlist, &peer_id.type, &peer_id.id)) { PyErr_Format(PeerError, "Peer must specify type and id"); return -1; } self->peer = tgl_peer_get(TLS, peer_id); if(self->peer == NULL) return -1; return 0; } static PyObject * tgl_Peer_getname (tgl_Peer *self, void *closure) { PyObject *ret; switch(self->peer->id.type) { case TGL_PEER_USER: ret = PyUnicode_FromString(self->peer->user.print_name); break; case TGL_PEER_CHAT: ret = PyUnicode_FromString(self->peer->chat.print_title); break; case TGL_PEER_ENCR_CHAT: ret = PyUnicode_FromString(self->peer->encr_chat.print_name); break; default: PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Peer_getuser_id (tgl_Peer *self, void *closure) { PyObject *ret; switch(self->peer->id.type) { case TGL_PEER_USER: ret = PyLong_FromLong(self->peer->id.id); break; case TGL_PEER_CHAT: PyErr_SetString(PeerError, "peer.type_name == 'chat' has no user_id"); Py_RETURN_NONE; break; case TGL_PEER_ENCR_CHAT: ret = PyLong_FromLong(self->peer->encr_chat.user_id); break; default: PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Peer_getuser_list (tgl_Peer *self, void *closure) { PyObject *ret; int i; struct tgl_chat_user *user_list; switch(self->peer->id.type) { case TGL_PEER_CHAT: ret = PyList_New(0); for(i = 0; i < self->peer->chat.user_list_size; i++) { // TODO: Sort tgl_user objects, maybe offline mode is enoug? user_list = self->peer->chat.user_list + i; PyList_Append(ret, PyLong_FromLong(user_list->user_id)); } break; case TGL_PEER_ENCR_CHAT: case TGL_PEER_USER: PyErr_SetString(PeerError, "Only peer.type_name == 'chat' has user_list"); Py_RETURN_NONE; break; default: PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Peer_getuser_status(tgl_Peer *self, void *closure) { PyObject *ret; switch(self->peer->id.type) { case TGL_PEER_USER: ret = PyDict_New(); PyDict_SetItemString(ret, "online", self->peer->user.status.online? Py_True : Py_False); PyDict_SetItemString(ret, "when", get_datetime(self->peer->user.status.when)); break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: PyErr_SetString(PeerError, "Only peer.type_name == 'user' has user_status"); Py_RETURN_NONE; break; default: PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Peer_getphone (tgl_Peer *self, void *closure) { PyObject *ret; switch(self->peer->id.type) { case TGL_PEER_USER: if(self->peer->user.phone) ret = PyUnicode_FromString(self->peer->user.phone); else Py_RETURN_NONE; break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: PyErr_SetString(PeerError, "Only peer.type_name == 'user' has phone"); Py_RETURN_NONE; break; default: PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Peer_getusername (tgl_Peer *self, void *closure) { PyObject *ret; switch(self->peer->id.type) { case TGL_PEER_USER: if(self->peer->user.username) ret = PyUnicode_FromString(self->peer->user.username); else Py_RETURN_NONE; break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: PyErr_SetString(PeerError, "Only peer.type_name == 'user' has username"); Py_RETURN_NONE; break; default: PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Peer_getfirst_name (tgl_Peer *self, void *closure) { PyObject *ret; switch(self->peer->id.type) { case TGL_PEER_USER: if(self->peer->user.first_name) ret = PyUnicode_FromString(self->peer->user.first_name); else Py_RETURN_NONE; break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: PyErr_SetString(PeerError, "Only peer.type_name == 'user' has first_name"); Py_RETURN_NONE; break; default: PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Peer_getlast_name (tgl_Peer *self, void *closure) { PyObject *ret; switch(self->peer->id.type) { case TGL_PEER_USER: if(self->peer->user.last_name) ret = PyUnicode_FromString(self->peer->user.last_name); else Py_RETURN_NONE; break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: PyErr_SetString(PeerError, "Only peer.type_name == 'user' has last_name"); Py_RETURN_NONE; break; default: PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Peer_getuser (tgl_Peer *self, void *closure) { PyObject *ret; switch(self->peer->id.type) { case TGL_PEER_ENCR_CHAT: ret = tgl_Peer_FromTglPeer(tgl_peer_get(TLS, TGL_MK_USER (self->peer->encr_chat.user_id))); break; case TGL_PEER_USER: ret = (PyObject*)self; break; case TGL_PEER_CHAT: PyErr_SetString(PeerError, "Only peer.type_name == 'chat' does not have user"); Py_RETURN_NONE; break; default: PyErr_SetString(PeerError, "peer.type_name not supported!"); Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Peer_gettype_name(tgl_Peer* self) { PyObject *name; switch(self->peer->id.type) { case TGL_PEER_USER: name = PyUnicode_FromString("user"); break; case TGL_PEER_CHAT: name = PyUnicode_FromString("chat"); break; case TGL_PEER_ENCR_CHAT: name = PyUnicode_FromString("secret_chat"); break; default: name = PyUnicode_FromString("unknown"); } return name; } static PyObject * tgl_Peer_getid (tgl_Peer *self, void *closure) { PyObject *ret; ret = PyLong_FromLong(self->peer->id.id); Py_XINCREF(ret); return ret; } static PyObject * tgl_Peer_gettype (tgl_Peer *self, void *closure) { PyObject *ret; ret = PyLong_FromLong(self->peer->id.type); Py_XINCREF(ret); return ret; } static PyGetSetDef tgl_Peer_getseters[] = { {"id", (getter)tgl_Peer_getid, NULL, "", NULL}, {"type", (getter)tgl_Peer_gettype, NULL, "", NULL}, {"type_name", (getter)tgl_Peer_gettype_name, NULL, "", NULL}, {"name", (getter)tgl_Peer_getname, NULL, "", NULL}, {"user_id", (getter)tgl_Peer_getuser_id, NULL, "", NULL}, {"user", (getter)tgl_Peer_getuser, NULL, "", NULL}, {"user_list", (getter)tgl_Peer_getuser_list, NULL, "", NULL}, {"user_status", (getter)tgl_Peer_getuser_status, NULL, "", NULL}, {"phone", (getter)tgl_Peer_getphone, NULL, "", NULL}, {"username", (getter)tgl_Peer_getusername, NULL, "", NULL}, {"first_name", (getter)tgl_Peer_getfirst_name, NULL, "", NULL}, {"last_name", (getter)tgl_Peer_getlast_name, NULL, "", NULL}, {NULL} /* Sentinel */ }; static PyMemberDef tgl_Peer_members[] = { {NULL} /* Sentinel */ }; static PyObject * tgl_Peer_send_msg (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"message", "callback", "preview", "reply", NULL}; char *message; int preview = -1; int reply = 0; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|Opi", kwlist, &message, &callback, &preview, &reply)) { PyObject *api_call; PyObject *flags; flags = Py_BuildValue("(ii)", preview, reply); if(callback) api_call = Py_BuildValue("OsOO", (PyObject*) self, message, callback, flags); else api_call = Py_BuildValue("OsOO", (PyObject*) self, message, Py_None, flags); Py_INCREF(Py_None); Py_XINCREF(api_call); Py_XINCREF(flags); return py_send_msg(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_fwd_msg (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"callback", NULL}; int fwd_id = 0; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "i|O", kwlist, &fwd_id, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OiO", (PyObject*) self, fwd_id, callback); else api_call = Py_BuildValue("Oi", (PyObject*) self, fwd_id); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_fwd(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_send_typing (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"callback", NULL}; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OO", (PyObject*) self, callback); else api_call = Py_BuildValue("O", (PyObject*) self); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_send_typing(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_send_typing_abort (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"callback", NULL}; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OO", (PyObject*) self, callback); else api_call = Py_BuildValue("O", (PyObject*) self); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_send_typing_abort(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_rename_chat (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"title", "callback", NULL}; char * title; PyObject *callback = NULL; if(self->peer->id.type != TGL_PEER_CHAT) { PyErr_SetString(PeerError, "Only a chat peer can be renamed"); Py_XINCREF(Py_False); return Py_False; } if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &title, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OsO", (PyObject*) self, title, callback); else api_call = Py_BuildValue("Os", (PyObject*) self, title); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_rename_chat(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_send_photo (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"filename", "callback", NULL}; char *filename; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &filename, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OsO", (PyObject*) self, filename, callback); else api_call = Py_BuildValue("Os", (PyObject*) self, filename); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_send_photo(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_send_video (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"filename", "callback", NULL}; char *filename; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &filename, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OsO", (PyObject*) self, filename, callback); else api_call = Py_BuildValue("Os", (PyObject*) self, filename); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_send_video(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_send_audio (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"filename", "callback", NULL}; char *filename; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &filename, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OsO", (PyObject*) self, filename, callback); else api_call = Py_BuildValue("Os", (PyObject*) self, filename); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_send_audio(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_send_document (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"filename", "callback", NULL}; char *filename; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &filename, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OsO", (PyObject*) self, filename, callback); else api_call = Py_BuildValue("Os", (PyObject*) self, filename); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_send_document(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_send_file (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"filename", "callback", NULL}; char *filename; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &filename, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OsO", (PyObject*) self, filename, callback); else api_call = Py_BuildValue("Os", (PyObject*) self, filename); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_send_file(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_send_text (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"filename", "callback", NULL}; char *filename; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &filename, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OsO", (PyObject*) self, filename, callback); else api_call = Py_BuildValue("Os", (PyObject*) self, filename); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_send_text(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_chat_set_photo (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"filename", "callback", NULL}; char * filename; PyObject *callback = NULL; if(self->peer->id.type != TGL_PEER_CHAT) { PyErr_SetString(PeerError, "Only a chat peer can have a chat photo set."); Py_XINCREF(Py_False); return Py_False; } if(PyArg_ParseTupleAndKeywords(args, kwargs, "s|O", kwlist, &filename, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OsO", (PyObject*) self, filename, callback); else api_call = Py_BuildValue("Os", (PyObject*) self, filename); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_chat_set_photo(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_chat_add_user (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"peer", "callback", NULL}; PyObject *peer; PyObject *callback = NULL; if(self->peer->id.type != TGL_PEER_CHAT) { PyErr_SetString(PeerError, "Only a chat peer can have a user added."); Py_XINCREF(Py_False); return Py_False; } if(PyArg_ParseTupleAndKeywords(args, kwargs, "O!|O", kwlist, &tgl_PeerType, &peer, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OOO", (PyObject*) self, peer, callback); else api_call = Py_BuildValue("OO", (PyObject*) self, peer); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_chat_add_user(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_chat_del_user (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"peer", "callback", NULL}; PyObject *peer; PyObject *callback = NULL; if(self->peer->id.type != TGL_PEER_CHAT) { PyErr_SetString(PeerError, "Only a chat peer can have a user deleted."); Py_XINCREF(Py_False); return Py_False; } if(PyArg_ParseTupleAndKeywords(args, kwargs, "O!|O", kwlist, &tgl_PeerType, &peer, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OOO", (PyObject*) self, peer, callback); else api_call = Py_BuildValue("OO", (PyObject*) self, peer); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_chat_del_user(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_history (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"offset", "limit", "callback", NULL}; int offset, limit; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "ii|O", kwlist, &offset, &limit, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OiiO", (PyObject*) self, offset, limit, callback); else api_call = Py_BuildValue("Oii", (PyObject*) self, offset, limit); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_history(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_info (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"callback", NULL}; PyObject *callback = NULL; if(self->peer->id.type == TGL_PEER_ENCR_CHAT) { PyErr_SetString(PeerError, "Secret chats currently have no info."); Py_XINCREF(Py_False); return Py_False; } if(PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OO", (PyObject*) self, callback); else api_call = Py_None; Py_INCREF(Py_None); Py_XINCREF(api_call); if(self->peer->id.type == TGL_PEER_USER) return py_user_info(Py_None, api_call); else return py_chat_info(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_send_contact (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"phone", "first_name", "last_name", "callback", NULL}; char *phone, *first_name, *last_name; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "sss|O", kwlist, &phone, &first_name, &last_name, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("Osss", (PyObject*) self, phone, first_name, last_name, callback); else api_call = Py_BuildValue("Os", (PyObject*) self, phone, first_name, last_name); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_send_contact(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_send_location (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"latitude", "longitude", "callback", NULL}; PyObject *latitude, *longitude; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "O!O!|O", kwlist, &PyFloat_Type, &latitude, &PyFloat_Type, &longitude, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OOOO", (PyObject*) self, latitude, longitude, callback); else api_call = Py_BuildValue("OOO", (PyObject*) self, latitude, longitude); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_send_location(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Peer_mark_read (tgl_Peer *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"callback", NULL}; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &callback)) { PyObject *api_call; if(callback) api_call = Py_BuildValue("OO", (PyObject*) self, callback); else api_call = Py_BuildValue("O", (PyObject*) self); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_mark_read(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyMethodDef tgl_Peer_methods[] = { {"send_msg", (PyCFunction)tgl_Peer_send_msg, METH_VARARGS | METH_KEYWORDS, "Send a message to peer object"}, {"send_typing", (PyCFunction)tgl_Peer_send_typing, METH_VARARGS | METH_KEYWORDS, ""}, {"send_typing_abort", (PyCFunction)tgl_Peer_send_typing_abort, METH_VARARGS | METH_KEYWORDS, ""}, {"rename_chat", (PyCFunction)tgl_Peer_rename_chat, METH_VARARGS | METH_KEYWORDS, ""}, {"send_photo", (PyCFunction)tgl_Peer_send_photo, METH_VARARGS | METH_KEYWORDS, ""}, {"send_video", (PyCFunction)tgl_Peer_send_video, METH_VARARGS | METH_KEYWORDS, ""}, {"send_audio", (PyCFunction)tgl_Peer_send_audio, METH_VARARGS | METH_KEYWORDS, ""}, {"send_file", (PyCFunction)tgl_Peer_send_file, METH_VARARGS | METH_KEYWORDS, ""}, {"send_document", (PyCFunction)tgl_Peer_send_document, METH_VARARGS | METH_KEYWORDS, ""}, {"send_text", (PyCFunction)tgl_Peer_send_text, METH_VARARGS | METH_KEYWORDS, ""}, {"chat_set_photo", (PyCFunction)tgl_Peer_chat_set_photo, METH_VARARGS | METH_KEYWORDS, ""}, {"info", (PyCFunction)tgl_Peer_info, METH_VARARGS | METH_KEYWORDS, ""}, {"history", (PyCFunction)tgl_Peer_history, METH_VARARGS | METH_KEYWORDS, ""}, {"chat_add_user", (PyCFunction)tgl_Peer_chat_add_user, METH_VARARGS | METH_KEYWORDS, ""}, {"chat_del_user", (PyCFunction)tgl_Peer_chat_del_user, METH_VARARGS | METH_KEYWORDS, ""}, {"send_contact", (PyCFunction)tgl_Peer_send_contact, METH_VARARGS | METH_KEYWORDS, ""}, {"send_location", (PyCFunction)tgl_Peer_send_location, METH_VARARGS | METH_KEYWORDS, ""}, {"mark_read", (PyCFunction)tgl_Peer_mark_read, METH_VARARGS | METH_KEYWORDS, ""}, {"fwd_msg", (PyCFunction)tgl_Peer_fwd_msg, METH_VARARGS | METH_KEYWORDS, ""}, {NULL} /* Sentinel */ }; static PyObject * tgl_Peer_repr(tgl_Peer *self) { PyObject *ret; switch(self->peer->id.type) { case TGL_PEER_USER: #if PY_VERSION_HEX < 0x02070900 ret = PyUnicode_FromFormat("", self->peer->id.id); #else ret = PyUnicode_FromFormat("", self->peer->id.id, PyObject_GetAttrString((PyObject*)self, "username"), PyObject_GetAttrString((PyObject*)self, "name"), PyObject_GetAttrString((PyObject*)self, "first_name"), PyObject_GetAttrString((PyObject*)self, "last_name"), PyObject_GetAttrString((PyObject*)self, "phone") ); #endif break; case TGL_PEER_CHAT: ret = PyUnicode_FromFormat("", self->peer->id.id, self->peer->chat.print_title); break; case TGL_PEER_ENCR_CHAT: ret = PyUnicode_FromFormat("", self->peer->id.id, self->peer->encr_chat.print_name, PyObject_GetAttrString((PyObject*)self, "user")); break; default: ret = PyUnicode_FromFormat(""); } return ret; } int tgl_Peer_hash(PyObject *self) { return PyObject_Hash(PyObject_GetAttrString(self, "id")); } PyObject * tgl_Peer_RichCompare(PyObject *self, PyObject *other, int cmp) { PyObject *result = NULL; if(!PyObject_TypeCheck(other, &tgl_PeerType)) { result = Py_False; } else { if(((tgl_Peer*)self)->peer == NULL || ((tgl_Peer*)other)->peer == NULL) { result = Py_False; // If either object is not properly instantiated, compare is false } else { switch (cmp) { case Py_EQ: result = ((tgl_Peer*)self)->peer->id.id == ((tgl_Peer*)other)->peer->id.id ? Py_True : Py_False; break; case Py_NE: result = ((tgl_Peer*)self)->peer->id.id == ((tgl_Peer*)other)->peer->id.id ? Py_False : Py_True; break; case Py_LE: case Py_GE: case Py_GT: case Py_LT: default: return Py_INCREF(Py_NotImplemented), Py_NotImplemented; } } } Py_XINCREF(result); return result; } PyTypeObject tgl_PeerType = { PyVarObject_HEAD_INIT(NULL, 0) "tgl.Peer", /* tp_name */ sizeof(tgl_Peer), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)tgl_Peer_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc)tgl_Peer_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)tgl_Peer_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ "tgl Peer", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)tgl_Peer_RichCompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ tgl_Peer_methods, /* tp_methods */ tgl_Peer_members, /* tp_members */ tgl_Peer_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)tgl_Peer_init, /* tp_init */ 0, /* tp_alloc */ tgl_Peer_new, /* tp_new */ }; PyObject * tgl_Peer_FromTglPeer(tgl_peer_t *peer) { tgl_Peer *self = (tgl_Peer *) tgl_Peer_new((PyTypeObject *)&tgl_PeerType, Py_None, Py_None); self->peer = peer; return (PyObject *) self; } // // struct tgl_message wrapper // static void tgl_Msg_dealloc(tgl_Msg* self) { Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject * tgl_Msg_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { tgl_Msg *self; PyDateTime_IMPORT; self = (tgl_Msg *)type->tp_alloc(type, 0); return (PyObject *)self; } static int tgl_Msg_init(tgl_Msg *self, PyObject *args, PyObject *kwds) { PyErr_SetString(MsgError, "You cannot instantiate a tgl.Msg object, only the API can send them."); return -1; } static PyObject * tgl_Msg_getid (tgl_Msg *self, void *closure) { PyObject *ret; ret = PyLong_FromLong(self->msg->id); Py_XINCREF(ret); return ret; } static PyObject * tgl_Msg_getflags (tgl_Msg *self, void *closure) { PyObject *ret; ret = PyLong_FromLong(self->msg->flags); Py_XINCREF(ret); return ret; } static PyObject * tgl_Msg_getmention (tgl_Msg *self, void *closure) { PyObject *ret; ret = ((self->msg->flags & TGLMF_MENTION) ? Py_True : Py_False); Py_XINCREF(ret); return ret; } static PyObject * tgl_Msg_getout (tgl_Msg *self, void *closure) { PyObject *ret; ret = ((self->msg->flags & TGLMF_OUT) ? Py_True : Py_False); Py_XINCREF(ret); return ret; } static PyObject * tgl_Msg_getunread (tgl_Msg *self, void *closure) { PyObject *ret; ret = ((self->msg->flags & TGLMF_UNREAD) ? Py_True : Py_False); Py_XINCREF(ret); return ret; } static PyObject * tgl_Msg_getservice (tgl_Msg *self, void *closure) { PyObject *ret; ret = ((self->msg->flags & TGLMF_SERVICE) ? Py_True : Py_False); Py_XINCREF(ret); return ret; } static PyObject * tgl_Msg_getaction (tgl_Msg *self, void *closure) { PyObject *ret; ret = PyLong_FromLong(self->msg->action.type); Py_XINCREF(ret); return ret; } static PyObject * tgl_Msg_getsrc (tgl_Msg *self, void *closure) { PyObject *ret; if(tgl_get_peer_type (self->msg->from_id)) { tgl_peer_t *peer = tgl_peer_get (TLS, self->msg->from_id); if(peer) ret = tgl_Peer_FromTglPeer(peer); else { PyErr_SetString(PeerError, "Cannot Retrieve Peer. Internal tgl error"); Py_RETURN_NONE; } } else { Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Msg_getdest (tgl_Msg *self, void *closure) { PyObject *ret; if(tgl_get_peer_type (self->msg->to_id)) { tgl_peer_t *peer = tgl_peer_get (TLS, self->msg->to_id); if(peer) ret = tgl_Peer_FromTglPeer(peer); else { PyErr_SetString(PeerError, "Cannot Retrieve Peer. Internal tgl error"); Py_RETURN_NONE; } } else { Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Msg_gettext (tgl_Msg *self, void *closure) { PyObject *ret; if(self->msg->message_len && self->msg->message && !(self->msg->flags & TGLMF_SERVICE)) { ret = PyUnicode_FromStringAndSize(self->msg->message, self->msg->message_len); } else { Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Msg_getmedia (tgl_Msg *self, void *closure) { PyObject *ret; // TODO probably want a custom class for media, but it's not too important right now. if(self->msg->media.type && self->msg->media.type != tgl_message_media_none && !(self->msg->flags & TGLMF_SERVICE)) { ret = PyDict_New(); switch (self->msg->media.type) { case tgl_message_media_photo: py_add_string_field (ret, "type", "photo"); py_add_string_field (ret, "caption", self->msg->media.caption); break; case tgl_message_media_document: case tgl_message_media_document_encr: py_add_string_field (ret, "type", "document"); break; case tgl_message_media_unsupported: py_add_string_field (ret, "type", "unsupported"); break; case tgl_message_media_geo: py_add_string_field (ret, "type", "geo"); py_add_num_field (ret, "longitude", self->msg->media.geo.longitude); py_add_num_field (ret, "latitude", self->msg->media.geo.latitude); break; case tgl_message_media_contact: py_add_string_field (ret, "type", "contact"); py_add_string_field (ret, "phone", self->msg->media.phone); py_add_string_field (ret, "first_name", self->msg->media.first_name); py_add_string_field (ret, "last_name", self->msg->media.last_name); py_add_num_field (ret, "user_id", self->msg->media.user_id); break; case tgl_message_media_webpage: py_add_string_field (ret, "type", "webpage"); py_add_string_field (ret, "type", "webpage"); py_add_string_field (ret, "url", self->msg->media.webpage->url); py_add_string_field (ret, "title", self->msg->media.webpage->title); py_add_string_field (ret, "description", self->msg->media.webpage->description); py_add_string_field (ret, "author", self->msg->media.webpage->author); break; case tgl_message_media_venue: py_add_string_field (ret, "type", "venue"); py_add_num_field (ret, "longitude", self->msg->media.venue.geo.longitude); py_add_num_field (ret, "latitude", self->msg->media.venue.geo.latitude); py_add_string_field (ret, "title", self->msg->media.venue.title); py_add_string_field (ret, "address", self->msg->media.venue.address); py_add_string_field (ret, "provider", self->msg->media.venue.provider); py_add_string_field (ret, "venue_id", self->msg->media.venue.venue_id); break; default: py_add_string_field (ret, "type", "unknown"); } } else { Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Msg_getdate (tgl_Msg *self, void *closure) { PyObject *ret; if(self->msg->date) { ret = get_datetime(self->msg->date); } else { Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Msg_getfwd_src (tgl_Msg *self, void *closure) { PyObject *ret; if(tgl_get_peer_type (self->msg->fwd_from_id)) { tgl_peer_t *peer = tgl_peer_get (TLS, self->msg->fwd_from_id); if(peer) ret = tgl_Peer_FromTglPeer(peer); else { PyErr_SetString(PeerError, "Cannot Retrieve Peer. Internal tgl error"); Py_RETURN_NONE; } } else { Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Msg_getfwd_date (tgl_Msg *self, void *closure) { PyObject *ret; if(tgl_get_peer_type (self->msg->fwd_from_id)) { ret = get_datetime(self->msg->fwd_date); } else { Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Msg_getreply (tgl_Msg *self, void *closure) { PyObject *ret; if(self->msg->reply_id) { struct tgl_message *MR = tgl_message_get (TLS, self->msg->reply_id); if(MR) { ret = tgl_Msg_FromTglMsg(MR); } else { Py_RETURN_NONE; } } else { Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } static PyObject * tgl_Msg_getreply_id (tgl_Msg *self, void *closure) { PyObject *ret; if(self->msg->reply_id) { ret = PyLong_FromLong(self->msg->reply_id); } else { Py_RETURN_NONE; } Py_XINCREF(ret); return ret; } // All load methods are implemented the same, just alias load_document static PyObject * tgl_Msg_load_document (tgl_Msg *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"callback", NULL}; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &callback)) { PyObject *api_call; api_call = Py_BuildValue("OO", (PyObject*) self, callback); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_load_document(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Msg_load_document_thumb (tgl_Msg *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"callback", NULL}; PyObject *callback = NULL; if(PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &callback)) { PyObject *api_call; api_call = Py_BuildValue("OO", (PyObject*) self, callback); Py_INCREF(Py_None); Py_XINCREF(api_call); return py_load_document_thumb(Py_None, api_call); } else { PyErr_Print(); Py_XINCREF(Py_False); return Py_False; } } static PyObject * tgl_Msg_repr(tgl_Msg *self) { PyObject *ret; #if PY_VERSION_HEX < 0x02070900 ret = PyUnicode_FromFormat("", self->msg->id); #else ret = PyUnicode_FromFormat("", self->msg->id, self->msg->flags, PyObject_GetAttrString((PyObject*)self, "mention"), PyObject_GetAttrString((PyObject*)self, "out"), PyObject_GetAttrString((PyObject*)self, "unread"), PyObject_GetAttrString((PyObject*)self, "service"), PyObject_GetAttrString((PyObject*)self, "src"), PyObject_GetAttrString((PyObject*)self, "dest"), PyObject_GetAttrString((PyObject*)self, "text"), PyObject_GetAttrString((PyObject*)self, "media"), PyObject_GetAttrString((PyObject*)self, "date"), PyObject_GetAttrString((PyObject*)self, "fwd_src"), PyObject_GetAttrString((PyObject*)self, "fwd_date"), PyObject_GetAttrString((PyObject*)self, "reply_id"), PyObject_GetAttrString((PyObject*)self, "reply") ); #endif return ret; } static PyGetSetDef tgl_Msg_getseters[] = { {"id", (getter)tgl_Msg_getid, NULL, "", NULL}, {"flags", (getter)tgl_Msg_getflags, NULL, "", NULL}, {"mention", (getter)tgl_Msg_getmention, NULL, "", NULL}, {"out", (getter)tgl_Msg_getout, NULL, "", NULL}, {"unread", (getter)tgl_Msg_getunread, NULL, "", NULL}, {"service", (getter)tgl_Msg_getservice, NULL, "", NULL}, {"src", (getter)tgl_Msg_getsrc, NULL, "", NULL}, {"dest", (getter)tgl_Msg_getdest, NULL, "", NULL}, {"text", (getter)tgl_Msg_gettext, NULL, "", NULL}, {"media", (getter)tgl_Msg_getmedia, NULL, "", NULL}, {"date", (getter)tgl_Msg_getdate, NULL, "", NULL}, {"fwd_src", (getter)tgl_Msg_getfwd_src, NULL, "", NULL}, {"fwd_date", (getter)tgl_Msg_getfwd_date, NULL, "", NULL}, {"reply", (getter)tgl_Msg_getreply, NULL, "", NULL}, {"reply_id", (getter)tgl_Msg_getreply_id, NULL, "", NULL}, {"action", (getter)tgl_Msg_getaction, NULL, "", NULL}, {NULL} /* Sentinel */ }; static PyMemberDef tgl_Msg_members[] = { {NULL} /* Sentinel */ }; static PyMethodDef tgl_Msg_methods[] = { {"load_document", (PyCFunction)tgl_Msg_load_document, METH_VARARGS | METH_KEYWORDS, ""}, {"load_photo", (PyCFunction)tgl_Msg_load_document, METH_VARARGS | METH_KEYWORDS, ""}, {"load_audio", (PyCFunction)tgl_Msg_load_document, METH_VARARGS | METH_KEYWORDS, ""}, {"load_video", (PyCFunction)tgl_Msg_load_document, METH_VARARGS | METH_KEYWORDS, ""}, {"load_document_thumb", (PyCFunction)tgl_Msg_load_document_thumb, METH_VARARGS | METH_KEYWORDS, ""}, {"load_video_thumb", (PyCFunction)tgl_Msg_load_document_thumb, METH_VARARGS | METH_KEYWORDS, ""}, {NULL} /* Sentinel */ }; PyTypeObject tgl_MsgType = { PyVarObject_HEAD_INIT(NULL, 0) "tgl.Msg", /* tp_name */ sizeof(tgl_Msg), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)tgl_Msg_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc)tgl_Msg_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ "tgl Message", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ tgl_Msg_methods, /* tp_methods */ tgl_Msg_members, /* tp_members */ tgl_Msg_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)tgl_Msg_init, /* tp_init */ 0, /* tp_alloc */ tgl_Msg_new, /* tp_new */ }; PyObject * tgl_Msg_FromTglMsg(struct tgl_message *msg) { tgl_Msg *self = (tgl_Msg *) tgl_Msg_new((PyTypeObject *)&tgl_MsgType, Py_None, Py_None); self->msg = msg; return (PyObject *) self; } #endif ================================================ FILE: python-types.h ================================================ #ifndef __PYTHON_TYPES_H__ #define __PYTHON_TYPES_H__ #include #include typedef struct { PyObject_HEAD tgl_peer_t *peer; } tgl_Peer; typedef struct { PyObject_HEAD struct tgl_message *msg; } tgl_Msg; PyObject * tgl_Peer_FromTglPeer(tgl_peer_t *peer); PyObject * tgl_Msg_FromTglMsg(struct tgl_message *peer); #endif ================================================ FILE: server.pub ================================================ -----BEGIN RSA PUBLIC KEY----- MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6 lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+ 8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB -----END RSA PUBLIC KEY----- ================================================ FILE: start-telegram-daemon ================================================ #!/usr/bin/perl -w # start-engine # derived from start-memcached # 2003/2004 - Jay Bonci # This script handles the parsing of the /etc/memcached.conf file # and was originally created for the Debian distribution. # Anyone may use this little script under the same terms as # memcached itself. # a bit changed it for telegram-daemon to generate config before start (Vitaly Valtman) use POSIX qw(strftime); use strict; my $id = defined($ARGV[0]) ? $ARGV[0] : ''; my $idx = $id eq '' ? '' : " '$id'"; my $idl = ($id =~ /^\.(.*)$/ ? "-$1" : $id); my $root = ""; my $params; my $etchandle; my $etcfile = "$root/etc/telegram-daemon/telegram-daemon$id.conf"; # This script assumes that engine is located at /usr/bin/engine, and # that the pidfile is writable at /var/run/engine.pid my $engine_pfx = "$root/usr/share/telegram-daemon/bin/"; my $pidfile = "$root/var/run/telegram-daemon$id.pid"; # If we don't get a valid logfile parameter in the /etc/engine.conf file, # we'll just throw away all of our in-daemon output. We need to re-tie it so # that non-bash shells will not hang on logout. Thanks to Michael Renner for # the tip my $fd_reopened = "/dev/null"; $fd_reopened = "$root/var/log/telegram-daemon/telegram-daemon$idl.log" if -d "$root/var/log/telegram-daemon/"; sub handle_logfile { my ($logfile) = @_; $logfile = "$root/var/log/telegram-daemon/$logfile" unless $logfile =~ /\//; $fd_reopened = $logfile; } sub reopen_logfile { my ($logfile) = @_; open *STDERR, ">>$logfile"; open *STDOUT, ">>$logfile"; open *STDIN, ">>/dev/null"; chown 239, 239, $logfile; $fd_reopened = $logfile; } sub adjust_arg { my ($arg) = @_; if ($arg =~ /^newest:(.*)$/) { my @L = split /:/, $1; my $x = $arg; my $xt = 0; for my $y (@L) { my @S = stat($y); if (scalar @S && $S[9] > $xt) { $x = $y; $xt = $S[9]; } } return $x; } return $arg; } # This is set up in place here to support other non -[a-z] directives my $conf_directives = { "logfile" => \&handle_logfile, }; my %Vars = ( "execute" => "msg-search-engine", "work_dir" => "$root/var/lib/telegram-daemon" ); my $have_c = 0; my $have_l = 0; my $have_u = 0; my $have_aes = 0; if(open $etchandle, $etcfile) { foreach my $line (<$etchandle>) { $line ||= ""; $line =~ s/\#.*//g; $line =~ s/\s+$//g; $line =~ s/^\s+//g; next unless $line; next if $line =~ /^\-[h]/; if($line =~ /^[^\-]/) { my ($directive, $int, $arg) = $line =~ /^(.*?)(\s+|\s*=\s*)(.*)/; next unless $directive; if (exists $conf_directives->{$directive}) { $conf_directives->{$directive}->($arg); } else { $Vars{$directive} = $arg; } next; } $have_l = 1 if $line =~ /^-L\s/; $have_c = 1 if $line =~ /^-c\s/; $have_u = 1 if $line =~ /^-U\s/; push @$params, $line; } }else{ $params = []; } push @$params, "-U telegramd" unless($have_u); push @$params, "-L $fd_reopened" unless($have_l); push @$params, "-c config$idl" unless($have_c); $params = join " ", @$params; if(-e $pidfile) { open PIDHANDLE, "$pidfile"; my $localpid = ; close PIDHANDLE; if ($localpid && $localpid =~ /(\d+)/) { $localpid = $1; } else { $localpid = -1; } if (-d "/proc/$localpid") { print STDERR "telegram-daemon$idl is already running.\n"; exit; } else { print STDERR "removing stale $pidfile.\n"; `rm -f $pidfile`; } } if (exists $Vars{'quit'}) { print STDERR "telegram-daemon$idl disabled\n"; exit(0); } my $engine = $engine_pfx.$Vars{'execute'}; my $wdir = $Vars{'work_dir'}; chdir $wdir if -d $wdir; unless (-x $engine) { print STDERR "executable $engine not found\n"; exit(1); } unless (-d $wdir) { print STDERR "work directory $wdir not found\n"; exit(1); } for my $x ('s', 0 .. 9) { if (defined($Vars{"arg$x"})) { $params .= " ".adjust_arg($Vars{"arg$x"}); } } my $pid = fork(); if (!$pid) { reopen_logfile ($fd_reopened); chdir $wdir; open(my $fh, '>', "config$idl"); my $text = <<"END_MSG" config_directory="$wdir"; test=false; msg_num=true; binlog_enabled=true; binlog="binlog$idl.bin"; pfs_enabled=true; log_level = 0; lua_script="script$idl.lua"; END_MSG ; print $fh $text; close $fh; my $t; $t = strftime ("%Y-%m-%d %H:%M:%S %Z", localtime); print STDERR "[$t] invoking telegram-daemon$idl: $engine $params\n"; exec "$engine $params"; exit (0); } else { if (open PIDHANDLE,">$pidfile") { print PIDHANDLE $pid; close PIDHANDLE; } else { print STDERR "Can't write pidfile to $pidfile.\n"; } } ================================================ FILE: telegram-cli-cygwin.patch ================================================ Binary files tg/.git/index and tg-cygwin/.git/index differ diff -urN tg/Makefile tg-cygwin/Makefile --- tg/Makefile 2015-06-16 12:39:34.931053900 +0900 +++ tg-cygwin/Makefile 2015-06-16 12:44:12.584342300 +0900 @@ -4,9 +4,9 @@ LDFLAGS= -L/usr/local/lib -L/usr/lib -L/usr/lib -L/usr/lib CPPFLAGS= -I/usr/local/include -I/usr/include -I/usr/include -I/usr/include/python3.4m -I/usr/include DEFS=-DHAVE_CONFIG_H -COMPILE_FLAGS=${CFLAGS} ${CPFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Werror -Wextra -Wno-missing-field-initializers -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb -Wno-unused-parameter -fPIC +COMPILE_FLAGS=${CFLAGS} ${CPFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Werror -Wextra -Wno-missing-field-initializers -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb -Wno-unused-parameter EXTRA_LIBS=-ljansson -lconfig -lz -levent -lm -lreadline -llua-5.2 -lpython3.4m -lssl -lcrypto -LOCAL_LDFLAGS=-rdynamic -ggdb -levent ${EXTRA_LIBS} -ldl -lpthread -lutil +LOCAL_LDFLAGS=-ggdb -levent ${EXTRA_LIBS} -ldl -lpthread -lutil LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS} DEP=dep ================================================ FILE: telegram-cli.spec ================================================ Name: telegram-cli Version: Beta Release: 2%{?dist} Summary: Private fast and open platform for instant messaging Packager: Pablo Iranzo Gómez (Pablo.Iranzo@gmail.com) Group: Internet/Messaging License: GPL URL: https://github.com/vysheng/tg Source: master.zip BuildRequires: lua-devel, openssl-devel, libconfig-devel, readline-devel, wget #Requires: wget %description Telegram is an Open Source messaging platform for mobile, desktop focused on privacy. %prep [ -d %{name} ] && rm -Rfv %{name} mkdir %{name} cd %{name} wget -O master.zip https://github.com/vysheng/tg/archive/master.zip unzip master.zip cd tg-master ./configure make %{?_smp_mflags} %install cd %{name} cd tg-master %{__install} -D -m0755 telegram %{buildroot}/usr/bin/telegram %{__install} -D -m0644 tg-server.pub %{buildroot}/etc/telegram/server.pub %files /usr/bin/telegram /etc/telegram/server.pub %changelog * Tue Feb 4 2014 Pablo Iranzo Gómez (Pablo.Iranzo@gmail.com) - Add server key to /etc/telegram/ * Sat Feb 1 2014 Pablo Iranzo Gómez (Pablo.Iranzo@gmail.com) - Initial SPEC file ================================================ FILE: telegram-daemon ================================================ #!/bin/bash ### BEGIN INIT INFO # Provides: engine # Required-Start: $local_fs $syslog # Required-Stop: $local_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: KittenDB Meta Engine ### END INIT INFO # # run script for KittenDB Engine # author: kot # author: burunduk # author: burunduk # # Version: 2013-06-06 # # Features added: # -- flock to avoid parallel execution # -- checks to avoid creating empty engine configuration files # a bit changed it for telegram-daemon to use different folders # and to have posiiblilities to have fake root # Vitaly Valtman ROOT="" PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMONDIR=$ROOT/usr/share/telegram-daemon/bin DAEMONBOOTSTRAP=$ROOT/usr/share/telegram-daemon/bin/start-telegram-daemon NAME=telegram-daemon DESC="KOT's meta engine" PIDFILE=$ROOT/var/run/$NAME LOCKFILE=$ROOT/var/lock/$NAME CONFFILE=$ROOT/etc/telegram-daemon/$NAME LOCK_WAIT=5 STOP_TIMEOUT=5 KILL_TIMEOUT=5 test -x $DAEMONDIR || exit 0 test -x $DAEMONBOOTSTRAP || exit 0 set -e ## Utilitary functions # Send information to stderr function echo_stderr() { echo "$*" 1>&2 } # Get engine status. Returns 0 on running engine, 1 otherwise. function engine_status() { local id="$1" local pif="$PIDFILE.$id.pid" if ! [ -f "$pif" ] ; then echo "stopped" return 1 fi local pid="$(<$pif)" if [ -z "$pid" ]; then echo "corrupt pid file" return 1 fi if [ -d "/proc/$pid/" ]; then echo "$pid" return 0 else echo "failed (pid $pid)" return 1 fi } # Start engine. Usage: engine_start function engine_start() { local eid="$1" local r='' local pid='' pid="$(engine_status "$eid")" && r='ok' || r='fail' if [ "$r" == 'ok' ] ; then echo_stderr "telegram-daemon-$eid: already running ($pid)" else start-stop-daemon --start --quiet --exec $DAEMONBOOTSTRAP -- .$eid 100> /dev/null fi return 0 } # Stop engine. Usage: engine_stop function engine_stop() { local eid="$1" local r='' local status="$(engine_status "$eid")" && r='ok' || r='fail' local pif="$PIDFILE.$eid.pid" if [ "$r" == 'ok' ] ; then start-stop-daemon --stop --quiet --oknodo --pidfile "$pif" local ti=0 while [ $ti -lt $((10 * $STOP_TIMEOUT)) ] ; do status="$(engine_status "$eid")" && r='ok' || r='fail' if [ "$r" == 'fail' ]; then break fi sleep 0.1 ti=$(($ti + 1)) done if [ "$r" == 'ok' ] ; then echo_stderr "telegram-daemon-$eid: not stopped, sending SIGKILL..." start-stop-daemon --stop --quiet --oknodo --pidfile "$pif" --signal KILL ti=0 while [ $ti -lt $((10 * $KILL_TIMEOUT)) ] ; do status="$(engine_status "$eid")" && r='ok' || r='fail' if [ "$r" == 'fail' ]; then break fi sleep 0.1 ti=$(($ti + 1)) done fi if [ "$r" == 'ok' ] ; then echo_stderr "telegram-daemon-$eid: not stopped with SIGKILL, giving up" return 1 else if [ -f "$pif" ] ; then rm "$pif" fi echo "telegram-daemon-$eid: stopped" fi else echo_stderr "telegram-daemon-$eid: not running: $status" fi return 0 } # usage: engine_disable function engine_disable() { local eid="$1" local conf="$CONFFILE.$eid.conf" [ -e "$conf" ] || return 1 # work only with existing engines if grep -E '^quit 1$' "$conf" > /dev/null ; then echo_stderr "telegram-daemon-$eid: already disabled" else echo 'quit 1' >> "$conf" fi return 0 } # usage: engine_enable function engine_enable() { local eid="$1" local conf="$CONFFILE.$eid.conf" [ -e "$conf" ] || return 1 # work only with existing engines if ! grep -E '^quit' "$conf" > /dev/null ; then echo_stderr "telegram-daemon-$eid: already enabled" else sed -i~ -e '/^quit/d' -- "$conf" fi return 0 } # Wait for engine's command to be completed function engine_wait() { local eid="$1" ( flock -x -w $(($LOCK_WAIT + $STOP_TIMEOUT + $KILL_TIMEOUT)) 100 || exit 1 ) 100> $LOCKFILE.$eid.lock || echo "Unable to wait for $eid" return 0 } # Run a single command # Only one instance of this command per engine is supposed to work function run_one() { local eid="$1" shift local command="$*" [ "${#eid}" -gt 5 ] && return 0 # avoid long engine ids ( flock -x -w $LOCK_WAIT 100 || exit 1 $command "$eid" ) 100> $LOCKFILE.$eid.lock return 0 } # Run commands function run() { local mode="$1" shift local command="$*" local eid='' if [ "$mode" == 'parallel' ] ; then for eid in $arguments ; do run_one "$eid" "$command" & done sleep 0.1 for eid in $arguments ; do engine_wait "$eid" done else for eid in $arguments ; do run_one "$eid" "$command" done fi return 0 } # Get all actual engine ids function arguments_all() { local file='' local id='' local list='' for file in $(ls $CONFFILE.?*.conf 2> /dev/null) ; do id=${file#$CONFFILE.} id=${id%.conf} list="$list $id" done for file in $(ls $PIDFILE.?*.pid 2> /dev/null) ; do id=${file#$PIDFILE.} id=${id%.pid} list="$list $id" done local f='' for f in $list ; do echo "$f" ; done | sort -u return 0 } ## Commands # Start engine. function engine_command_start() { local eid="$1" engine_start "$eid" } # Stop engine. function engine_command_stop() { local eid="$1" engine_stop "$eid" } # Enable engine. function engine_command_enable() { local eid="$1" engine_enable "$eid" engine_start "$eid" } # Disable engine. function engine_command_disable() { local eid="$1" engine_disable "$eid" engine_stop "$eid" } # Restart engine. function engine_command_restart() { local eid="$1" engine_stop "$eid" echo "restarting telegram-daemon-$eid..." engine_start "$eid" } # Send signal to engine. Usage: engine_command_signal function engine_command_signal() { local id="$2" local signal="$1" local r='' local comment="$(engine_status "$id")" && r='ok' || r='fail' local res='' if [ "$r" == 'ok' ]; then start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE.$id.pid --signal "$signal" else echo_stderr "telegram-daemon-$id: not running: $comment" fi return 0 } # Get engine status function engine_command_status() { local id="$1" local res="telegram-daemon-$id: " local r='' local pid='' pid="$(engine_status "$id")" && r='ok' || r='fail' if [ "$r" == 'ok' ]; then res="$res $(COLUMNS=10000 ps -o pid,c,stime,time,cmd --no-header --pid $pid | sed -e 's/\/usr\/share\/telegram-daemon\/bin\///')" else res="$res $pid" fi echo "$res" return 0 } ## Entry point command="$1" shift arguments="$*" if [ -z "$arguments" ] ; then if [ "$command" == "status" -o "$command" == "start" -o "$command" == "rotate-logs" -o "$command" == "stop" ] ; then arguments="$(arguments_all)" fi elif [ "$arguments" == "all" ] ; then arguments="$(arguments_all)" fi if [ -z "$arguments" ] ; then echo "nothing to do" exit 0 fi case "$command" in ('disable') run parallel engine_command_disable ;; ('enable') run parallel engine_command_enable ;; # ('start') run parallel engine_command_start ;; ('status') run normal engine_command_status ;; ('stop') run parallel engine_command_stop ;; # ('rotate-logs') run parallel engine_command_signal USR1 ;; # ('restart'|'force-reload') run parallel engine_command_restart ;; (*) N=/etc/init.d/$NAME echo "Usage: $N {start|stop|restart|rotate-logs|status} [|all]" >&2 echo " additional commands: disable , enable , reindex (use with caution)" >&2 exit 1 ;; esac exit 0 ================================================ FILE: telegram.h ================================================ /* This file is part of telegram-cli. Telegram-cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Telegram-cli 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 telegram-cli. If not, see . Copyright Vitaly Valtman 2013-2015 */ #ifndef PROG_NAME #define PROG_NAME "telegram-cli" #endif #define TELEGRAM_CLI_VERSION "1.4.1" ================================================ FILE: test.lua ================================================ started = 0 our_id = 0 function vardump(value, depth, key) local linePrefix = "" local spaces = "" if key ~= nil then linePrefix = "["..key.."] = " end if depth == nil then depth = 0 else depth = depth + 1 for i=1, depth do spaces = spaces .. " " end end if type(value) == 'table' then mTable = getmetatable(value) if mTable == nil then print(spaces ..linePrefix.."(table) ") else print(spaces .."(metatable) ") value = mTable end for tableKey, tableValue in pairs(value) do vardump(tableValue, depth, tableKey) end elseif type(value) == 'function' or type(value) == 'thread' or type(value) == 'userdata' or value == nil then print(spaces..tostring(value)) else print(spaces..linePrefix.."("..type(value)..") "..tostring(value)) end end print ("HI, this is lua script") function ok_cb(extra, success, result) end -- Notification code {{{ function get_title (P, Q) if (Q.type == 'user') then return P.first_name .. " " .. P.last_name elseif (Q.type == 'chat') then return Q.title elseif (Q.type == 'encr_chat') then return 'Secret chat with ' .. P.first_name .. ' ' .. P.last_name else return '' end end local lgi = require ('lgi') local notify = lgi.require('Notify') notify.init ("Telegram updates") local icon = os.getenv("HOME") .. "/.telegram-cli/telegram-pics/telegram_64.png" function do_notify (user, msg) local n = notify.Notification.new(user, msg, icon) n:show () end -- }}} function on_msg_receive (msg) if started == 0 then return end if msg.out then return end do_notify (get_title (msg.from, msg.to), msg.text) if (msg.text == 'ping') then if (msg.to.id == our_id) then send_msg (msg.from.print_name, 'pong', ok_cb, false) else send_msg (msg.to.print_name, 'pong', ok_cb, false) end return end if (msg.text == 'PING') then if (msg.to.id == our_id) then fwd_msg (msg.from.print_name, msg.id, ok_cb, false) else fwd_msg (msg.to.print_name, msg.id, ok_cb, false) end return end end function on_our_id (id) our_id = id end function on_user_update (user, what) --vardump (user) end function on_chat_update (chat, what) --vardump (chat) end function on_secret_chat_update (schat, what) --vardump (schat) end function on_get_difference_end () end function cron() -- do something postpone (cron, false, 1.0) end function on_binlog_replay_end () started = 1 postpone (cron, false, 1.0) end ================================================ FILE: tg-server.pub ================================================ -----BEGIN RSA PUBLIC KEY----- MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6 lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+ 8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB -----END RSA PUBLIC KEY----- ================================================ FILE: tg-test.py ================================================ import tgl import pprint from functools import partial our_id = 0 pp = pprint.PrettyPrinter(indent=4) binlog_done = False; def on_binlog_replay_end(): binlog_done = True; def on_get_difference_end(): pass def on_our_id(id): our_id = id return "Set ID: " + str(our_id) def msg_cb(success, msg): pp.pprint(success) pp.pprint(msg) HISTORY_QUERY_SIZE = 100 def history_cb(msg_list, peer, success, msgs): print(len(msgs)) msg_list.extend(msgs) print(len(msg_list)) if len(msgs) == HISTORY_QUERY_SIZE: tgl.get_history(peer, len(msg_list), HISTORY_QUERY_SIZE, partial(history_cb, msg_list, peer)); def cb(success): print(success) def on_msg_receive(msg): if msg.out and not binlog_done: return; if msg.dest.id == our_id: # direct message peer = msg.src else: # chatroom peer = msg.dest pp.pprint(msg) if msg.text.startswith("!ping"): peer.send_msg("PONG! google.com", preview=False, reply=msg.id) def on_secret_chat_update(peer, types): return "on_secret_chat_update" def on_user_update(): pass def on_chat_update(): pass # Set callbacks tgl.set_on_binlog_replay_end(on_binlog_replay_end) tgl.set_on_get_difference_end(on_get_difference_end) tgl.set_on_our_id(on_our_id) tgl.set_on_msg_receive(on_msg_receive) tgl.set_on_secret_chat_update(on_secret_chat_update) tgl.set_on_user_update(on_user_update) tgl.set_on_chat_update(on_chat_update)