work/0000775000000000000000000000000013337271225006735 5ustar work/.gitignore0000664000000000000000000000120213337271225010720 0ustar *~ *.o *.lo .deps .libs src/sympathy.h src/sympathy.h.head sympathy.man src/libsympathy.a src/libsympathy.la apps/sympathy test/test test/xn libtool aclocal.m4 apps/Makefile apps/Makefile.in autom4te.cache config.log config.status configure ltmain.sh Makefile Makefile.in src/config.h src/config.h.in src/Makefile src/Makefile.in test/Makefile test/Makefile.in compile libsympathy-config libsympathy-config.src debian/files debian/*.substvars debian/*.debhelper.log debian/*.postinst.debhelper debian/*.postrm.debhelper debian/*.preinst.debhelper debian/*.prerm.debhelper debian/.debhelper debian/debhelper-build-stamp debian/sympathy work/AUTHORS0000664000000000000000000000014713337271225010007 0ustar AUTHORS: $Id: AUTHORS,v 1.2 2008/03/10 11:49:32 james Exp $ James McKenzie work/COPYING0000664000000000000000000006375313337271225010006 0ustar COPYING: Copyright (c) 2008 James McKenzie , GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 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. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, 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 and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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 with this License. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. 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 library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; 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. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! work/COPYING.emails0000664000000000000000000001215113337271225011241 0ustar Here is the email conversation containing the grant of licence from James McKenzie, the original author and principal copyrightholder: ============================================================ From: Ian Jackson To: [James McKenzie] Subject: Licence for sympathy Date: Thu, 6 Nov 2014 17:33:09 +0000 Hi. As you know we're using sympathy [ description of situation deleted -iwj ]. I would like to solve this problem by packaging it. I'd probably put it in Debian. What I absolutely need from you (or whoever is the copyright holder) is a licence statement. That could be as simple as saying `yes' to `please can I distribute sympathy and serialmgr under AGPLv3+' (or pick some less fierce licence). As a bonus, if you have an existing git history I should be using, it would be convenient for everyone if I could have a copy, or a copy of your CVS repo. But maybe you would need to launder your history for that. So in any case please don't let "this isn't the best version" stop you from giving permission. Thanks, Ian. ============================================================ From: [James McKenzie] To: Ian Jackson Subject: Re: Licence for sympathy Date: Thu, 06 Nov 2014 18:21:15 +0000 On 6 November 2014 17:33:09 GMT+00:00, Ian Jackson wrote: >[ quoted text deleted; see above for a copy -iwj ] gpl2 or lgpl please let me think which overnight also ill make an email addr fo\ r it ============================================================ From: Ian Jackson To: [James McKenzie] Subject: Re: Licence for sympathy Date: Fri, 7 Nov 2014 11:21:31 +0000 James writes ("Re: Licence for sympathy"): > gpl2 or lgpl please let me think which overnight also ill make an email addr \ for it Right. If you choose GPL can it please be GPL2+ rather than GPL2-only, since the latter lacks compatibility with lots of things... Anyway, I'll get to work on it. Thanks, Ian. ============================================================ From: [James McKenzie] To: Ian Jackson Subject: Re: Licence for sympathy Date: Fri, 07 Nov 2014 12:42:06 +0000 On 11/07/2014 11:21 AM, Ian Jackson wrote: > James writes ("Re: Licence for sympathy"): >> gpl2 or lgpl please let me think which overnight also ill make an email addr\ for it > > Right. If you choose GPL can it please be GPL2+ rather than > GPL2-only, since the latter lacks compatibility with lots of things... Right I'm loath to use GPL2+, as whilst the intentions are good I don't trust the politics, so lets go with LGPL (or even BSD) [ irrelevant personal communication paragraph deleted -iwj. ] J. ============================================================ From: Ian Jackson To: [James McKenzie] Subject: Re: Licence for sympathy Date: Fri, 7 Nov 2014 14:10:43 +0000 James writes ("Re: Licence for sympathy"): > Right I'm loath to use GPL2+, as whilst the intentions are good I don't > trust the politics, so lets go with LGPL (or even BSD) OK. I assume you mean LGPLv2.1+. But if you meant LGPLv3+ or LGPLv2.1-only or MIT (or 2-clause BSD) do say. I did a git-cvsimport on your anon-CVS. Would you like me to graft the thing I found on woking on the top of that, or would you like me to avoid publishing your CVS history more widely ? I'm dropping the DOCS directory because it looks like a bunch of samizdat. Very useful, but wouldn't get through copyright review for Debian NEW. [ irrelevant personal communication paragraphs deleted -iwj. ] Ian. ============================================================ From: Ian Jackson To: [James McKenzie] Subject: Re: Licence for sympathy Date: Wed, 12 Nov 2014 12:31:15 +0000 James writes ("Re: Licence for sympathy"): > sorry got waylaid yesterday will try and sort all this out today - where > did you intend to put the repository? github? I was going to use my own colo (and upload to Debian sid). But if you want a more shareish cloudy kind of repo, I'll use gitorious. (Free Software needs Free tools[1]) Do you want me to email you a link to a git branch for you to double-check, before I publish more widely ? Ian. [1] http://mako.cc/writing/hill-free_tools.html ============================================================ From: [James McKenzie] To: Ian Jackson Subject: Re: Licence for sympathy Date: Wed, 12 Nov 2014 12:41:40 +0000 On 12/11/14 12:31, Ian Jackson wrote: > James writes ("Re: Licence for sympathy"): >> sorry got waylaid yesterday will try and sort all this out today - where >> did you intend to put the repository? github? your repo is fine, I'll stick a copy in mine or we can just use mine. > I was going to use my own colo (and upload to Debian sid). But if you > want a more shareish cloudy kind of repo, I'll use gitorious. (Free > Software needs Free tools[1]) > > Do you want me to email you a link to a git branch for you to > double-check, before I publish more widely ? yes please did I say I'd made sympathy@madingley.org to take inbound email about it? J. work/ChangeLog0000664000000000000000000000073613337271225010515 0ustar ChangeLog: Copyright (c) 2008 James McKenzie , All rights reserved. $Id: ChangeLog,v 1.2 2008/03/11 18:21:03 james Exp $ 1.2.0: Added -I and -N options Added logging for client connexions Added sighup handling Fixed a race in -c -s mode where client would attempt to connect to server before server was ready Changed socket protocol so that -ls doesn't cause entire history and state to be placed in server's send buffer and then dumped. work/INSTALL0000664000000000000000000001763113337271225007776 0ustar # # # INSTALL: # # Copyright (c) 2008 James McKenzie , # All rights reserved. # # $Id: INSTALL,v 1.1 2008/02/03 16:20:23 james Exp $ # # $Log: INSTALL,v $ # Revision 1.1 2008/02/03 16:20:23 james # *** empty log message *** # # # # Basic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.in' is used to create `configure' by a program called `autoconf'. You only need `configure.in' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not supports the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' can not figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure' can figure that out, but if it prints a message saying it can not guess the host type, give it the `--host=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name with three fields: CPU-COMPANY-SYSTEM See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the host type. If you are building compiler tools for cross-compiling, you can also use the `--target=TYPE' option to select the type of system they will produce code for and the `--build=TYPE' option to select the type of system on which you are compiling the package. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Operation Controls ================== `configure' recognizes the following options to control how it operates. `--cache-file=FILE' Use and save the results of the tests in FILE instead of `./config.cache'. Set FILE to `/dev/null' to disable caching, for debugging `configure'. `--help' Print a summary of the options to `configure', and exit. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--version' Print the version of Autoconf used to generate the `configure' script, and exit. `configure' also accepts some other, not widely useful, options. work/Makefile.am0000664000000000000000000000474213337271225011000 0ustar # # # Makefile.am: # # Copyright (c) 2008 James McKenzie , # All rights reserved. # # $Id: Makefile.am,v 1.8 2008/02/28 22:55:27 staffcvs Exp $ # # $Log: Makefile.am,v $ # Revision 1.8 2008/02/28 22:55:27 staffcvs # *** empty log message *** # # Revision 1.7 2008/02/27 18:29:49 james # *** empty log message *** # # Revision 1.6 2008/02/27 16:01:24 james # *** empty log message *** # # Revision 1.5 2008/02/27 15:17:55 james # *** empty log message *** # # Revision 1.4 2008/02/27 15:04:32 james # *** empty log message *** # # Revision 1.3 2008/02/27 10:47:34 james # *** empty log message *** # # Revision 1.2 2008/02/24 00:42:52 james # *** empty log message *** # # Revision 1.1 2008/02/03 16:20:23 james # *** empty log message *** # # # # SUBDIRS=src apps test man1_MANS=sympathy.man bin_SCRIPTS = libsympathy-config clean-local: -rm -f libsympathy-config version.sed sympathy.man sympathy.man: sympathy.1 version.sed @SED@ -f version.sed < sympathy.1 > sympathy.man || rm -f sympathy.man libsympathy-config.src:libsympathy-config.src.in libsympathy-config:libsympathy-config.src version.sed @SED@ -f version.sed < libsympathy-config.src > libsympathy-config || rm -f libsympathy-config chmod +x $@ VFD=${srcdir} VF=${shell cat ${VFD}/version-files} VFS=${VF:%=${VFD}/%} VCHK=${shell cat ${VFS} | @MD5SUM@ | @AWK@ '{print $$1 }' } VNUM=${shell @GREP@ ${VCHK} ${VFD}/version-md5sums | @AWK@ '{ print $$2 }' } VSTP=${shell @GREP@ ${VCHK} ${VFD}/version-stamps | @AWK@ 'BEGIN { FS="\t" }; { print $$2 }' } VDEF=${shell echo `cat ${VFD}/version-major`.`cat ${VFD}/version-minor`.`cat ${VFD}/version-micro` } VSDF=${shell tail -1 ${VFD}/version-stamps | @AWK@ 'BEGIN { FS="\t" }; { print $$2 }' } EXTRA_DIST=version-files version-major version-minor version-micro version-md5sums version-stamps sympathy.1 version.sed: $(VFD)/version-files $(VFD)/version-major \ $(VFD)/version-minor $(VFD)/version-micro \ $(VFD)/version-md5sums $(VFD)/version-stamps ${VFS} if [ .${VNUM} = . ]; then \ echo "s/%VERSION%/${VDEF}-E/g" > version.sed; \ echo "s/%VERSIONSTAMP%/After ${VSDF}/g" >> version.sed; \ echo "s/%LONGVERSION%/Version ${VDEF} + Edits/g" >> version.sed; \ else \ echo "s/%VERSION%/${VNUM}/g" > version.sed; \ echo "s/%VERSIONSTAMP%/${VSTP}/g" >> version.sed; \ echo "s/%LONGVERSION%/Version ${VNUM}/g" >> version.sed; \ fi protos: (cd src && ${MAKE} protos) tidy: cvs commit -m "" (cd src && ${MAKE} tidy) (cd apps && ${MAKE} tidy) work/NEWS0000664000000000000000000000021613337271225007433 0ustar NEWS: Copyright (c) 2008 James McKenzie , All rights reserved. $Id: NEWS,v 1.2 2008/03/10 11:49:32 james Exp $ work/README0000664000000000000000000000266313337271225007624 0ustar Copyright (c) 2008 James McKenzie , All rights reserved. $Id: README,v 1.2 2008/03/10 11:49:32 james Exp $ Sympathy is a replacement for screen(1), minicom(1) and consolidate(1). It is a VT52/VT100/ANSI terminal emulator with some special features. In normal use sympathy would sit between a terminal device (a serial port or a pseudo-tty) and the user’s usual terminal emulator (eg xterm(1)). Sympathy renders data from the terminal device into an internal frame buffer and then expresses changes in this frame buffer to the outer terminal emulator using a small subset of ANSI escape codes. Sympathy always generates valid escape codes to the outer ter- minal, and will reset the state of its internal terminal emulator when it detects receive errors on the terminal device. Sympathy, unlike screen(1), takes care to preserve the scroll-back fea- tures of the outer terminal emulator: lines that scroll off the top of the internal frame buffer are scrolled off the top of the outer termi- nal emulator. When sympathy is used in client/server mode, some history is added to the outer terminal emulator when the client connects. Sympathy also supports automatic baud-rate detection, and advanced log- ging features. Sympathy logs whenever any of the modem control lines change state, receive errors, and the contents of any line on the frame buffer as the cursor moves off it. work/apps/0000775000000000000000000000000013337271225007700 5ustar work/apps/Makefile.am0000664000000000000000000000257613337271225011746 0ustar # # Makefile.am: # # Copyright (c) 2008 James McKenzie , # All rights reserved. # # $Id: Makefile.am,v 1.12 2008/03/07 13:56:39 james Exp $ # # $Log: Makefile.am,v $ # Revision 1.12 2008/03/07 13:56:39 james # *** empty log message *** # # Revision 1.11 2008/02/24 00:42:53 james # *** empty log message *** # # Revision 1.10 2008/02/20 18:35:10 james # *** empty log message *** # # Revision 1.9 2008/02/20 18:33:37 james # *** empty log message *** # # Revision 1.8 2008/02/20 18:31:44 james # *** empty log message *** # # Revision 1.7 2008/02/16 01:30:56 james # *** empty log message *** # # Revision 1.6 2008/02/14 10:34:30 james # *** empty log message *** # # Revision 1.5 2008/02/14 02:46:44 james # *** empty log message *** # # Revision 1.4 2008/02/14 00:57:58 james # *** empty log message *** # # Revision 1.3 2008/02/13 18:05:06 james # *** empty log message *** # # Revision 1.2 2008/02/06 11:30:45 james # *** empty log message *** # # Revision 1.1 2008/02/03 16:20:24 james # *** empty log message *** # # # INCLUDES = -I$(srcdir)/../src bin_PROGRAMS = sympathy HDRS=clients.h mainloop.h SRCS=sympathy.c usage.c clients.c mainloop.c expand.c noinst_HEADERS=${HDRS} sympathy_SOURCES = ${SRCS} sympathy_LDADD = ../src/libsympathy.la -lutil tidy: ${SRCS} ${HDRS} indent -i2 -ts0 ${SRCS} ${HDRS} /bin/rm -f *~ AM_CFLAGS=-g -Werror work/apps/clients.c0000664000000000000000000001633513337271225011515 0ustar /* * clients.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: clients.c,v 1.25 2008/05/09 12:35:57 james Exp $"; /* * $Log: clients.c,v $ * Revision 1.25 2008/05/09 12:35:57 james * *** empty log message *** * * Revision 1.24 2008/03/11 17:56:04 james * *** empty log message *** * * Revision 1.23 2008/03/11 17:47:24 james * *** empty log message *** * * Revision 1.22 2008/03/07 14:16:44 james * *** empty log message *** * * Revision 1.21 2008/03/07 14:13:40 james * *** empty log message *** * * Revision 1.20 2008/03/07 13:56:39 james * *** empty log message *** * * Revision 1.19 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.18 2008/03/03 18:16:16 james * *** empty log message *** * * Revision 1.17 2008/03/03 18:15:19 james * *** empty log message *** * * Revision 1.16 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.15 2008/03/02 10:27:24 james * *** empty log message *** * * Revision 1.14 2008/02/28 16:57:51 james * *** empty log message *** * * Revision 1.13 2008/02/28 16:37:16 james * *** empty log message *** * * Revision 1.12 2008/02/28 12:12:24 james * *** empty log message *** * * Revision 1.11 2008/02/23 11:48:51 james * *** empty log message *** * * Revision 1.10 2008/02/22 17:06:59 james * *** empty log message *** * * Revision 1.9 2008/02/20 18:49:11 staffcvs * *** empty log message *** * * Revision 1.8 2008/02/20 18:31:44 james * *** empty log message *** * * Revision 1.7 2008/02/15 23:52:12 james * *** empty log message *** * * Revision 1.6 2008/02/15 03:32:07 james * *** empty log message *** * * Revision 1.5 2008/02/14 10:34:47 james * *** empty log message *** * * Revision 1.4 2008/02/14 10:34:30 james * *** empty log message *** * * Revision 1.3 2008/02/14 02:46:44 james * *** empty log message *** * * Revision 1.2 2008/02/14 00:57:58 james * *** empty log message *** * * Revision 1.1 2008/02/13 18:05:06 james * *** empty log message *** * */ #include #include #include #include #include #include #include "clients.h" void client_initialize (Client * c, Context * ctx) { send_history (ctx->h, c); send_vt102 (ctx->v, c); c->initialized = 1; } void client_execute_message (Client * client, IPC_Msg * m, Context * c) { switch (m->hdr.type) { case IPC_MSG_TYPE_NOOP: break; case IPC_MSG_TYPE_DEBUG: log_f (c->l, "", m->debug.msg); break; case IPC_MSG_TYPE_KEY: vt102_send (c, m->key.key); break; case IPC_MSG_TYPE_SETBAUD: tty_set_baud (c->t, m->setbaud.baud); tty_parse_reset (c); log_f (c->l, "", m->setbaud.baud); break; case IPC_MSG_TYPE_SENDBREAK: log_f (c->l, ""); tty_send_break (c->t); break; case IPC_MSG_TYPE_SETFLOW: log_f (c->l, "", m->setflow.flow ? "on" : "off"); tty_set_flow (c->t, m->setflow.flow); break; case IPC_MSG_TYPE_SETANSI: vt102_set_ansi (c->v, m->setansi.ansi); break; case IPC_MSG_TYPE_HANGUP: log_f (c->l, ""); tty_hangup (c->t); break; case IPC_MSG_TYPE_SETSIZE: vt102_resize (c, m->setsize.winsize); break; case IPC_MSG_TYPE_RESET: vt102_reset (c); break; case IPC_MSG_TYPE_INITIALIZE: client_initialize (client, c); break; case IPC_MSG_TYPE_KILLME: client->dead++; break; default: log_f (c->l, "", m->hdr.type); } } void client_free (Client * c) { if (c->s) socket_free (c->s); free (c); #if 0 fprintf (stderr, "Client at %p freed\n", c); #endif } Client * clients_new_client (Clients * cs, Socket * s, Context * ctx) { Client *c; c = (Client *) xmalloc (sizeof (Client)); c->initialized = 0; c->dead = 0; c->s = s; c->next = cs->head; cs->head = c; cs->n++; #if 0 fprintf (stderr, "Client at %p created\n", c); #endif log_f (ctx->l, "", c, cs->n); if (ipc_msg_send_debug (s, "new_client")) c->dead++; return c; } void clients_reap (Clients * cs, Context * ctx) { Client **p, *c; for (p = &cs->head; *p;) { Client *c = *p; if (c->dead) { *p = c->next; client_free (c); cs->n--; log_f (ctx->l, "", c, cs->n); } else { p = &(c->next); } } } Clients * clients_new (void) { Clients *ret = (Clients *) xmalloc (sizeof (Clients)); ret->n = 0; ret->head = NULL; return ret; } void clients_pre_select (Clients * cs, fd_set * rfds, fd_set * wfds) { Client *c; for (c = cs->head; c; c = c->next) { socket_pre_select (c->s, rfds, wfds); } } void clients_post_select (Clients * cs, Context * ctx, fd_set * rfds, fd_set * wfds) { Client *c; int deaded = 0; for (c = cs->head; c; c = c->next) { if (socket_post_select (c->s, rfds, wfds)) { c->dead++; deaded++; } if (c->s->msg) { client_execute_message (c, c->s->msg, ctx); socket_consume_msg (c->s); if (c->dead) deaded++; } } if (deaded) clients_reap (cs, ctx); } void clients_shutdown (Clients * cs, Context * ctx) { Client *c; for (c = cs->head; c; c = c->next) { c->dead++; } clients_reap (cs, ctx); } int send_status (Clients * cs, char *msg) { char mbuf[IPC_MAX_BUF + sizeof (IPC_Msg_status)]; IPC_Msg_status *m = (IPC_Msg_status *) mbuf; int len; Client *c; if (!msg) return 0; len = strlen (msg) + 1; if (!len) return 0; if (len > IPC_MAX_BUF) len = IPC_MAX_BUF; m->size = len + sizeof (IPC_Msg_status); m->type = IPC_MSG_TYPE_STATUS; strncpy (m->status, msg, IPC_MAX_BUF); m->status[IPC_MAX_BUF - 1] = 0; for (c = cs->head; c; c = c->next) { if (!c->dead && c->initialized) if (ipc_msg_send (c->s, (IPC_Msg *) m)) c->dead++; } return len; } int send_output (Clients * cs, void *buf, int len) { char mbuf[IPC_MAX_BUF + sizeof (IPC_Msg_term)]; IPC_Msg_term *m = (IPC_Msg_term *) mbuf; Client *c; if (!len) return 0; if (len > IPC_MAX_BUF) len = IPC_MAX_BUF; m->size = len + sizeof (IPC_Msg_term); m->type = IPC_MSG_TYPE_TERM; m->len = len; memcpy (m->term, buf, len); for (c = cs->head; c; c = c->next) { if (!c->dead && c->initialized) if (ipc_msg_send (c->s, (IPC_Msg *) m)) c->dead++; } return len; } void send_history (History * h, Client * c) { int rptr = h->wptr; HISTORY_INC (h, rptr); HISTORY_INC (h, rptr); while (rptr != h->wptr) { History_ent *l = &h->lines[rptr]; if (l->valid) { if (ipc_msg_send_history (c->s, l)) c->dead++; } HISTORY_INC (h, rptr); } } void send_vt102 (VT102 * v, Client * c) { if (ipc_msg_send_vt102 (c->s, v)) c->dead++; } work/apps/clients.h0000664000000000000000000000400113337271225011505 0ustar /* * clients.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: clients.h,v 1.12 2008/05/09 12:35:57 james Exp $ */ /* * $Log: clients.h,v $ * Revision 1.12 2008/05/09 12:35:57 james * *** empty log message *** * * Revision 1.11 2008/03/11 17:56:04 james * *** empty log message *** * * Revision 1.10 2008/03/11 17:47:24 james * *** empty log message *** * * Revision 1.9 2008/03/10 11:49:32 james * *** empty log message *** * * Revision 1.8 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.7 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.6 2008/03/02 10:27:24 james * *** empty log message *** * * Revision 1.5 2008/02/14 10:34:47 james * *** empty log message *** * * Revision 1.4 2008/02/14 10:34:30 james * *** empty log message *** * * Revision 1.3 2008/02/14 02:46:44 james * *** empty log message *** * * Revision 1.2 2008/02/14 00:57:58 james * *** empty log message *** * * Revision 1.1 2008/02/13 18:05:06 james * *** empty log message *** * */ #ifndef __CLIENTS_H__ #define __CLIENTS_H__ typedef struct Client_struct { struct Client_struct *next; int initialized; Socket *s; int dead; } Client; typedef struct { Client *head; int n; } Clients; /* clients.c */ extern void client_free (Client * c); extern Client *clients_new_client (Clients * cs, Socket * s, Context * ctx); extern void clients_reap (Clients * cs, Context * ctx); extern Clients *clients_new (void); extern void clients_pre_select (Clients * cs, fd_set * rfds, fd_set * wfds); extern void clients_post_select (Clients * cs, Context * ctx, fd_set * rfds, fd_set * wfds); extern void clients_shutdown (Clients * cs, Context * ctx); extern int send_output (Clients * cs, void *buf, int len); extern int send_status (Clients * cs, char *msg); extern void send_history (History * h, Client * c); extern void send_vt102 (VT102 * v, Client * c); #endif work/apps/expand.c0000664000000000000000000000640313337271225011326 0ustar /* * expand.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: expand.c,v 1.6 2008/03/11 17:56:04 james Exp $"; /* * $Log: expand.c,v $ * Revision 1.6 2008/03/11 17:56:04 james * *** empty log message *** * * Revision 1.5 2008/03/10 11:49:32 james * *** empty log message *** * * Revision 1.4 2008/03/07 14:19:29 staffcvs * *** empty log message *** * * Revision 1.3 2008/03/07 14:16:44 james * *** empty log message *** * * Revision 1.2 2008/03/07 14:13:40 james * *** empty log message *** * * Revision 1.1 2008/03/07 13:56:39 james * *** empty log message *** * */ #include #include static int xdigit_to_i (char c) { switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return c - '0'; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': return 0xa + (c - 'a'); case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': return 0xA + (c - 'A'); } return -1; } static int my_isxdigit (char c) { return (xdigit_to_i (c) == -1) ? 0 : 1; } static int my_isodigit (char c) { switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': return 1; } return 0; } static int octal (const char **in) { int o = 0; while (**in) { if (!my_isodigit (**in)) return o; o <<= 3; o += (*((*in)++)) - '0'; } return o; } static int hex (const char **in) { int x = 0; (*in)++; while (**in) { printf ("%c %d\n", **in, x); if (!my_isxdigit (**in)) return x; x <<= 4; x += xdigit_to_i (*((*in)++)); } return x; } char * expand (const char *in, int *len) { const char *iptr = in; int l; char *optr; char *ret; if (!in) return (char *) 0; l = strlen (in); optr = ret = malloc (l + 1); if (!ret) return ret; l = 0; while (*iptr) { if (*iptr == '\\') { iptr++; switch (*iptr) { case '\'': case '\"': case '\?': case '\\': *(optr++) = *(iptr++); l++; break; case 'a': *(optr++) = '\a'; l++; iptr++; break; case 'b': *(optr++) = '\b'; l++; iptr++; break; case 'f': *(optr++) = '\f'; l++; iptr++; break; case 'n': *(optr++) = '\n'; l++; iptr++; break; case 'r': *(optr++) = '\r'; l++; iptr++; break; case 't': *(optr++) = '\t'; l++; iptr++; break; case 'v': *(optr++) = '\v'; l++; iptr++; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': *(optr++) = octal (&iptr); l++; break; case 'x': *(optr++) = hex (&iptr); l++; break; default: *(optr++) = '\\'; l++; *(optr++) = *(iptr++); l++; } } else { *(optr++) = *(iptr++); l++; } } if (*len) *len = l; *(optr++) = 0; return ret; } work/apps/mainloop.c0000664000000000000000000003047213337271225011670 0ustar /* * mainloop.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: mainloop.c,v 1.33 2008/05/09 12:35:57 james Exp $"; /* * $Log: mainloop.c,v $ * Revision 1.33 2008/05/09 12:35:57 james * *** empty log message *** * * Revision 1.32 2008/03/11 17:56:50 james * *** empty log message *** * * Revision 1.31 2008/03/11 17:56:04 james * *** empty log message *** * * Revision 1.30 2008/03/11 17:47:24 james * *** empty log message *** * * Revision 1.29 2008/03/10 11:49:32 james * *** empty log message *** * * Revision 1.28 2008/03/07 13:56:39 james * *** empty log message *** * * Revision 1.27 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.26 2008/03/06 21:34:09 james * *** empty log message *** * * Revision 1.25 2008/03/06 21:33:02 james * *** empty log message *** * * Revision 1.24 2008/03/06 16:49:39 james * *** empty log message *** * * Revision 1.23 2008/03/06 16:49:05 james * *** empty log message *** * * Revision 1.22 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.21 2008/03/02 10:27:24 james * *** empty log message *** * * Revision 1.20 2008/02/28 16:57:51 james * *** empty log message *** * * Revision 1.19 2008/02/28 16:37:16 james * *** empty log message *** * * Revision 1.18 2008/02/28 11:27:48 james * *** empty log message *** * * Revision 1.17 2008/02/27 09:42:53 james * *** empty log message *** * * Revision 1.16 2008/02/27 09:42:21 james * *** empty log message *** * * Revision 1.15 2008/02/27 01:31:38 james * *** empty log message *** * * Revision 1.14 2008/02/27 01:31:14 james * *** empty log message *** * * Revision 1.13 2008/02/26 23:56:12 james * *** empty log message *** * * Revision 1.12 2008/02/26 23:23:16 james * *** empty log message *** * * Revision 1.11 2008/02/24 00:43:55 james * *** empty log message *** * * Revision 1.10 2008/02/23 13:05:57 staffcvs * *** empty log message *** * * Revision 1.9 2008/02/23 11:48:51 james * *** empty log message *** * * Revision 1.8 2008/02/22 23:39:30 james * *** empty log message *** * * Revision 1.7 2008/02/20 20:16:07 james * *** empty log message *** * * Revision 1.6 2008/02/20 19:44:37 james * @@ * * Revision 1.5 2008/02/20 18:31:44 james * *** empty log message *** * * Revision 1.4 2008/02/20 17:18:33 james * *** empty log message *** * * Revision 1.3 2008/02/20 02:11:35 james * *** empty log message *** * * Revision 1.2 2008/02/16 10:58:52 james * *** empty log message *** * * Revision 1.13 2008/02/15 23:52:12 james * *** empty log message *** * * Revision 1.12 2008/02/15 03:32:07 james * *** empty log message *** * * Revision 1.11 2008/02/14 16:21:17 james * *** empty log message *** * * Revision 1.10 2008/02/14 10:39:14 james * *** empty log message *** * * Revision 1.9 2008/02/14 10:34:47 james * *** empty log message *** * * Revision 1.8 2008/02/14 10:34:30 james * *** empty log message *** * * Revision 1.7 2008/02/14 02:46:44 james * *** empty log message *** * * Revision 1.6 2008/02/14 00:57:58 james * *** empty log message *** * * Revision 1.5 2008/02/13 18:05:06 james * *** empty log message *** * * Revision 1.4 2008/02/13 17:21:55 james * *** empty log message *** * * Revision 1.3 2008/02/08 15:06:52 james * *** empty log message *** * * Revision 1.2 2008/02/07 15:42:49 james * *** empty log message *** * * Revision 1.1 2008/02/05 14:25:49 james * *** empty log message *** * */ #include #include #include "mainloop.h" #include "clients.h" typedef struct { int nclients; int lines; int baud; int crtscts; int cd_edge_sec; int blocked; int bootstrap; } Status; static Status get_status (TTY * t, Clients * cs) { static struct timeval last_cd_edge = { 0 }; static int last_cd_state = -1; int cd; struct timeval now, dif; TTY_Status tty_status = { 0 }; Status status; tty_get_status (t, &tty_status); status.bootstrap = 1; if (cs) status.nclients = cs->n; else status.nclients = 0; status.lines = tty_status.lines; status.baud = tty_status.baud; status.crtscts = (tty_status.termios.c_cflag & CRTSCTS) ? 1 : 0; status.blocked = tty_status.blocked; cd = (tty_status.lines & TIOCM_CD) ? 1 : 0; if (cd != last_cd_state) { gettimeofday (&last_cd_edge, NULL); last_cd_state = cd; } gettimeofday (&now, NULL); timersub (&now, &last_cd_edge, &dif); status.cd_edge_sec = dif.tv_sec; return status; } static char * line_to_name (int l) { switch (l) { #ifdef TIOCM_LE case TIOCM_LE: return "LE"; #endif #ifdef TIOCM_DTR case TIOCM_DTR: return "DTR"; #endif #ifdef TIOCM_RTS case TIOCM_RTS: return "RTS"; #endif #ifdef TIOCM_ST case TIOCM_ST: return "ST"; #endif #ifdef TIOCM_SR case TIOCM_SR: return "SR"; #endif #ifdef TIOCM_CTS case TIOCM_CTS: return "CTS"; #endif #ifdef TIOCM_CD case TIOCM_CD: return "CD"; #endif #ifdef TIOCM_RI case TIOCM_RI: return "RI"; #endif #ifdef TIOCM_DSR case TIOCM_DSR: return "DSR"; #endif } return "??"; } static void log_line_changes (Context * ctx, int old, int new) { int dif = old ^ new; int c = 1; char buf[1024], *ptr = buf; char *n; if (!dif) return; if (!ctx->l) return; n = "= c) { if (dif & c) { *(ptr++) = ' '; *(ptr++) = (new & c) ? '+' : '-'; n = line_to_name (c); while (*n) *(ptr++) = *(n++); } c <<= 1; } *(ptr++) = '>'; *ptr = 0; ctx->l->log (ctx->l, buf); } static char * do_line (char *ptr, int lines, int line) { char *lname; if (!(lines & line)) return ptr; lname = line_to_name (line); *(ptr++) = ' '; while (*lname) *(ptr++) = *(lname++); return ptr; } static void check_status (Context * c, Clients * cs) { static Status old_status = { 0 }; Status status; char buf[1024]; char *ptr = buf; char *t; status = get_status (c->t, cs); if (!memcmp (&status, &old_status, sizeof (status))) return; log_line_changes (c, old_status.lines, status.lines); old_status = status; ptr += sprintf (ptr, "CTRL-B "); t = c->t->name; if (!strncmp (t, "/dev/", 5)) t += 5; while (*t) *(ptr++) = *(t++); ptr += sprintf (ptr, " %db", status.baud); ptr = do_line (ptr, status.lines, TIOCM_RTS); ptr = do_line (ptr, status.lines, TIOCM_CTS); ptr = do_line (ptr, status.lines, TIOCM_DTR); ptr = do_line (ptr, status.lines, TIOCM_DSR); ptr = do_line (ptr, status.lines, TIOCM_RI); ptr = do_line (ptr, status.lines, TIOCM_CD); if (status.blocked) { t = ", Locked"; while (*t) *(ptr++) = *(t++); } if (status.crtscts) { t = ", Flow"; while (*t) *(ptr++) = *(t++); } #if 0 if (status.lines & TIOCM_CD) { ptr += sprintf (ptr, ", On %d.%d", status.cd_edge_sec / 60, status.cd_edge_sec % 60); } else { ptr += sprintf (ptr, ", Off %d.%d", status.cd_edge_sec / 60, status.cd_edge_sec % 60); } #endif ptr += sprintf (ptr, ", %d client%s", status.nclients, (status.nclients == 1) ? "" : "s"); if (c->tp->biterrs) { ptr += sprintf (ptr, ", %d err%s", c->tp->biterrs, (c->tp->biterrs == 1) ? "" : "s"); if (c->tp->guessed_baud == -1) { ptr += sprintf (ptr, " try higher"); } else if (c->tp->guessed_baud > 0) { ptr += sprintf (ptr, " try %db", c->tp->guessed_baud); } } *ptr = 0; #if 0 log_f (c->l, "%s:%d %s", __FILE__, __LINE__, buf); #endif if (cs) send_status (cs, buf); else cmd_new_status (c->d, c, buf); } static int msg_from_server (ANSI * a, IPC_Msg * m, Context * c) { int err = 0; switch (m->hdr.type) { case IPC_MSG_TYPE_NOOP: break; case IPC_MSG_TYPE_DEBUG: // fprintf (stderr,"%p [%d] %s\n", m, m->hdr.size , m->debug.msg ); break; case IPC_MSG_TYPE_HISTORY: history_add (c->h, m->history.history.line); break; case IPC_MSG_TYPE_VT102: if (sizeof (VT102) != m->vt102.len) crash_out ("sizeof(VT102) differs in client and server"); *(c->v) = m->vt102.vt102; if (a->one_shot) { a->one_shot (a, &c->v->crt); err++; /* Simulate a fatal write error enclosing tty */ } break; case IPC_MSG_TYPE_TERM: err += tty_parse (c, m->term.term, m->term.len); break; case IPC_MSG_TYPE_STATUS: cmd_new_status (c->d, c, m->status.status); break; default: fprintf (stderr, "Unhandeled message type %d\n", m->hdr.type); } return err; } void mainloop (Context * c, ANSI * ansi, Socket * server_socket, Socket * client_socket) { fd_set rfds, wfds; Clients *clients; c->tp = tty_parser_new (); c->u = utf8_new (); /* are we being fed by a tty or a socket */ if (client_socket) { if (server_socket) crash_out ("mainloop cannot both be a server and a client"); c->k = keydis_ipc_new (client_socket); } else { if (!c->t) crash_out ("mainloop must have either a client_socket or a terminal"); c->k = keydis_vt102_new (); } /* do we have an upstream terminal to talk to */ /* if so start a command parser */ if (ansi) { c->d = cmd_new (); } else { c->d = NULL; } vt102_reset (c); if (server_socket) { if (client_socket) crash_out ("mainloop cannot both be a server and a client"); clients = clients_new (); } else { clients = NULL; } for (;;) { struct timeval tv = { 0, 250000 }; if ((c->d) && (c->d->disconnect)) break; /* update the status lines, locally or remotely */ if (c->t) check_status (c, clients); FD_ZERO (&rfds); FD_ZERO (&wfds); if (c->t) tty_pre_select (c->t, &rfds, &wfds); if (server_socket) { FD_SET (server_socket->fd, &rfds); clients_pre_select (clients, &rfds, &wfds); } if (client_socket) socket_pre_select (client_socket, &rfds, &wfds); if (ansi && ansi->terminal) tty_pre_select (ansi->terminal, &rfds, &wfds); select (FD_SETSIZE, &rfds, &wfds, NULL, &tv); /* any message from clients, or new connexions */ if (server_socket) { Socket *new_client_socket; if (FD_ISSET (server_socket->fd, &rfds) && ((new_client_socket = socket_accept (server_socket)))) { { Client *new_client; /* New client connexion */ new_client = clients_new_client (clients, new_client_socket, c); } } clients_post_select (clients, c, &rfds, &wfds); } /* any data from the port */ if (c->t && FD_ISSET (c->t->rfd, &rfds)) { char buf[IPC_MAX_BUF]; int red; red = c->t->recv (c->t, buf, sizeof (buf)); if (red < 0) break; if (red) { if (clients) send_output (clients, buf, red); if (tty_parse (c, buf, red)) break; } } /* any data from the server */ if (client_socket) { int err = 0; if (socket_post_select (client_socket, &rfds, &wfds)) break; while (client_socket->msg && !err) { err += msg_from_server (ansi, client_socket->msg, c); socket_consume_msg (client_socket); } if (err) break; } /* update our local screen */ if (ansi) { if (ansi->dispatch) if (ansi->dispatch (ansi, c)) break; if (ansi->update) if (ansi->update (ansi, c)) break; } } if (clients) clients_shutdown (clients, c); log_f (c->l, ""); } work/apps/mainloop.h0000664000000000000000000000216713337271225011675 0ustar /* * mainloop.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: mainloop.h,v 1.10 2008/03/07 13:16:02 james Exp $ */ /* * $Log: mainloop.h,v $ * Revision 1.10 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.9 2008/03/06 16:49:39 james * *** empty log message *** * * Revision 1.8 2008/03/06 16:49:05 james * *** empty log message *** * * Revision 1.7 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.6 2008/03/02 10:27:24 james * *** empty log message *** * * Revision 1.5 2008/02/27 09:42:53 james * *** empty log message *** * * Revision 1.4 2008/02/27 09:42:21 james * *** empty log message *** * * Revision 1.3 2008/02/27 01:31:14 james * *** empty log message *** * * Revision 1.2 2008/02/20 18:49:11 staffcvs * *** empty log message *** * * Revision 1.1 2008/02/20 18:33:37 james * *** empty log message *** * */ #ifndef __MAINLOOP_H__ #define __MAINLOOP_H__ #include extern void mainloop (Context *, ANSI * a, Socket *, Socket *); #endif /* __MAINLOOP_H__ */ work/apps/sympathy.c0000664000000000000000000005105413337271225011727 0ustar /* * sympathy.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: sympathy.c,v 1.52 2010/07/27 14:49:34 james Exp $"; /* * $Log: sympathy.c,v $ * Revision 1.52 2010/07/27 14:49:34 james * add support for byte logging * * Revision 1.51 2010/07/16 11:04:10 james * ignore tedious return values * * Revision 1.50 2008/05/09 12:56:28 staffcvs * *** empty log message *** * * Revision 1.49 2008/05/09 12:43:49 staffcvs * *** empty log message *** * * Revision 1.48 2008/05/09 12:35:57 james * *** empty log message *** * * Revision 1.47 2008/05/09 12:26:58 staffcvs * *** empty log message *** * * Revision 1.46 2008/05/09 12:19:18 james * *** empty log message *** * * Revision 1.45 2008/03/15 01:44:31 james * *** empty log message *** * * Revision 1.44 2008/03/12 01:30:23 james * *** empty log message *** * * Revision 1.43 2008/03/12 01:26:56 james * *** empty log message *** * * Revision 1.42 2008/03/11 15:02:52 james * *** empty log message *** * * Revision 1.41 2008/03/10 11:49:32 james * *** empty log message *** * * Revision 1.40 2008/03/07 14:16:44 james * *** empty log message *** * * Revision 1.39 2008/03/07 14:13:40 james * *** empty log message *** * * Revision 1.38 2008/03/07 13:56:39 james * *** empty log message *** * * Revision 1.37 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.36 2008/03/06 21:34:09 james * *** empty log message *** * * Revision 1.35 2008/03/06 21:33:02 james * *** empty log message *** * * Revision 1.34 2008/03/06 16:49:39 james * *** empty log message *** * * Revision 1.33 2008/03/06 16:49:05 james * *** empty log message *** * * Revision 1.32 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.31 2008/03/03 06:04:18 james * *** empty log message *** * * Revision 1.30 2008/03/02 10:38:18 james * *** empty log message *** * * Revision 1.29 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.28 2008/03/02 10:27:24 james * *** empty log message *** * * Revision 1.27 2008/03/02 09:55:37 james * *** empty log message *** * * Revision 1.26 2008/02/29 14:55:09 james * *** empty log message *** * * Revision 1.25 2008/02/28 22:43:25 james * *** empty log message *** * * Revision 1.24 2008/02/28 22:00:42 james * *** empty log message *** * * Revision 1.23 2008/02/28 16:57:51 james * *** empty log message *** * * Revision 1.22 2008/02/28 01:47:44 james * *** empty log message *** * * Revision 1.21 2008/02/27 16:01:24 james * *** empty log message *** * * Revision 1.20 2008/02/27 10:00:34 james * *** empty log message *** * * Revision 1.19 2008/02/27 09:47:05 james * *** empty log message *** * * Revision 1.18 2008/02/27 09:42:53 james * *** empty log message *** * * Revision 1.17 2008/02/27 09:42:21 james * *** empty log message *** * * Revision 1.16 2008/02/27 01:31:38 james * *** empty log message *** * * Revision 1.15 2008/02/27 01:31:14 james * *** empty log message *** * * Revision 1.14 2008/02/24 00:43:55 james * *** empty log message *** * * Revision 1.13 2008/02/24 00:42:53 james * *** empty log message *** * * Revision 1.12 2008/02/23 11:48:52 james * *** empty log message *** * * Revision 1.11 2008/02/20 20:16:07 james * *** empty log message *** * * Revision 1.10 2008/02/20 19:44:37 james * @@ * * Revision 1.9 2008/02/20 18:49:11 staffcvs * *** empty log message *** * * Revision 1.8 2008/02/20 18:33:37 james * *** empty log message *** * * Revision 1.7 2008/02/20 18:31:44 james * *** empty log message *** * * Revision 1.6 2008/02/20 17:18:33 james * *** empty log message *** * * Revision 1.5 2008/02/20 15:50:14 james * *** empty log message *** * * Revision 1.4 2008/02/20 02:11:35 james * *** empty log message *** * * Revision 1.3 2008/02/14 02:46:44 james * *** empty log message *** * * Revision 1.2 2008/02/14 00:57:58 james * *** empty log message *** * * Revision 1.1 2008/02/05 14:25:49 james * *** empty log message *** * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mainloop.h" int use_syslog = 0; extern void usage (void); extern char *expand (const char *, int *); static char hostname[1024]; char *socket_dirs[] = { "~/.sympathy", "~/sympathy", "/etc/sympathy", "/var/sympathy", NULL }; int safe_atoi (char *a) { char *end; int ret; if (!a) return -1; ret = (int) strtol (a, &end, 0); if (end == a) return -1; return ret; } char * fatal_moan (char *fmt, ...) { va_list ap; va_start (ap, fmt); if (use_syslog) { vsyslog (LOG_ERR, fmt, ap); } else { vfprintf (stderr, fmt, ap); putc ('\n', stderr); } va_end (ap); exit (1); } static void sigchld (int dummy) { int status; wait3 (&status, WNOHANG, NULL); } /* Dispell zombies, from, for example, log compression */ void garlic (void) { struct sigaction sa; sa.sa_handler = sigchld; sa.sa_flags = SA_RESTART; sigaction (SIGCHLD, &sa, NULL); } char * teedious_snprintf (char *fmt, va_list ap) { va_list aq; int size = 1024; char *buf = malloc (size); int n; if (!buf) fatal_moan ("malloc failed"); while (1) { va_copy (aq, ap); n = vsnprintf (buf, size, fmt, aq); va_end (aq); if (n > -1 && n < (size)) return buf; if (n > -1) /* glibc 2.1 */ size = n + 1; else /* glibc 2.0 */ size *= 2; /* twice the old size */ buf = realloc (buf, size); if (!buf) fatal_moan ("malloc failed"); } } char * gloo_paths (char *dir, char *leaf) { int i; char *ret, *ptr; if (!dir) dir = ""; if (!leaf) leaf = ""; ret = ptr = xmalloc (strlen (dir) + strlen (leaf) + 2); while (*dir) *(ptr++) = *(dir++); *(ptr++) = '/'; while (*leaf) *(ptr++) = *(leaf++); *ptr = 0; return ret; } /* make the path in fmt from home (hence the name) */ char * mome (char *fmt, ...) { char *ret, *home, *leaf; va_list ap; home = getenv ("HOME"); if (!home) return NULL; if (fmt) { va_start (ap, fmt); leaf = teedious_snprintf (fmt, ap); va_end (ap); } else { leaf = NULL; } ret = gloo_paths (home, leaf); if (leaf) free (leaf); return ret; } Socket * find_socket (char **retpath, char *fmt, ...) { Socket *ret; char *path, *leaf, *h, **ptr; va_list ap; if (fmt) { va_start (ap, fmt); leaf = teedious_snprintf (fmt, ap); va_end (ap); } else { leaf = NULL; } for (ptr = socket_dirs; *ptr; ptr++) { if (**ptr == '~') { h = mome (*ptr + 1); } else { h = *ptr; } if (!h) continue; path = gloo_paths (h, leaf); if (**ptr == '~') free (h); ret = socket_connect (path); if (ret) { if (retpath) { *retpath = path; } else { free (path); } free (leaf); return ret; } free (path); } free (leaf); return NULL; } int list_sockets_in_dir (char *sockdir) { struct dirent *ent; struct stat buf; char *sn = NULL; Socket *s; DIR *dir = opendir (sockdir); int hostname_len = strlen (hostname); if (!dir) return 0; rewinddir (dir); while ((ent = readdir (dir))) { sn = gloo_paths (sockdir, ent->d_name); if (stat (sn, &buf) || (!S_ISSOCK (buf.st_mode))) { free (sn); continue; } s = socket_connect (sn); if (s) { printf ("\t%s (Active)\n", sn); socket_free (s); } else { if (strncmp (ent->d_name, hostname, hostname_len)) { printf ("\t%s (Unknown - not this host)\n", sn); } else { printf ("\t%s (Dead, wiped)\n", sn); unlink (sn); } } free (sn); } closedir (dir); return 0; } int list_sockets (void) { char **ptr, *h; for (ptr = socket_dirs; *ptr; ptr++) { if (**ptr == '~') { h = mome (*ptr + 1); } else { h = *ptr; } if (!h) continue; list_sockets_in_dir (h); if (**ptr == '~') free (h); } return 0; } void get_hostname (void) { struct utsname name; if (uname (&name)) { strcpy (hostname, "unknown."); return; } strcpy (hostname, name.nodename); strcat (hostname, "."); } void send_to_server (Socket * c, char *s) { int n; s = expand (s, &n); if (!n) return; while (n--) { ipc_msg_send_key (c, *(uint8_t *) s); s++; } ipc_msg_send_killme (c); } int main (int argc, char *argv[]) { Context ctx_store = { 0 }, *ctx = &ctx_store; int c; extern char *optarg; extern int optind, opterr, optopt; CRT_Pos size = { VT102_COLS_80, VT102_ROWS_24 }; ANSI *ansi = NULL; int cs_pipe[2] = { 0 }; int cs = 0; int oflags[128]; char *oargs[128]; Socket *server_socket = NULL, *client_socket = NULL; int history = 200; int pid; char *pid_file = NULL; get_hostname (); memset (oflags, 0, sizeof (oflags)); memset (oargs, 0, sizeof (oargs)); while ((c = getopt (argc, argv, "BI:NCSRP:vw:utscr:lKHd:pb:fL:Fk:n:")) != EOF) { switch (c) { case ':': case 'h': case '?': usage (); case 'S': use_syslog++; openlog ("sympathy", LOG_PID | LOG_CONS, LOG_DAEMON); /*fall through */ default: if ((c >= 'A') && (c <= 'Z')) { oflags[c]++; oargs[c] = optarg; } else if ((c >= 'a') && (c <= 'z')) { oflags[c]++; oargs[c] = optarg; } else { if (use_syslog) { syslog (LOG_ERR, "unknown option %c\n", c); } else { fprintf (stderr, "unknown option %c\n", c); } usage (); } } } /* Compatability for screen's ls */ if (oflags['l']) oflags['s'] = 0; { int sum = 0; sum += oflags['t']; sum += (oflags['s'] || oflags['c']) ? 1 : 0; sum += oflags['r']; sum += oflags['l']; sum += oflags['v']; sum += oflags['C']; if (!sum) { /* If no mode is specified behave like screen */ oflags['s']++; oflags['c']++; sum++; } if (sum != 1) fatal_moan ("specifiy exactly one of ( -c and or -s ), -t, -r, -C, -l and -v"); } if (oflags['v']) { fprintf (stderr, "Version: %s\n", libsympathy_version ()); fprintf (stderr, "Version: %s\n", rcsid); return 0; } if (oflags['l']) return list_sockets (); if (oflags['r'] && oflags['k']) fatal_moan ("-k is incompatible with -r"); if (oflags['n']) { history = safe_atoi (oargs['n']); if (history < 0) fatal_moan ("cannot parse -n %s as an integer", oargs['n']); if (!history) fatal_moan ("agrument to -n must be greater than zero"); } /* Fold -r implies -c */ if (oflags['r']) oflags['c']++; if (oflags['p'] && oflags['d']) fatal_moan ("-p incompatible with -d"); if (oflags['c'] && oflags['s'] && oflags['F']) fatal_moan ("-F is incompatible with -c -s"); if (oflags['H'] && oflags['N']) fatal_moan ("-H is incompatible with -N"); /* implement server and client: this process forks. The parent */ /* becomes the client and the child forks again to become the */ /* server. If there's no -k argument the client (parent) needs */ /* to find out the pid of the server, we use a pipe */ if (oflags['s'] && oflags['c']) { cs++; int result; result = pipe (cs_pipe); switch (pid = fork ()) { case 0: /* child becomes the server */ oflags['c'] = 0; oflags['H'] = 0; oflags['N'] = 0; oflags['I'] = 0; close (cs_pipe[0]); break; case -1: fatal_moan ("fork failed"); default: /* parent becomes client */ oflags['s'] = 0; oflags['K'] = 0; oflags['d'] = 0; oflags['p'] = 0; oflags['b'] = 0; oflags['f'] = 0; oflags['L'] = 0; oflags['R'] = 0; oflags['B'] = 0; oflags['P'] = 0; oflags['n'] = 0; oflags['w'] = 0; /* Collect the child */ waitpid (pid, NULL, 0); /* if there was no k argument we need to find the */ /* pid of the server process so that we can work out */ /* what the socket is called. The server tells us on */ /* a pipe. We do this even if k is specified to avoid */ /* a race, the server writes to the pipe when the socket */ /* is opened */ close (cs_pipe[1]); if (read (cs_pipe[0], &pid, sizeof (pid)) != sizeof (pid)) fatal_moan ("Failed to receive pid of server process"); close (cs_pipe[0]); if (!oflags['k']) { oargs['k'] = mome ("/.sympathy/%s%d", hostname, pid); oflags['k']++; } } } if (oflags['c'] && !oflags['k'] && !oflags['r']) fatal_moan ("-c requires a socket to be specified with -s or -k or -r"); if ((oflags['H'] || oflags['N'] || oflags['I']) && oflags['s']) fatal_moan ("-s is incompatible with -H, -N and -I"); if ((oflags['p'] || oflags['d'] || oflags['K'] || oflags['b'] || oflags['f'] || oflags['L'] || oflags['R'] || oflags['B'] || oflags['P']) && oflags['c']) fatal_moan ("-c or -r are incompatible with -p, -d, -K, -b, -f, -R, -P, -B or -L"); if (oflags['C'] && (!oflags['d'])) fatal_moan ("-C requires -d"); if (oflags['t'] || oflags['s']) { if (!oflags['p'] && !oflags['d']) oflags['p']++; } if (oflags['w']) { char buf[128], *ptr; strcpy (buf, oargs['w']); ptr = index (buf, 'x'); if (ptr) { *ptr = 0; ptr++; size.y = safe_atoi (ptr); } size.x = safe_atoi (buf); if ((size.x > VT102_MAX_COLS) || (size.x < 1)) fatal_moan ("-w requires a width between 1 and %d\n", VT102_MAX_COLS); if ((size.y > VT102_MAX_ROWS) || (size.y < 1)) fatal_moan ("-w requires a height between 1 and %d\n", VT102_MAX_ROWS); } if (oflags['s'] && !oflags['F']) { /* nochdir incase socket is relative path, unlink then will fail */ int fish; fish = daemon (1, 0); } garlic (); if (oflags['s']) { char *path; path = mome ("/.sympathy"); mkdir (path, 0700); free (path); if (!oflags['k']) { pid = getpid (); oargs['k'] = mome ("/.sympathy/%s%d", hostname, pid); oflags['k']++; } server_socket = socket_listen (oargs['k']); /* Tell our parent's parent what our pid is */ /* and that we've opened the server socket */ if (cs) { pid = getpid (); int fish; fish = write (cs_pipe[1], &pid, sizeof (pid)); close (cs_pipe[1]); } if (!server_socket) fatal_moan ("failed to create socket %s for listening", oargs['k']); } if (oflags['s'] || oflags['t'] || oflags['C']) { if (oflags['P']) { FILE *fp; pid_file = oargs['P']; fp = fopen (pid_file, "w"); if (fp) { fprintf (fp, "%d", getpid ()); fclose (fp); } } if (oflags['L']) { ctx->l = file_log_new (oargs['L'], oflags['R']); ctx->byte_logging=oflags['B']; if (!ctx->l) fatal_moan ("unable to access log file %s", oargs['L']); } if (oflags['p']) { if (optind < argc) { ctx->t = ptty_open (argv[optind], &argv[optind], &size); } else { ctx->t = ptty_open (NULL, NULL, &size); } if (!ctx->t) fatal_moan ("unable to open a ptty"); } else { /* HACK-- check that console=device does not occur in */ /* /proc/cmdline */ if (!oargs['d']) fatal_moan ("no argument to -d"); { char kernel_cmdline[4096] = { 0 }; char search_string[1024] = "console="; char *ptr = oargs['d']; int fd; if (!strncmp ("/dev/", ptr, 5)) ptr += 5; strcat (search_string, ptr); fd = open ("/proc/cmdline", O_RDONLY); int fish; fish = read (fd, kernel_cmdline, sizeof (kernel_cmdline)); close (fd); kernel_cmdline[sizeof (kernel_cmdline) - 1] = 0; if (strstr (kernel_cmdline, search_string)) fatal_moan ("/proc/cmdline contains %s", search_string); } ctx->t = serial_open (oargs['d'], oflags['K'] ? SERIAL_LOCK_ACTIVE : SERIAL_LOCK_PASSIVE); if (!ctx->t) fatal_moan ("unable to open serial port %s", oargs['d']); if (oflags['C']) { ctx->t->close (ctx->t); return 0; } } if (oflags['b']) { int baud = safe_atoi (oargs['b']); if (baud < 0) fatal_moan ("Unable to parse baudrate %s", oargs['b']); tty_set_baud (ctx->t, baud); } tty_set_flow (ctx->t, oflags['f'] ? 1 : 0); } if (oflags['r']) { char *id = oargs['r']; if (!id) fatal_moan ("-r requires an argument"); if (safe_atoi (id) > 0) { client_socket = find_socket (&oargs['k'], "%s%d", hostname, safe_atoi (id)); } else { client_socket = find_socket (&oargs['k'], "%s", id); } if (!client_socket) fatal_moan ("failed to find socket %s", oargs['r']); } else if (oflags['c']) { client_socket = socket_connect (oargs['k']); if (!client_socket) fatal_moan ("failed to connect to socket %s", oargs['k']); } if (oflags['I']) { if (!client_socket) fatal_moan ("-I requires either -c or -r", oargs['k']); if (!oargs['I']) fatal_moan ("-I requires an arugment"); send_to_server (client_socket, oargs['I']); } else { if (client_socket) ipc_msg_send_initialize (client_socket); if (oflags['c'] || oflags['t']) { if (oflags['N']) { ctx->r = rx_new_raw (0, 1); ansi = ansi_new_raw (0, 1); } else if (oflags['H']) { ansi = ansi_new_html (stdout); } else { terminal_register_handlers (); ansi = ansi_new_from_terminal (terminal_open (0, 1), oflags['u'] ? 0 : 1); ansi->reset (ansi, NULL); } if (ansi->set_title) { if (oflags['c'] && oargs['k']) { ansi->set_title (ansi, oargs['k']); } else if ((ctx->t) && (ctx->t->name)) { ansi->set_title (ansi, ctx->t->name); } } } } ctx->v = vt102_new (&size); ctx->h = history_new (history); mainloop (ctx, ansi, server_socket, client_socket); if (ansi) { ansi->close (ansi); terminal_atexit (); } if (ctx->t) ctx->t->close (ctx->t); if (ctx->l) ctx->l->close (ctx->l); if (server_socket) socket_free (server_socket); if (client_socket) socket_free (client_socket); if (pid_file) unlink (pid_file); if (!oflags['H'] && !oflags['I']) printf ("you have now exited sympathy\n"); return 0; } work/apps/usage.c0000664000000000000000000001545013337271225011155 0ustar /* * usage.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: usage.c,v 1.28 2011/02/28 18:11:10 james Exp $"; /* * $Log: usage.c,v $ * Revision 1.28 2011/02/28 18:11:10 james * *** empty log message *** * * Revision 1.27 2008/05/09 12:35:57 james * *** empty log message *** * * Revision 1.26 2008/05/09 12:26:58 staffcvs * *** empty log message *** * * Revision 1.25 2008/05/09 12:19:18 james * *** empty log message *** * * Revision 1.24 2008/03/12 01:30:23 james * *** empty log message *** * * Revision 1.23 2008/03/12 01:26:56 james * *** empty log message *** * * Revision 1.22 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.21 2008/03/06 21:34:09 james * *** empty log message *** * * Revision 1.20 2008/03/06 17:21:41 james * *** empty log message *** * * Revision 1.19 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.18 2008/03/03 06:04:18 james * *** empty log message *** * * Revision 1.17 2008/02/28 16:57:51 james * *** empty log message *** * * Revision 1.16 2008/02/27 18:29:49 james * *** empty log message *** * * Revision 1.15 2008/02/27 16:01:24 james * *** empty log message *** * * Revision 1.14 2008/02/27 09:55:57 james * *** empty log message *** * * Revision 1.13 2008/02/27 09:42:53 james * *** empty log message *** * * Revision 1.12 2008/02/27 09:42:21 james * *** empty log message *** * * Revision 1.11 2008/02/27 01:31:38 james * *** empty log message *** * * Revision 1.10 2008/02/27 01:31:14 james * *** empty log message *** * * Revision 1.9 2008/02/24 00:43:55 james * *** empty log message *** * * Revision 1.8 2008/02/24 00:42:53 james * *** empty log message *** * * Revision 1.7 2008/02/23 11:48:52 james * *** empty log message *** * * Revision 1.6 2008/02/20 18:49:11 staffcvs * *** empty log message *** * * Revision 1.5 2008/02/20 18:31:44 james * *** empty log message *** * * Revision 1.4 2008/02/20 17:18:33 james * *** empty log message *** * * Revision 1.3 2008/02/20 02:11:35 james * *** empty log message *** * * Revision 1.2 2008/02/16 10:58:52 james * *** empty log message *** * * Revision 1.1 2008/02/16 01:30:56 james * *** empty log message *** * */ #include #include void usage (void) { fprintf (stderr, "Usage:\n" "sympathy -t [-K] [-d serialdev|-p] [-b baud] [-f] [-L log] [-w WxH]\n" " [-F] [-P pidfile] [-u] [-N]\n" " [pty program] [pty program args]\n" "sympathy -s [-K] [-d serialdev|-p] [-b baud] [-f] [-L log] [-w WxH]\n" " [-F] [-P pidfile] [-n hlines] [-k skt]\n" " [-S] [pty program] [pty program args]\n" "sympathy [-s -c] [-K] [-d serialdev|-p] [-b baud] [-f] [-L log] [-w WxH]\n" " [-F] [-P pidfile] [-u] [-N] [-n hlines] [-k skt]\n" " [-S] [pty program] [pty program args]\n" "sympathy -c [-H] [-I string ] [-u] [-N] -k skt\n" "sympathy -r id [-H] [-I string ] [-u] [-N]\n" "sympathy -C -d serialdev\n" "sympathy {-l|-ls}\n" "sympathy -v\n" "sympathy -h\n" "\n" "Main mode:\n" " -t terminal emulator mode: one process is started which reads from\n" " the serial device or ptty and writes to the user's terminal.\n" " -s server mode: a process is started (and daemonized unless -F is\n" " given) which listens on a socket, and reads from the serial\n" " device or ptty.\n" " -s -c server and client mode: Fork a server and connect a client\n" " incompatible with -F. This is the default mode\n" " -c client mode: connect to server mode process\n" " -r id client mode: connect to server mode process on socket\n" " ~/.sympathy/id or ~/.sympathy/hostname.id if id is an\n" " integer\n" " -l or -ls list active sockets in ~/.sympathy\n" " -C clear inactive locks\n" " -v show version\n" " -h show help\n" "\n" "Options:\n" " -K lock the serial device. By default sympathy checks that no\n" " other process has created a lock file, and temporarily ceases\n" " to access the serial port if it spots one. With this option\n" " sympathy creates a lock file and prevents other programs\n" " accessing the serial port. Incompatible with -p\n" " -d serialdev the serial device to connect to, eg /dev/ttyS0\n" " -p fork a login shell in a ptty and connect to that rather than\n" " connect to a serial port. This option is the default if\n" " no -d option is specified\n" " -b baud the baudrate to set. If omitted sympathy does not set\n" " a baudrate and uses the current setting\n" " -f set RTS/CTS flowcontrol. By default sympathy disables flow\n" " control\n" " -k socket explicity set the name of the socket, by default\n" " sympathy will use ~/.sympathy/$pid\n" " -F do not detach, run the server in the foreground\n" " -H instead of connecting the user's terminal to the session\n" " emit HTML of the current state of the screen on stdout\n" " -L log log activity on the device to the file log\n" " -n nlines the number of lines of history to store in the\n" " server, that are replayed on connexion\n" " -P pidfile write the pid of the server/terminal process to pidfile\n" " -R rotate logile specified with -L option\n" " -S log errors to syslog\n" " -u don't emit utf-8 try to use ISO-2202 to the local terminal\n" " -w W[xH] start session with a screen of size W by H. 0, # All rights reserved. # # $Id: autogen.sh,v 1.2 2008/03/07 14:36:25 james Exp $ # # $Log: autogen.sh,v $ # Revision 1.2 2008/03/07 14:36:25 james # *** empty log message *** # # Revision 1.1 2008/03/07 14:32:55 james # *** empty log message *** # # Revision 1.1 2008/02/03 16:20:24 james # *** empty log message *** # # # # # libtoolize -f -c --automake aclocal autoheader autoconf automake -a -c -Wno-portability #automake -a -c Makefile #automake -a -c src/Makefile #automake -a -c apps/Makefile #automake -a -c test/Makefile work/config.guess0000775000000000000000000012564413337271225011271 0ustar #! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2016 Free Software Foundation, Inc. timestamp='2016-10-02' # This file 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 to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ /sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || \ echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` machine=${arch}${endian}-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case "${UNAME_MACHINE_ARCH}" in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case "${UNAME_MACHINE_ARCH}" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; *:Sortix:*:*) echo ${UNAME_MACHINE}-unknown-sortix exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/lslpp ] ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = hppa2.0w ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; e2k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; k1om:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; mips64el:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; riscv32:Linux:*:* | riscv64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; SX-ACE:SUPER-UX:*:*) echo sxace-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; esac cat >&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` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: work/config.sub0000775000000000000000000010676313337271225010735 0ustar #! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2016 Free Software Foundation, Inc. timestamp='2016-11-04' # This file 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 to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | e2k | epiphany \ | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; leon|leon[3-9]) basic_machine=sparc-$basic_machine ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; asmjs) basic_machine=asmjs-unknown ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; e500v[12]) basic_machine=powerpc-unknown os=$os"spe" ;; e500v[12]-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` os=$os"spe" ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; leon-*|leon[3-9]-*) basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; moxiebox) basic_machine=moxie-unknown os=-moxiebox ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ | -onefs* | -tirtos* | -phoenix* | -fuchsia*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -ios) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: work/configure.in0000664000000000000000000000705313337271225011253 0ustar dnl dnl dnl configure.in: dnl dnl Copyright (c) 2008 James McKenzie , dnl All rights reserved. dnl dnl $Id: configure.in,v 1.6 2008/03/06 21:34:09 james Exp $ dnl dnl $Log: configure.in,v $ dnl Revision 1.6 2008/03/06 21:34:09 james dnl *** empty log message *** dnl dnl Revision 1.5 2008/03/06 21:33:02 james dnl *** empty log message *** dnl dnl Revision 1.4 2008/02/27 15:17:56 james dnl *** empty log message *** dnl dnl Revision 1.3 2008/02/27 15:04:32 james dnl *** empty log message *** dnl dnl Revision 1.2 2008/02/13 18:05:06 james dnl *** empty log message *** dnl dnl Revision 1.1 2008/02/03 16:20:23 james dnl *** empty log message *** dnl dnl dnl dnl AC_PREREQ(2.13) AC_INIT(src/libsympathy.c) AC_PROG_CC AC_SYS_LARGEFILE LIBSYMPATHY_MAJOR_VERSION=`cat $srcdir/version-major` LIBSYMPATHY_MINOR_VERSION=`cat $srcdir/version-minor` LIBSYMPATHY_MICRO_VERSION=`cat $srcdir/version-micro` LIBSYMPATHY_INTERFACE_VERSION_MIN=$LIBSYMPATHY_MINOR_VERSION LIBSYMPATHY_INTERFACE_VERSION_MAX=$LIBSYMPATHY_MINOR_VERSION LIBSYMPATHY_INTERFACE_REVISION=1 LIBSYMPATHY_VERSION=$LIBSYMPATHY_MAJOR_VERSION.$LIBSYMPATHY_MINOR_VERSION.$LIBSYMPATHY_MICRO_VERSION AC_SUBST(LIBSYMPATHY_MAJOR_VERSION) AC_SUBST(LIBSYMPATHY_MINOR_VERSION) AC_SUBST(LIBSYMPATHY_MICRO_VERSION) AC_SUBST(LIBSYMPATHY_VERSION) AC_SUBST(LIBSYMPATHY_INTERFACE_VERSION_MIN) AC_SUBST(LIBSYMPATHY_INTERFACE_VERSION_MAX) AC_SUBST(LIBSYMPATHY_INTERFACE_REVISION) LT_RELEASE=$LIBSYMPATHY_MAJOR_VERSION.$LIBSYMPATHY_MINOR_VERSION LT_CURRENT=$LIBSYMPATHY_INTERFACE_VERSION_MAX LT_REVISION=$LIBSYMPATHY_MICRO_VERSION LT_AGE=`expr $LIBSYMPATHY_INTERFACE_VERSION_MAX - $LIBSYMPATHY_INTERFACE_VERSION_MIN` AC_SUBST(LT_RELEASE) AC_SUBST(LT_CURRENT) AC_SUBST(LT_REVISION) AC_SUBST(LT_AGE) VERSION=$LIBSYMPATHY_VERSION PACKAGE=libsympathy AM_INIT_AUTOMAKE($PACKAGE,$VERSION) AM_PROG_LIBTOOL AM_CONFIG_HEADER(src/config.h) AC_CHECK_PROG(MD5SUM,md5sum,md5sum) AC_CHECK_PROG(GREP,grep,grep) AC_CHECK_PROG(SED,sed,sed) AC_PROG_AWK dnl AC_DEFINE_UNQUOTED(LIBSYMPATHY_MAJOR_VERSION, $LIBSYMPATHY_MAJOR_VERSION) dnl AC_DEFINE_UNQUOTED(LIBSYMPATHY_MINOR_VERSION, $LIBSYMPATHY_MINOR_VERSION) dnl AC_DEFINE_UNQUOTED(LIBSYMPATHY_MICRO_VERSION, $LIBSYMPATHY_MICRO_VERSION) AC_CHECK_HEADERS(fcntl.h malloc.h sys/ioctl.h unistd.h) AC_CHECK_HEADERS(sys/scsi/impl/uscsi.h scsi/sg.h stdint.h) AC_CHECK_HEADERS(sys/int_types.h string.h strings.h) AC_CHECK_HEADERS(dirent.h sys/stat.h) AC_C_INLINE AC_C_CONST AC_HEADER_TIME AC_STRUCT_TM AC_CHECK_FUNCS(select strdup strstr) G2_TM_H=$ac_cv_struct_tm G2_HAVE_STDINT_H=0 G2_HAVE_SYS_INT_TYPES_H=0 if test "$ac_cv_header_sys_int_types_h" = "yes"; then G2_HAVE_SYS_INT_TYPES_H=1 fi if test "$ac_cv_header_stdint_h" = "yes"; then G2_HAVE_STDINT_H=1 fi G2_HAVE_UNISTD_H=0 if test "$ac_cv_header_unistd_h" = "yes"; then G2_HAVE_UNISTD_H=1 fi G2_HAVE_MALLOC_H=0 if test "$ac_cv_header_malloc_h" = "yes"; then G2_HAVE_MALLOC_H=1 fi G2_HAVE_STDINT_H=0 if test "$ac_cv_header_stdint_h" = "yes"; then G2_HAVE_STDINT_H=1 fi G2_TIME_WITH_SYS_TIME=0 if test "$ac_cv_header_time_h" = "yes"; then G2_TIME_WITH_SYS_TIME=1 fi G2_TM_IN_SYS_TIME=0 if test "$ac_cv_struct_tm" = "sys/time.h"; then G2_TM_IN_SYS_TIME=1 fi dnl CFLAGS=-g AC_SUBST(G2_TM_H) AC_SUBST(G2_HAVE_STDINT_H) AC_SUBST(G2_HAVE_SYS_INT_TYPES_H) AC_SUBST(G2_HAVE_UNISTD_H) AC_SUBST(G2_HAVE_MALLOC_H) AC_SUBST(G2_HAVE_STDINT_H) AC_SUBST(G2_TIME_WITH_SYS_TIME) AC_SUBST(G2_TM_IN_SYS_TIME) AC_OUTPUT([Makefile src/Makefile src/sympathy.h.head test/Makefile apps/Makefile libsympathy-config.src],[chmod +x libsympathy-config.src]) work/debian/0000775000000000000000000000000013337271225010157 5ustar work/debian/changelog0000664000000000000000000000237013337271225012033 0ustar sympathy (1.2.1+woking+cvs+git20171124-1) unstable; urgency=medium * Fix overly zealous gcc-8 warning about integer overflow. Closes:#897873. * Document the -B option. * Do not send "\e[21m" when turning off bold. It enables underline! -- Ian Jackson Wed, 22 Aug 2018 15:26:29 +0100 sympathy (1.2.1+woking+cvs+git20171124) unstable; urgency=medium * #include to fix FTBFS. Closes:#882248. -- Ian Jackson Fri, 24 Nov 2017 16:11:35 +0000 sympathy (1.2.1+woking+cvs+git20161222) unstable; urgency=low * Many build and packaging fixes. * Error handling bugfixes. * Import from upstream CVS, "Sun Mar 2 10:37:56 2008 +0000". * Merge upstream CVS with files from woking (a now ex-host at Citrix). * Improvements to serialmgrd. * Change to native package. There are no orig tarballs and the source is pretty small so it's not worth messing about with diffs. -- Ian Jackson Thu, 22 Dec 2016 17:56:54 +0000 sympathy (1.2.1+woking-1) unstable; urgency=low * Initial release from sourced code rescued from woking.cam.xci-test.com. -- Ian Jackson Fri, 20 Feb 2015 18:34:20 +0000 work/debian/compat0000664000000000000000000000000213337271225011355 0ustar 9 work/debian/control0000664000000000000000000000124513337271225011564 0ustar Source: sympathy Maintainer: Ian Jackson Uploaders: Ian Jackson Build-Depends: libtool, autoconf, automake, debhelper Section: comm Priority: optional Standards-Version: 3.9.8.0 Package: sympathy Architecture: any Depends: ${misc:Depends}, ${shlibs:Depends} Pre-Depends: ${misc:Pre-Depends} Description: serial port concentrator system - server/client program sympathy is a system for logging and providing access to serial (RS232) ports; typically, multiple serial ports on a single server (aka, a serial concentrator). . sympathy can function as a replacement for screen(1), minicom(1) and consolidate(1). work/debian/copyright0000664000000000000000000001636613337271225012126 0ustar Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: sympathy Upstream-Contact: James McKenzie License: LGPL-2.1+ The following statement applies to the whole package, as everything is either explicitly LGPLv2.1+ or LGPLv2.1+-compatible. . This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. . You should have received a copy of the GNU Lesser General Public License along with this program. If not see www.fsf.org. . On a Debian system you can find a copy of the GNU Lesser General Public License version 2.1 in /usr/share/common-licenses/LGPL-2.1 Files: * Copyright: 2008, James KcKenzie License: LGPL-2.1+ Files: debian/* Copyright: 2015, Citrix Systems License: BSD-2-clause All rights reserved. . Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: . 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. . 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. . THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Files: config.guess config.sub depcomp missing Copyright: 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. License: GPL-2+ or autoconf-special-case As a special exception to the GNU General Public License, if you distribute this file as part of a program that contains a configuration script generated by Autoconf, you may include it under the same distribution terms that you use for the rest of that program. Files: install-sh Copyright: 1994 X Consortium License: MIT Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: . The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. . THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. . Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other deal- ings in this Software without prior written authorization from the X Consor- tium. . FSF changes to this file are in the public domain. Files: test/vttest-20071216.tar.gz Copyright: 1996-2005, 2007 Thomas E. Dickey 1984 Per Lindberg License: Copyright 1996-2005,2007 by Thomas E. Dickey . All Rights Reserved . Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the above listed copyright holder(s) not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. . THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. . VTTEST.C . Written November 1983 - July 1984 by Per Lindberg, Stockholm University Computer Center (QZ), Sweden. . THE MAD PROGRAMMER STRIKES AGAIN! . Copyright (c) 1984, Per Lindberg All rights reserved. . Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of Per Lindberg nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. . THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. work/debian/rules0000775000000000000000000000074613337271225011246 0ustar #!/usr/bin/make -f %: dh $@ override_dh_auto_configure: ./autogen.sh dh_auto_configure examples=debian/sympathy/usr/share/doc/sympathy/examples override_dh_auto_install: dh_auto_install find debian/sympathy \( \ -name libsympathy-config \ -o -name \*.a -o -name \*.la -o -name \*.h \ \) -print0 | xargs -0r rm -- install -m 755 -d $(examples) install -m 755 serialmgr/run_sympathy serialmgr/serialmgrd $(examples)/. override_dh_compress: dh_compress -Xexamples work/depcomp0000775000000000000000000005601613337271225010322 0ustar #! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2013-05-30.07; # UTC # Copyright (C) 1999-2014 Free Software Foundation, Inc. # 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, 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 to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: work/install-sh0000775000000000000000000003246413337271225010752 0ustar #!/bin/sh # install - install a program, script, or datafile scriptversion=2006-12-25.00 # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then trap '(exit $?); exit' 1 2 13 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names starting with `-'. case $src in -*) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # Protect names starting with `-'. case $dst in -*) dst=./$dst;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writeable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; -*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test -z "$d" && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: work/libsympathy-config.src.in0000664000000000000000000000304413337271225013664 0ustar #!/bin/sh # # libsympathy-config.src.in: # # Copyright (c) 2008 James McKenzie , # All rights reserved. # # $Id: libsympathy-config.src.in,v 1.1 2008/02/03 16:20:23 james Exp $ # # $Log: libsympathy-config.src.in,v $ # Revision 1.1 2008/02/03 16:20:23 james # *** empty log message *** # # # # prefix=@prefix@ exec_prefix=@exec_prefix@ exec_prefix_set=no usage() { cat <&2 fi while test $# -gt 0; do case "$1" in -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac case $1 in --prefix=*) prefix=$optarg if test $exec_prefix_set = no ; then exec_prefix=$optarg fi ;; --prefix) echo_prefix=yes ;; --exec-prefix=*) exec_prefix=$optarg exec_prefix_set=yes ;; --exec-prefix) echo_exec_prefix=yes ;; --version) echo %VERSION% exit 0 ;; --cflags) if test "@includedir@" != /usr/include ; then includes="-I@includedir@" fi echo_cflags=yes ;; --libs) echo_libs=yes ;; *) usage 1 1>&2 ;; esac shift done if test "$echo_prefix" = "yes"; then echo $prefix fi if test "$echo_exec_prefix" = "yes"; then echo $exec_prefix fi if test "$echo_cflags" = "yes"; then echo $includes fi if test "$echo_libs" = "yes"; then echo -L@libdir@ -lsympathy fi work/maintainer/0000775000000000000000000000000013337271225011064 5ustar work/maintainer/make_distn0000775000000000000000000000052213337271225013127 0ustar #! /bin/sh # # make_distn: # # Copyright (c) 2008 James McKenzie , # All rights reserved. # # $Id: make_distn,v 1.1 2008/02/03 16:20:24 james Exp $ # # $Log: make_distn,v $ # Revision 1.1 2008/02/03 16:20:24 james # *** empty log message *** # # # # # ./maintainer/bootstrap ./configure make dist make distclean work/maintainer/tag0000775000000000000000000000221613337271225011566 0ustar #!/bin/sh # # tag: # # Copyright (c) 2008 James McKenzie , # All rights reserved. # # $Id: tag,v 1.6 2008/03/03 18:21:17 james Exp $ # # $Log: tag,v $ # Revision 1.6 2008/03/03 18:21:17 james # *** empty log message *** # # Revision 1.5 2008/02/27 16:01:25 james # *** empty log message *** # # Revision 1.4 2008/02/27 15:17:56 james # *** empty log message *** # # Revision 1.3 2008/02/27 09:50:15 james # *** empty log message *** # # Revision 1.2 2008/02/27 09:49:25 james # *** empty log message *** # # Revision 1.1 2008/02/03 16:20:24 james # *** empty log message *** # # # # set -x cvs update -d cvs commit -m "" FILES=`cat version-files` CHK=`cat $FILES | md5sum | awk '{print $1}'` TG=`grep $CHK version-md5sums | awk '{print $2}'` if [ .$TG != . ]; then echo This code already tagged as Version $TG exit 0 fi MAJOR=`cat version-major` MINOR=`cat version-minor` MICRO=$[ `cat version-micro` + 1 ] echo $MICRO > version-micro STP=`date '+"%B %d, %Y"'` echo "$CHK ${MAJOR}.${MINOR}.${MICRO}" >> version-md5sums echo "$CHK $STP" >> version-stamps cvs commit -m "" cvs tag libsympathy-${MAJOR}_${MINOR}_${MICRO} . work/maintainer/tidy0000775000000000000000000000136313337271225011766 0ustar #!/bin/sh # # tidy: # # Copyright (c) 2008 James McKenzie , # All rights reserved. # # $Id: tidy,v 1.1 2008/02/03 16:20:24 james Exp $ # # $Log: tidy,v $ # Revision 1.1 2008/02/03 16:20:24 james # *** empty log message *** # # # # if [ -f Makefile ]; then make distclean fi for i in acconfig.h AUTHORS bstrap ChangeLog configure.in COPYING INSTALL mdist NEWS README tidy src/config.h.in `find . -name Makefile.am -print` `find . -name \*.[ch] -print` ; do if [ -f $i ]; then gimme $i fi done find . -name \*.[ch] -print | xargs indent -i2 -ts0 find . -name \*~ -print| xargs /bin/rm -f find . -name \*.BAK -print| xargs /bin/rm -f find . -name a.out -print| xargs /bin/rm -f find . -name core -print| xargs /bin/rm -f work/missing0000775000000000000000000001533013337271225010336 0ustar #! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2013-10-28.13; # UTC # Copyright (C) 1996-2014 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # 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, 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 to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: work/serialmgr/0000775000000000000000000000000013337271225010722 5ustar work/serialmgr/run_sympathy0000775000000000000000000000023713337271225013414 0ustar #!/usr/bin/env perl # # $Id: run_sympathy,v 1.1 2008/05/09 13:06:50 staffcvs Exp $ # exec '@prefix@/bin/sympathy', '-c', '-k', $ENV{HOME} . '/console-socket'; work/serialmgr/serialmgrd0000775000000000000000000002671013337271225013007 0ustar #!/usr/bin/env perl # #$Id: serialmgrd,v 1.25 2009/06/27 18:24:33 staffcvs Exp $ # use Data::Dumper; use Error qw(:try); use POSIX; use Sys::Syslog; my $stuff = []; my $hosts = []; my $hup = 0; my $consolidate_exe = "/usr/bin/consolidate"; my $sympathy_exe = "/usr/bin/sympathy"; my @keys = qw(host portcode baud task user password name options); my $labeling = { shedu => { offsets => [ 0, 7, 3, 11, 15 ], }, phoenix => { offsets => [ 0, 3, 11, 15 ], }, leprechaun => { offsets => [ 0, 3 ], }, imp => { offsets => [ 0, 3 ], }, pixie => { offsets => [ 0, 3, 11 ], }, basilisk => { offsets => [ 0, 3, 11, 7, 15 ], }, wyvern => { offsets => [ 0, 3, 11 ], }, goblin => { offsets => [ 0, 3 ], }, naga => { offsets => [ 0, 5 ], }, dragon => { offsets => [ 0, 3, 11 ], }, woking => { offsets => [ 0, 3, 11 ], }, }; sub port_decode($$) { my ( $host, $code ) = @_; return "/dev/ttyS" . $code if ( $code =~ /^\d+$/ ); return "/dev/ttyUSB" . $1 if ( $code =~ /^u.(\d+)$/ ); return "/dev/ttyS" . ( $labeling->{$host}->{offsets}->[$1] + $2 ) if ( $code =~ /^(\d+)\.(\d+)$/ ); return $code; } sub quit() { sleep(10); exit(1); } sub read_file() { my $lines = []; my $c; open FILE, "<" . "/etc/serialmgr/config"; while () { next if ( $_ =~ /^#/ ); chomp; @_ = split(':'); $c = 0; push @$lines, { map { $keys[ $c++ ] => $_ } @_ }; } close FILE; return $lines; } sub hostname() { my ( $sysname, $nodename, $release, $version, $machine ) = POSIX::uname(); return $1 if ( $nodename =~ /([^.]+)\./ ); return $nodename; } sub check_users($) { my $c = shift; for my $l (@$c) { my $shell; if ( $l->{task} eq "sympathy" ) { $shell = "/usr/bin/run_sympathy"; } else { $shell = "/usr/bin/run_conclient"; } if ( not defined getpwnam( $l->{user} ) ) { syslog( LOG_ERR, "creating an account for user " . $l->{user} ); mkdir "/export/home"; mkdir "/export/home/colo"; my @cmd = (); push @cmd, "useradd"; push @cmd, "-d", "/export/home/colo/" . $l->{user}; if ( length( $l->{password} ) > 2 ) { push @cmd, "-p", $l->{password}; } push @cmd, "-s", $shell; push @cmd, "-m"; push @cmd, $l->{user}; #print join( ' ', @cmd ), "\n"; system @cmd; } if ( not defined getgrnam( $l->{user} ) ) { syslog( LOG_ERR, "need to create a group for " . $l->{user} ); quit(); } my $current_shell = ( getpwnam( $l->{user} ) )[8]; my $uid = getpwnam( $l->{user} ) ; if (( $uid > 0 ) and ( $current_shell ne $shell )) { syslog( LOG_ERR, "changing shell for user " . $l->{user} . " to " . $shell ); my @cmd = (); push @cmd, "usermod"; push @cmd, "-s", $shell; push @cmd, $l->{user}; system @cmd; } if ( length( $l->{password} ) > 2 ) { my $pwd = ( getpwnam( $l->{user} ) )[1]; if ( $l->{password} ne $pwd ) { syslog( LOG_ERR, "changing password for user " . $l->{user} ); my @cmd = (); push @cmd, "usermod"; push @cmd, "-p", $l->{password}; push @cmd, $l->{user}; system @cmd; } } if ( $l->{user} eq 'root' ) { } elsif ( ! -d "/export/home/colo/".$l->{user} ) { syslog( LOG_ERR, "need to create a home directory for " . $l->{user} ); quit(); } elsif ( ( getpwnam( $l->{user} ) )[2] != ( stat _ )[4] || ( getpwnam( $l->{user} ) )[3] != ( stat _ )[5] ) { syslog( LOG_ERR, "changing home directory ownership for user " . $l->{user} ); my @cmd = (); push @cmd, "chown", "-R"; push @cmd, $l->{user}.".".$l->{user}; push @cmd, "/export/home/colo/".$l->{user}; system @cmd; } } } sub resolve_users($) { my $c = shift; my $ret=[]; my $host = hostname(); for my $l (@$c) { next if ( $l->{host} ne $host ); my $uid = $l->{user}; my $gid = $l->{user}; if ( $uid =~ /[^\d]/ ) { $uid = getpwnam($uid); if ( !defined($uid) ) { syslog( LOG_ERR, "unknown user " . $l->{user} ); quit(); } } if ( $gid =~ /[^\d]/ ) { $gid = getgrnam($gid); if ( !defined($gid) ) { syslog( LOG_ERR, "unknown group " . $l->{user} ); quit(); } } $l->{uid} = $uid; $l->{gid} = $gid; $l->{backoff} = 0; $l->{badstarts} = 0; $l->{running} = 0; if ( $l->{uid} > 0 ) { $l->{socket} = "/export/home/colo/" . $l->{user} . "/console-socket"; $l->{socket_dir} = "/export/home/colo/" . $l->{user}; $l->{log} = "/export/home/colo/" . $l->{user} . "/logs/console"; $l->{log_dir} = "/export/home/colo/" . $l->{user} . "/logs"; } else { if ( $l->{task} eq "sympathy" ) { $l->{socket} = "/root/sympathy/" . $l->{name}; $l->{socket_dir} = "/root/sympathy"; $l->{log} = "/root/sympathy/" . $l->{name} . ".log"; $l->{log_dir} = "/root/sympathy"; } else { $l->{socket} = "/root/consoles/" . $l->{name}; $l->{socket_dir} = "/root/consoles"; $l->{log} = "/root/consoles/" . $l->{name} . ".log"; $l->{log_dir} = "/root/consoles"; } } push @$ret,$l; } return $ret; } sub get_config() { my $cf = read_file(); my $stuff = []; # my $host = hostname(); for $line (@$cf) { # if ( $line->{host} eq $host ) { $line->{device} = port_decode( $line->{host}, $line->{portcode} ); push @$stuff, $line; # } } return $stuff; } sub task_exe_args ($) { my ($t) = @_; my @args; my $exe; if ( $t->{task} eq "sympathy" ) { push @args, "-S"; push @args, "-s"; push @args, "-F"; push @args, "-d"; push @args, $t->{device}; push @args, "-b"; push @args, $t->{baud}; push @args, "-K"; push @args, "-k"; push @args, $t->{socket}; push @args, "-L"; push @args, $t->{log}; push @args, "-R"; push @args, $t->{options} if $t->{options}; $exe = $sympathy_exe; } else { push @args, "-d"; push @args, "-e"; push @args, "-s"; push @args, $t->{baud} . ",n,8"; push @args, "-f"; push @args, "none"; push @args, "-l"; push @args, "1048576"; push @args, $t->{device}; push @args, $t->{log}; push @args, $t->{socket}; push @args, $t->{options} if $t->{options}; $exe = $consolidate_exe; } return ($exe, @args); } sub task_info_string ($) { my ($t) = @_; return join "\0", $t->{uid}, $t->{gid}, task_exe_args($t); } sub start($) { my $t = shift; $t->{started} = time(); my $pid = fork(); if ( !defined($pid) ) { syslog( LOG_ERR, "fork failed" ); return undef; } elsif ( $pid != 0 ) { $t->{pid} = $pid; $t->{running} = 1; syslog( LOG_ERR, "Started " . $t->{task} . " for " . $t->{name} . " on " . $t->{device} . " (" . $t->{portcode} . ") pid " . $t->{pid} ); return $pid; } # use sympathy to clean up any old lock files whilst we're still root system( $sympathy_exe, "-S", "-C", "-d", $t->{device} ); chown $t->{gid}, $t->{uid}, $t->{device}; $( = $) = $t->{gid} if ( $t->{gid} != 0 ); $< = $> = $t->{uid} if ( $t->{uid} != 0 ); mkdir $t->{socket_dir}; mkdir $t->{log_dir}; my ($exe, @args) = task_exe_args($t); syslog(LOG_ERR, $exe. " ". join( ' ', @args )); exec( $exe, @args ); exit(1); } sub taskinfo ($) { my ($t) = @_; return $t->{task} . " for " . $t->{name} . " on " . $t->{device} . " (" . $t->{portcode} . ") pid " . $t->{pid}; } sub died($) { my $t = shift; my $ranfor = $t->{ended} - $t->{started}; syslog( LOG_ERR, "Finished " . $t->{task} . " for " . $t->{name} . " on " . $t->{device} . " (" . $t->{portcode} . ") pid " . $t->{pid} . " lasted " . $ranfor . "s" ); if ( $ranfor < 20 ) { $t->{badstarts}++; } if ( $t->{badstarts} > 5 ) { syslog( LOG_ERR, "Looping " . taskinfo( $t ) . " suspended" ); $t->{backoff} = time() + 5 * 60; $t->{badstarts} = 0; } $t->{pid} = undef; } sub hup() { $hup++; } sub medea($) { my ($killstuff) = @_; for $t (@$killstuff) { kill POSIX::SIGTERM, $t->{pid} if ( defined( $t->{pid} ) ); } } sub terminate() { syslog( LOG_ERR, "shutting down on signal" ); medea($stuff); exit(0); } sub sigchld() { for (;;) { my $got = waitpid -1, WNOHANG; last if $got<=0; my ($t) = grep { $_->{running} and $_->{pid} == $got } @$stuff; if ($t) { syslog( LOG_INFO, "Terminated " . taskinfo( $t ). ": $?" ); $t->{ended} = time(); $t->{running} = 0; } else { syslog( LOG_INFO, "Terminated unknown pid $got: $?" ); } } } openlog( "serialmgrd", "pid,console", LOG_LOCAL0 ); syslog( LOG_ERR, "starts" ); $stuff = get_config(); check_users($stuff); $stuff=resolve_users($stuff); $SIG{HUP} = \&hup; $SIG{INT} = $SIG{TERM} = \&terminate; $SIG{CHLD} = \&sigchld; while (1) { my $now = time(); sigchld(); for $t (@$stuff) { if ( defined $t->{pid} ) { if ( ( $t->{running} ) and ( kill( 0, $t->{pid} ) == 0 ) ) { $t->{running} = 0; $t->{ended} = time(); } if ( not $t->{running} ) { died($t); } } if ( ( not defined( $t->{pid} ) ) and ( $t->{backoff} < $now ) ) { start($t); } } if ( scalar(@$stuff) < 1 ) { syslog( LOG_ERR, "Nothing to do - sleeping 3600s" ); sleep(3600); } if ($hup) { $hup = 0; syslog( LOG_ERR, "SIGHUP rereading config" ); my $oldstuff = $stuff; my %oldmap; foreach my $t (@$stuff) { $oldmap{ task_info_string $t } = $t; } $stuff = get_config(); check_users($stuff); $stuff=resolve_users($stuff); foreach my $t (@$stuff) { my $old = $oldmap{ task_info_string $t }; next unless $old && $old->{running}; foreach my $key (qw(running started ended pid)) { $t->{$key} = $old->{$key}; $old->{$key} = undef; } syslog( LOG_INFO, "Keeping " . taskinfo($t) ); } medea($oldstuff); } sleep(10); } work/src/0000775000000000000000000000000013337271225007524 5ustar work/src/Makefile.am0000664000000000000000000000774513337271225011575 0ustar # # # Makefile.am: # # Copyright (c) 2008 James McKenzie , # All rights reserved. # # $Id: Makefile.am,v 1.24 2008/03/07 13:16:02 james Exp $ # # $Log: Makefile.am,v $ # Revision 1.24 2008/03/07 13:16:02 james # *** empty log message *** # # Revision 1.23 2008/03/06 16:49:05 james # *** empty log message *** # # Revision 1.22 2008/03/03 06:04:18 james # *** empty log message *** # # Revision 1.21 2008/02/28 22:55:27 staffcvs # *** empty log message *** # # Revision 1.20 2008/02/27 15:04:32 james # *** empty log message *** # # Revision 1.19 2008/02/27 10:47:34 james # *** empty log message *** # # Revision 1.18 2008/02/26 23:23:17 james # *** empty log message *** # # Revision 1.17 2008/02/24 00:42:53 james # *** empty log message *** # # Revision 1.16 2008/02/22 23:39:27 james # *** empty log message *** # # Revision 1.15 2008/02/15 16:48:56 james # *** empty log message *** # # Revision 1.14 2008/02/15 03:32:07 james # *** empty log message *** # # Revision 1.13 2008/02/14 16:21:17 james # *** empty log message *** # # Revision 1.12 2008/02/14 02:46:44 james # *** empty log message *** # # Revision 1.11 2008/02/14 01:55:57 james # *** empty log message *** # # Revision 1.10 2008/02/13 18:05:06 james # *** empty log message *** # # Revision 1.9 2008/02/13 16:57:29 james # *** empty log message *** # # Revision 1.8 2008/02/13 09:12:20 james # *** empty log message *** # # Revision 1.7 2008/02/12 22:36:46 james # *** empty log message *** # # Revision 1.6 2008/02/09 15:47:28 james # *** empty log message *** # # Revision 1.5 2008/02/08 15:06:42 james # *** empty log message *** # # Revision 1.4 2008/02/07 01:04:16 james # *** empty log message *** # # Revision 1.3 2008/02/07 00:39:13 james # *** empty log message *** # # Revision 1.2 2008/02/04 01:32:39 james # *** empty log message *** # # Revision 1.1 2008/02/03 16:20:24 james # *** empty log message *** # # # # INCLUDES= # NB order here matters. PROJECTHDRS= crt.h utf8.h tty.h ansi.h vt102.h keys.h history.h ring.h slide.h \ log.h ipc.h symsocket.h keydis.h cmd.h lockfile.h rx.h \ context.h vt102_charset.h prototypes.h HDRS=project.h ${PROJECTHDRS} SRCS=ansi.c crt.c html.c libsympathy.c render.c version.c vt102.c tty.c \ keydis.c history.c ring.c ptty.c terminal.c util.c log.c ipc.c \ slide.c symsocket.c serial.c cmd.c lockfile.c utf8.c vt102_charset.c \ rotate.c raw.c CPROTO=cproto SYMPATHYSRCS=${SRCS} noinst_HEADERS= prototypes.h ${HDRS} EXTRA_DIST=sympathy.h.tail clean-local: -rm -f sympathy.h version.h version-num libsympathy_a_SOURCES = ${SYMPATHYSRCS} libsympathy_la_SOURCES = ${SYMPATHYSRCS} libsympathy_a_CFLAGS = ${AM_CFLAGS} BUILT_SOURCES = version.h sympathy.h lib_LIBRARIES=libsympathy.a lib_LTLIBRARIES=libsympathy.la include_HEADERS=sympathy.h AM_CFLAGS=-g -Werror libsympathy_la_LDFLAGS = \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -release $(LT_RELEASE) \ -export-dynamic VFD=${srcdir}/.. VF=${shell cat ${VFD}/version-files} VFS=${VF:%=${VFD}/%} VCHK=${shell cat ${VFS} | @MD5SUM@ | @AWK@ '{print $$1 }' } VNUM=${shell @GREP@ ${VCHK} ${VFD}/version-md5sums | @AWK@ '{ print $$2 }' } VDEF=${shell echo `cat ${VFD}/version-major`.`cat ${VFD}/version-minor`.`cat ${VFD}/version-micro` } protos: sympathy.h echo > prototypes.h ${CPROTO} -e -v ${INCLUDES} ${SRCS} > prototypes.tmp mv -f prototypes.tmp prototypes.h tidy: ${SRCS} ${HDRS} indent -i2 -ts0 ${SRCS} ${HDRS} /bin/rm -f *~ sympathy.h: ${PROJECTHDRS} sympathy.h.head sympathy.h.tail cat sympathy.h.head ${PROJECTHDRS} sympathy.h.tail > $@ || /bin/rm -f $@ version.h: $(VFD)/version-files $(VFD)/version-major \ $(VFD)/version-minor $(VFD)/version-micro \ $(VFD)/version-md5sums ${VFS} if [ .${VNUM} = . ]; then \ echo "#define VERSION \"libsympathy Version ${VDEF} + Edits\"" > version.h; \ echo ${VDEF}-E > version-num; \ else \ echo "#define VERSION \"libsympathy Version ${VNUM}\"" > version.h; \ echo ${VNUM} > version-num; \ fi work/src/ansi.c0000664000000000000000000004640713337271225010635 0ustar /* * ansi.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: ansi.c,v 1.50 2008/03/07 13:16:02 james Exp $"; /* * $Log: ansi.c,v $ * Revision 1.50 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.49 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.48 2008/03/06 22:51:39 james * *** empty log message *** * * Revision 1.47 2008/03/06 21:34:09 james * *** empty log message *** * * Revision 1.46 2008/03/06 21:33:02 james * *** empty log message *** * * Revision 1.45 2008/03/06 17:21:41 james * *** empty log message *** * * Revision 1.44 2008/03/06 16:49:05 james * *** empty log message *** * * Revision 1.43 2008/03/06 01:41:48 james * *** empty log message *** * * Revision 1.42 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.41 2008/03/02 12:30:54 staffcvs * *** empty log message *** * * Revision 1.40 2008/03/02 10:50:32 staffcvs * *** empty log message *** * * Revision 1.39 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.38 2008/03/02 10:27:24 james * *** empty log message *** * * Revision 1.37 2008/02/29 22:50:29 james * *** empty log message *** * * Revision 1.36 2008/02/28 22:00:42 james * *** empty log message *** * * Revision 1.35 2008/02/28 16:57:51 james * *** empty log message *** * * Revision 1.34 2008/02/27 09:42:53 james * *** empty log message *** * * Revision 1.33 2008/02/27 09:42:21 james * *** empty log message *** * * Revision 1.32 2008/02/26 23:56:12 james * *** empty log message *** * * Revision 1.31 2008/02/26 23:23:17 james * *** empty log message *** * * Revision 1.30 2008/02/24 00:42:53 james * *** empty log message *** * * Revision 1.29 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.28 2008/02/22 17:07:00 james * *** empty log message *** * * Revision 1.27 2008/02/20 22:54:22 staffcvs * *** empty log message *** * * Revision 1.26 2008/02/20 20:16:07 james * *** empty log message *** * * Revision 1.25 2008/02/20 19:44:37 james * @@ * * Revision 1.24 2008/02/20 19:36:06 james * @@ * * Revision 1.23 2008/02/20 19:25:09 james * *** empty log message *** * * Revision 1.22 2008/02/15 03:32:07 james * *** empty log message *** * * Revision 1.21 2008/02/14 02:46:44 james * *** empty log message *** * * Revision 1.20 2008/02/14 01:55:57 james * *** empty log message *** * * Revision 1.19 2008/02/13 16:57:29 james * *** empty log message *** * * Revision 1.18 2008/02/13 09:12:21 james * *** empty log message *** * * Revision 1.17 2008/02/13 01:08:18 james * *** empty log message *** * * Revision 1.16 2008/02/07 13:22:51 james * *** empty log message *** * * Revision 1.15 2008/02/07 13:19:48 james * *** empty log message *** * * Revision 1.14 2008/02/07 12:21:16 james * *** empty log message *** * * Revision 1.13 2008/02/07 12:16:04 james * *** empty log message *** * * Revision 1.12 2008/02/07 11:32:41 james * *** empty log message *** * * Revision 1.11 2008/02/07 11:11:14 staffcvs * *** empty log message *** * * Revision 1.10 2008/02/07 01:02:52 james * *** empty log message *** * * Revision 1.9 2008/02/07 00:43:27 james * *** empty log message *** * * Revision 1.8 2008/02/07 00:39:13 james * *** empty log message *** * * Revision 1.7 2008/02/06 20:26:57 james * *** empty log message *** * * Revision 1.6 2008/02/06 17:53:28 james * *** empty log message *** * * Revision 1.5 2008/02/06 15:53:22 james * *** empty log message *** * * Revision 1.4 2008/02/04 20:23:55 james * *** empty log message *** * * Revision 1.3 2008/02/04 05:45:55 james * :: * * Revision 1.2 2008/02/04 02:05:06 james * *** empty log message *** * * Revision 1.1 2008/02/03 23:31:25 james * *** empty log message *** * */ #include "project.h" static int ansi_move (ANSI * a, CRT_Pos p) { char buf[16]; int n; int dx = p.x - a->pos.x; int dy = p.y - a->pos.y; int err = 0; // a->pos.x = ANSI_INVAL; if (a->pos.x != ANSI_INVAL) { if ((!dx) && (!dy)) return 0; if (!dy) { if (dx == 1) { if (a->terminal->xmit (a->terminal, "\033[C", 3) != 3) err++; } else if (dx == -1) { if (a->terminal->xmit (a->terminal, "\033[D", 3) != 3) err++; } else { n = snprintf (buf, sizeof (buf), "\033[%dG", p.x + 1); if (a->terminal->xmit (a->terminal, buf, n) != n) err++; } } else if (!dx) { if (dy == -1) { if (a->terminal->xmit (a->terminal, "\033[A", 3) != 3) err++; } else if (dy == 1) { if (a->terminal->xmit (a->terminal, "\033[B", 3) != 3) err++; } else if (dy < 0) { n = snprintf (buf, sizeof (buf), "\033[%dA", -dy); if (a->terminal->xmit (a->terminal, buf, n) != n) err++; } else { n = snprintf (buf, sizeof (buf), "\033[%dB", dy); if (a->terminal->xmit (a->terminal, buf, n) != n) err++; } } else if (!p.x) { if (dy == 1) { if (a->terminal->xmit (a->terminal, "\033[E", 3) != 3) err++; } else if (dy == -1) { if (a->terminal->xmit (a->terminal, "\033[F", 3) != 3) err++; } else if (dy > 0) { n = snprintf (buf, sizeof (buf), "\033[%dE", dy); if (a->terminal->xmit (a->terminal, buf, n) != n) err++; } else { n = snprintf (buf, sizeof (buf), "\033[%dF", -dy); if (a->terminal->xmit (a->terminal, buf, n) != n) err++; } } else { n = snprintf (buf, sizeof (buf), "\033[%d;%dH", p.y + 1, p.x + 1); if (a->terminal->xmit (a->terminal, buf, n) != n) err++; } } else { n = snprintf (buf, sizeof (buf), "\033[%d;%dH", p.y + 1, p.x + 1); if (a->terminal->xmit (a->terminal, buf, n) != n) err++; } a->pos = p; return err; } static int ansi_showhide_cursor (ANSI * a, int hide) { int err = 0; if (a->hide_cursor == hide) return err; if (hide) { if (a->terminal->xmit (a->terminal, "\033[?25l", 6) != 6) err++; } else { if (a->terminal->xmit (a->terminal, "\033[?25h", 6) != 6) err++; } a->hide_cursor = hide; return err; } static int ansi_force_attr_normal (ANSI * a) { if (a->terminal->xmit (a->terminal, "\033[0m", 4) != 4) return 1; a->attr = CRT_ATTR_NORMAL; a->color = ANSI_INVAL; return 0; } static int ansi_set_title (ANSI * a, char *t) { char buf[1024]; int i; char *term = getenv ("TERM"); if (!term) return 0; if (strncmp (term, "xterm", 5) && strncmp (term, "rxvt", 4)) return 0; i = sprintf (buf, "\033]0;%s\007", t); if (a->terminal->xmit (a->terminal, buf, i) != i) return 1; return 0; } static int ansi_set_color (ANSI * a, int color) { int dif; char buf[16]; int i; int fg, bg; if ((a->color != ANSI_INVAL) && (color == a->color)) return 0; fg = CRT_COLOR_FG (color); bg = CRT_COLOR_BG (color); if (fg & CRT_COLOR_INTENSITY) { fg += 90; } else { fg += 30; } if (bg & CRT_COLOR_INTENSITY) { bg += 100; } else { bg += 40; } i = sprintf (buf, "\033[%d;%dm", fg, bg); #if 0 fprintf (stderr, "Color set to %d %d %x\n", fg, bg, color); #endif if (a->terminal->xmit (a->terminal, buf, i) != i) return 1; a->color = color; return 0; } static int ansi_set_attr (ANSI * a, int attr) { int dif; int err = 0; dif = attr ^ a->attr; if (!dif) return 0; a->attr = attr; #if 0 if (attr == CRT_ATTR_NORMAL) { ansi_force_attr_normal (a); return; } #endif if (dif & CRT_ATTR_UNDERLINE) { if (attr & CRT_ATTR_UNDERLINE) { if (a->terminal->xmit (a->terminal, "\033[4m", 4) != 4) err++; } else { if (a->terminal->xmit (a->terminal, "\033[24m", 5) != 5) err++; } } if (dif & CRT_ATTR_REVERSE) { if (attr & CRT_ATTR_REVERSE) { if (a->terminal->xmit (a->terminal, "\033[7m", 4) != 4) err++; } else { if (a->terminal->xmit (a->terminal, "\033[27m", 5) != 5) err++; } } if (dif & CRT_ATTR_BOLD) { if (attr & CRT_ATTR_BOLD) { if (a->terminal->xmit (a->terminal, "\033[1m", 4) != 4) err++; } else { if (a->terminal->xmit (a->terminal, "\033[22m", 5) != 5) err++; } } return err; } static int ascii_emit (TTY * t, uint32_t ch) { int i; /* Some quick obvious subsititons for quotation marks */ switch (ch) { case 0x2018: ch = '`'; break; case 0x2019: ch = '\''; break; case 0x201c: case 0x201d: ch = '"'; break; } /* Short cut the easy stuff */ if (ch < 0x7f) { uint8_t c = ch; return (t->xmit (t, &c, 1) == 1) ? 0 : -1; } for (i = 0; i < VT102_CHARSET_SIZE; ++i) { if (vt102_charset_gl[i] == ch) { uint8_t c[3] = { 016, i, 017 }; return (t->xmit (t, &c, 3) == 3) ? 0 : -1; } } return (t->xmit (t, "?", 1) == 1) ? 0 : -1; } static int ansi_render (ANSI * a, CRT_CA ca) { int err = 0; int dif; if ((ca.chr < VT102_CHARSET_SIZE) && (vt102_charset_c0[ca.chr])) ca.chr = vt102_charset_c0[ca.chr]; if ((ca.chr >= 0x80) && (ca.chr < 0xa0)) ca.chr = ' '; ansi_set_attr (a, ca.attr); ansi_set_color (a, ca.color); if (a->utf8) { if (utf8_emit (a->terminal, ca.chr)) err++; } else { if (ascii_emit (a->terminal, ca.chr)) err++; } a->pos.x++; /* Can't easily wrap round here as don't know size of destination screen */ /* so invalidate the cached cursor position */ if (a->pos.x >= a->size.x) a->pos.x = ANSI_INVAL; return err; } static int ansi_cls (ANSI * a) { CRT_Pos p = { 0 }; int err; crt_cls (&a->crt); err += ansi_set_attr (a, CRT_ATTR_NORMAL); err += ansi_set_color (a, CRT_COLOR_NORMAL); err += ansi_move (a, p); if (a->terminal->xmit (a->terminal, "\033[2J", 4) != 4) err++; /* different emulators leave cursor in different places after cls differently */ a->pos.x = ANSI_INVAL; return err; } static int ansi_draw_line (ANSI * a, CRT_CA * cap, int y) { int err = 0; CRT_Pos p = { 0, y }; CRT_CA *acap = &a->crt.screen[CRT_ADDR_POS (&p)]; for (p.x = 0; p.x < a->crt.size.x; ++p.x) { if (p.x >= a->size.x) continue; if (crt_ca_cmp (*acap, *cap)) { err += ansi_showhide_cursor (a, 1); *acap = *cap; err += ansi_move (a, p); err += ansi_render (a, *acap); } acap++; cap++; } return err; } static int ansi_resize_check (ANSI * a, CRT_Pos * size) { int err = 0; if ((size && crt_pos_cmp (a->crt.size, *size)) || crt_pos_cmp (a->terminal->size, a->size)) { terminal_getsize (a->terminal); a->size = a->terminal->size; a->pos.x = ANSI_INVAL; a->hide_cursor = ANSI_INVAL; crt_reset (&a->crt); if (size) a->crt.size = *size; // a->terminal->xmit (a->terminal, "\033c", 3); // maybe - issue 132 column command if we're 132? ansi_cls (a); if (a->terminal->xmit (a->terminal, "\033=", 2) != 2) err++; if (a->terminal->xmit (a->terminal, "\033[?6l", 5) != 5) err++; if (a->terminal->xmit (a->terminal, "\033[r", 3) != 3) err++; if (a->utf8) { if (a->terminal->xmit (a->terminal, "\033%G", 3) != 3) err++; } else { if (a->terminal->xmit (a->terminal, "\033(B", 3) != 3) err++; if (a->terminal->xmit (a->terminal, "\033)0", 3) != 3) err++; if (a->terminal->xmit (a->terminal, "\017", 1) != 3) err++; } } return err; } static int ansi_history (ANSI * a, History * h) { char buf[32]; int i; int guess_scroll; int err = 0; /* Do we need to catch up on history? */ if (a->history_ptr == h->wptr) return err; err += ansi_resize_check (a, NULL); if ((a->size.x < a->crt.size.x) || (a->size.y < a->crt.size.y)) return err; guess_scroll = a->crt.size.y - 1; /* Bototm line should be a status line */ err += ansi_force_attr_normal (a); err += ansi_set_color (a, CRT_COLOR_NORMAL); i = sprintf (buf, "\033[%d;%dr", 1, guess_scroll); if (a->terminal->xmit (a->terminal, buf, i) != i) err++; while (a->history_ptr != h->wptr) { History_ent *e = &h->lines[a->history_ptr]; HISTORY_INC (h, a->history_ptr); if (!e->valid) continue; /* If so write the line ot the top of the screen */ err += ansi_draw_line (a, e->line, 0); /* Roll guess_scroll lines up putting the top line into the xterm's history */ /* Make extra lines a predictable colour */ err += ansi_set_color (a, CRT_COLOR_NORMAL); err += ansi_showhide_cursor (a, 1); i = sprintf (buf, "\033[%d;%dH", guess_scroll, 1); if (a->terminal->xmit (a->terminal, buf, i) != i) err++; if (a->terminal->xmit (a->terminal, "\033D", 2) != 2) err++; a->pos.x = ANSI_INVAL; /* now do the same in our image of the screen */ { CRT_Pos s = { 0 } , e = { 0}; /* scroll lines up */ for (s.y++; s.y < guess_scroll; s.y++, e.y++) { memcpy (&a->crt.screen[CRT_ADDR_POS (&e)], &a->crt.screen[CRT_ADDR_POS (&s)], sizeof (CRT_CA) * a->crt.size.x); } /* erase new line */ s.y = e.y; e.x = CRT_COLS - 1; crt_erase (&a->crt, s, e, 1, CRT_COLOR_NORMAL); } } /* reset margins */ if (a->terminal->xmit (a->terminal, "\033[r", 3) != 3) err++; a->pos.x = ANSI_INVAL; return err; } static int ansi_draw (ANSI * a, CRT * c) { CRT_Pos p; int o; int hidden_cursor = 0; int err = 0; err += ansi_resize_check (a, &c->size); for (p.y = 0; p.y < a->crt.size.y; ++p.y) { if (p.y >= a->size.y) continue; err += ansi_draw_line (a, &c->screen[CRT_ADDR (p.y, 0)], p.y); } if ((c->size.x > a->size.x) || (c->size.y > a->size.y)) { char msg[1024]; // = "Window is too small"; int i; p.x = 0; p.y = 0; i = sprintf (msg, "Window too small (%dx%d need %dx%d)", a->size.x, a->size.y, c->size.x, c->size.y); err += ansi_showhide_cursor (a, 1); err += ansi_set_attr (a, CRT_ATTR_REVERSE); err += ansi_set_color (a, CRT_MAKE_COLOR (CRT_COLOR_WHITE, CRT_COLOR_RED)); err += ansi_move (a, p); if (a->terminal->xmit (a->terminal, msg, i) != i) err++; a->pos.x = ANSI_INVAL; } if ((c->pos.x >= a->size.x) || (c->pos.y >= a->size.y)) { err += ansi_showhide_cursor (a, 1); return err; } a->crt.pos = c->pos; err += ansi_move (a, a->crt.pos); a->crt.hide_cursor = c->hide_cursor; err += ansi_showhide_cursor (a, a->crt.hide_cursor); return err; } static int ansi_reset (ANSI * a, CRT * c) { a->size.x = -1; return ansi_draw (a, c ? c : &a->crt); } static void ansi_terminal_reset (ANSI * a) { CRT_Pos p = { 0, a->crt.size.y }; ansi_force_attr_normal (a); ansi_move (a, p); } static int ansi_key (ANSI * a, Context * c, int key) { if (!c->d) return c->k->key (c->k, c, key); cmd_show_status (c->d, c); if (c->d->active) { if (key == CMD_CANCEL_KEY) { return cmd_deactivate (c->d, c); } else if (key == CMD_KEY) { cmd_deactivate (c->d, c); } else { return cmd_key (c->d, c, a, key); } } else if (key == CMD_KEY) { return cmd_activate (c->d, c); } return c->k->key (c->k, c, key); } static void ansi_flush_escape (ANSI * a, Context * c) { ANSI_Parser *p = &a->parser; int i; for (i = 0; i < p->escape_ptr; ++i) { ansi_key (a, c, p->escape_buf[i]); } p->escape_ptr = 0; p->in_escape = 0; } static void ansi_parse_deckey (ANSI * a, Context * c) { ANSI_Parser *p = &a->parser; if ((p->escape_buf[1] != '[') && (p->escape_buf[1] != 'O')) { ansi_flush_escape (a, c); return; } if ((p->escape_buf[2] >= 'A') || (p->escape_buf[2] <= 'Z')) { ansi_key (a, c, KEY_UP + (p->escape_buf[2] - 'A')); } else if ((p->escape_buf[2] >= 'a') || (p->escape_buf[2] <= 'z')) { ansi_key (a, c, KEY_154 + (p->escape_buf[2] - 'a')); } else { ansi_flush_escape (a, c); return; } p->in_escape = 0; p->escape_ptr = 0; } static void ansi_parse_ansikey (ANSI * a, Context * c) { ANSI_Parser *p = &a->parser; int l = p->escape_ptr - 1; char *end; int k; if ((p->escape_buf[1] != '[') || (p->escape_buf[l] != '~')) { ansi_flush_escape (a, c); return; } k = strtol (&p->escape_buf[2], &end, 10); if (end != &p->escape_buf[l]) { ansi_flush_escape (a, c); return; } ansi_key (a, c, KEY_180 + k); p->in_escape = 0; p->escape_ptr = 0; } static void ansi_parse_escape (ANSI * a, Context * c) { ANSI_Parser *p = &a->parser; switch (p->escape_ptr) { case 0: case 1: return; case 2: switch (p->escape_buf[1]) { case '[': case 'O': break; default: ansi_flush_escape (a, c); } break; case 3: switch (p->escape_buf[1]) { case 'O': ansi_parse_deckey (a, c); break; case '[': if ((p->escape_buf[2] >= 'A') && (p->escape_buf[2] <= 'Z')) ansi_parse_deckey (a, c); break; default: ansi_flush_escape (a, c); } break; case 4: case 5: case 6: case 7: if (p->escape_buf[p->escape_ptr - 1] == '~') ansi_parse_ansikey (a, c); break; default: ansi_flush_escape (a, c); } } static void ansi_check_escape (ANSI * a, Context * c) { ANSI_Parser *p = &a->parser; struct timeval now, diff; gettimeofday (&now, NULL); timersub (&now, &p->last_escape, &diff); #if 0 fprintf (stderr, "ie %d tl %d.%06d eb %d\n", p->in_escape, diff.tv_sec, diff.tv_usec, p->escape_ptr); #endif if (!p->in_escape) return; /* Time up? */ if (diff.tv_sec || (diff.tv_usec > ANSI_ESCAPE_TIMEOUT)) ansi_flush_escape (a, c); } static void ansi_parse_char (ANSI * a, Context * c, int ch) { ANSI_Parser *p = &a->parser; /* See if it's time to flush the escape */ ansi_check_escape (a, c); if (ch == 033) { if (p->in_escape) ansi_flush_escape (a, c); p->in_escape++; p->escape_ptr = 0; gettimeofday (&p->last_escape, NULL); } if (p->in_escape) { p->escape_buf[p->escape_ptr++] = ch; ansi_parse_escape (a, c); } else { ansi_key (a, c, ch); } } static void ansi_parse (ANSI * a, Context * c, char *buf, int len) { while (len--) ansi_parse_char (a, c, *(buf++)); } static int ansi_dispatch (ANSI * a, Context * c) { char buf[1024]; int red; ansi_check_escape (a, c); if (!a->terminal) return 0; red = a->terminal->recv (a->terminal, buf, sizeof (buf)); if (red <= 0) return red; ansi_parse (a, c, buf, red); return 0; } static int ansi_update (ANSI * a, Context * c) { int err = 0; err += ansi_history (a, c->h); err += ansi_draw (a, &c->v->crt); tty_length (a->terminal, c->v->crt.size.y); return err; } static void ansi_free (ANSI * a) { a->terminal_reset (a); if (a->terminal) a->terminal->close (a->terminal); free (a); } ANSI * ansi_new_from_terminal (TTY * t, int utf8) { ANSI *ret; ret = xmalloc (sizeof (ANSI)); memset (ret, 0, sizeof (ANSI)); ret->terminal = t; ret->utf8 = utf8; ret->update = ansi_update; ret->reset = ansi_reset; ret->terminal_reset = ansi_terminal_reset; ret->set_title = ansi_set_title; ret->close = ansi_free; ret->dispatch = ansi_dispatch; return ret; } work/src/ansi.h0000664000000000000000000000514113337271225010630 0ustar /* * ansi.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: ansi.h,v 1.20 2008/03/10 11:49:32 james Exp $ */ /* * $Log: ansi.h,v $ * Revision 1.20 2008/03/10 11:49:32 james * *** empty log message *** * * Revision 1.19 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.18 2008/03/06 21:34:09 james * *** empty log message *** * * Revision 1.17 2008/03/06 21:33:02 james * *** empty log message *** * * Revision 1.16 2008/03/06 16:49:05 james * *** empty log message *** * * Revision 1.15 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.14 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.13 2008/02/24 00:42:53 james * *** empty log message *** * * Revision 1.12 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.11 2008/02/20 20:16:07 james * *** empty log message *** * * Revision 1.10 2008/02/20 19:44:37 james * @@ * * Revision 1.9 2008/02/20 19:36:06 james * @@ * * Revision 1.8 2008/02/20 19:25:09 james * *** empty log message *** * * Revision 1.7 2008/02/13 16:57:29 james * *** empty log message *** * * Revision 1.6 2008/02/13 01:08:18 james * *** empty log message *** * * Revision 1.5 2008/02/07 12:16:04 james * *** empty log message *** * * Revision 1.4 2008/02/07 00:43:27 james * *** empty log message *** * * Revision 1.3 2008/02/07 00:39:13 james * *** empty log message *** * * Revision 1.2 2008/02/06 11:30:37 james * *** empty log message *** * * Revision 1.1 2008/02/03 23:31:25 james * *** empty log message *** * */ #ifndef __ANSI_H__ #define __ANSI_H__ #define ANSI_INVAL -1 #define ANSI_ESCAPE_BUF_LEN 10 #define ANSI_ESCAPE_TIMEOUT 100000 /* in ms */ typedef struct { int in_escape; struct timeval last_escape; char escape_buf[ANSI_ESCAPE_BUF_LEN]; int escape_ptr; } ANSI_Parser; struct CRT_struct; struct Context_struct; typedef struct ANSI_struct { ANSI_Parser parser; TTY *terminal; int eof; CRT crt; CRT_Pos pos; CRT_Pos size; int hide_cursor; int attr; int color; int utf8; int history_ptr; FILE *file; int (*dispatch) (struct ANSI_struct *, struct Context_struct *); int (*update) (struct ANSI_struct *, struct Context_struct *); int (*one_shot) (struct ANSI_struct *, struct CRT_struct *); int (*reset) (struct ANSI_struct *, struct CRT_struct *); int (*set_title) (struct ANSI_struct *, char *); void (*terminal_reset) (struct ANSI_struct *); void (*close) (struct ANSI_struct *); } ANSI; #endif /* __ANSI_H__ */ work/src/cmd.c0000664000000000000000000000721213337271225010435 0ustar /* * cmd.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: cmd.c,v 1.13 2008/03/07 13:16:02 james Exp $"; /* * $Log: cmd.c,v $ * Revision 1.13 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.12 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.11 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.10 2008/03/02 10:50:32 staffcvs * *** empty log message *** * * Revision 1.9 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.8 2008/02/29 22:50:29 james * *** empty log message *** * * Revision 1.7 2008/02/28 22:00:42 james * *** empty log message *** * * Revision 1.6 2008/02/28 16:57:51 james * *** empty log message *** * * Revision 1.5 2008/02/28 15:37:06 james * *** empty log message *** * * Revision 1.4 2008/02/28 11:27:48 james * *** empty log message *** * * Revision 1.3 2008/02/22 17:07:00 james * *** empty log message *** * * Revision 1.2 2008/02/15 23:52:12 james * *** empty log message *** * * Revision 1.1 2008/02/15 15:14:19 james * *** empty log message *** * */ #include "project.h" int cmd_parse (Cmd * c, Context * ctx, ANSI * a, char *buf) { if (!strcmp (buf, "quit")) c->disconnect++; else if (!strcmp (buf, "flow")) ctx->k->set_flow (ctx->k, ctx, 1); else if (!strcmp (buf, "noflow")) ctx->k->set_flow (ctx->k, ctx, 0); else if (!strcmp (buf, "ansi")) ctx->k->set_ansi (ctx->k, ctx, 0); else if (!strcmp (buf, "noansi")) ctx->k->set_ansi (ctx->k, ctx, 1); else if (!strncmp (buf, "baud", 4)) ctx->k->set_baud (ctx->k, ctx, atoi (buf + 4)); else if (!strcmp (buf, "break")) ctx->k->send_break (ctx->k, ctx); else if (!strcmp (buf, "hangup")) ctx->k->hangup (ctx->k, ctx); else if (!strcmp (buf, "reset")) ctx->k->reset (ctx->k, ctx); else if (!strcmp (buf, "expand")) { int w = a->terminal->size.x; int h = a->terminal->size.y - 1; ctx->k->set_size (ctx->k, ctx, w, h); } else if (!strncmp (buf, "width", 5)) ctx->k->set_size (ctx->k, ctx, atoi (buf + 5), 0); else if (!strncmp (buf, "height", 6)) ctx->k->set_size (ctx->k, ctx, 0, atoi (buf + 6)); else return -1; return 0; } void cmd_show_status (Cmd * c, Context * ctx) { if (!ctx->v) return; if (c->error) vt102_status_line (ctx->v, "Command not recognized - press any key"); else if (!c->active) vt102_status_line (ctx->v, c->csl); else vt102_status_line (ctx->v, c->buf); } int cmd_key (Cmd * c, Context * ctx, ANSI * a, int key) { if (c->error) { c->error = 0; c->active = 0; cmd_show_status (c, ctx); return 0; } if (key == 13) { if (cmd_parse (c, ctx, a, c->buf + 1)) { c->error++; } else { c->active = 0; } cmd_show_status (c, ctx); return 0; } if (((key == 8) || (key == 127)) && (c->ptr > 1)) { c->ptr--; c->buf[c->ptr] = 0; } if ((key >= 32) && (key < 127)) { c->buf[c->ptr] = key; c->ptr++; c->buf[c->ptr] = 0; } cmd_show_status (c, ctx); return 0; } int cmd_deactivate (Cmd * c, Context * ctx) { c->active = 0; cmd_show_status (c, ctx); return 0; } int cmd_activate (Cmd * c, Context * ctx) { c->active = 1; c->ptr = 1; c->buf[0] = ':'; c->buf[1] = 0; cmd_show_status (c, ctx); return 0; } void cmd_new_status (Cmd * c, Context * ctx, char *msg) { strcpy (c->csl, msg); cmd_show_status (c, ctx); } Cmd * cmd_new (void) { Cmd *ret; ret = (Cmd *) xmalloc (sizeof (Cmd)); ret->disconnect = 0; ret->active = 0; ret->error = 0; ret->csl[0] = 0; } work/src/cmd.h0000664000000000000000000000206613337271225010444 0ustar /* * cmd.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: cmd.h,v 1.8 2008/03/10 11:49:32 james Exp $ */ /* * $Log: cmd.h,v $ * Revision 1.8 2008/03/10 11:49:32 james * *** empty log message *** * * Revision 1.7 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.6 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.5 2008/03/02 12:30:54 staffcvs * *** empty log message *** * * Revision 1.4 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.3 2008/02/28 11:27:48 james * *** empty log message *** * * Revision 1.2 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.1 2008/02/15 15:14:19 james * *** empty log message *** * */ #ifndef __CMD_H__ #define __CMD_H__ #define CMD_KEY 2 /* CTRL B */ #define CMD_CANCEL_KEY 3 /* CTRL C */ typedef struct { int active; int error; int disconnect; char csl[128]; char buf[128]; int ptr; } Cmd; #endif /* __CMD_H__ */ work/src/context.h0000664000000000000000000000277113337271225011370 0ustar /* * context.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: context.h,v 1.14 2010/07/27 14:49:35 james Exp $ */ /* * $Log: context.h,v $ * Revision 1.14 2010/07/27 14:49:35 james * add support for byte logging * * Revision 1.13 2008/03/10 11:49:32 james * *** empty log message *** * * Revision 1.12 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.11 2008/03/06 16:49:05 james * *** empty log message *** * * Revision 1.10 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.9 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.8 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.7 2008/02/22 23:39:27 james * *** empty log message *** * * Revision 1.6 2008/02/15 03:32:07 james * *** empty log message *** * * Revision 1.5 2008/02/14 02:46:44 james * *** empty log message *** * * Revision 1.4 2008/02/14 01:55:57 james * *** empty log message *** * * Revision 1.3 2008/02/13 09:12:21 james * *** empty log message *** * * Revision 1.2 2008/02/12 22:36:46 james * *** empty log message *** * * Revision 1.1 2008/02/09 15:47:28 james * *** empty log message *** * */ #ifndef __CONTEXT_H__ #define __CONTEXT_H__ typedef struct Context_struct { VT102 *v; TTY *t; TTY_Parser *tp; History *h; Log *l; KeyDis *k; Cmd *d; UTF8 *u; RX *r; int byte_logging; } Context; #endif /* __CONTEXT_H__ */ work/src/crt.c0000664000000000000000000000660413337271225010466 0ustar /* * crt.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: crt.c,v 1.18 2008/03/07 12:37:04 james Exp $"; /* * $Log: crt.c,v $ * Revision 1.18 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.17 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.16 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.15 2008/02/27 09:42:21 james * *** empty log message *** * * Revision 1.14 2008/02/27 00:27:21 james * *** empty log message *** * * Revision 1.13 2008/02/26 23:56:12 james * *** empty log message *** * * Revision 1.12 2008/02/26 23:23:17 james * *** empty log message *** * * Revision 1.11 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.10 2008/02/22 17:07:00 james * *** empty log message *** * * Revision 1.9 2008/02/07 13:22:51 james * *** empty log message *** * * Revision 1.8 2008/02/07 13:19:48 james * *** empty log message *** * * Revision 1.7 2008/02/07 12:41:06 james * *** empty log message *** * * Revision 1.6 2008/02/07 12:16:04 james * *** empty log message *** * * Revision 1.5 2008/02/06 11:30:37 james * *** empty log message *** * * Revision 1.4 2008/02/05 01:11:46 james * *** empty log message *** * * Revision 1.3 2008/02/04 20:23:55 james * *** empty log message *** * * Revision 1.2 2008/02/04 02:05:06 james * *** empty log message *** * * Revision 1.1 2008/02/03 23:31:25 james * *** empty log message *** * */ #include "project.h" void crt_erase (CRT * c, CRT_Pos s, CRT_Pos e, int ea, int color) { CRT_CA *ps = &c->screen[CRT_ADDR_POS (&s)]; CRT_CA *pe = &c->screen[CRT_ADDR_POS (&e)]; while (ps <= pe) { ps->chr = ' '; if (ea) { ps->attr = CRT_ATTR_NORMAL; ps->color = color; } ps++; } } void crt_cls (CRT * c) { CRT_Pos s = { 0, 0 }; CRT_Pos e = { CRT_COLS - 1, CRT_ROWS - 1 }; int i; crt_erase (c, s, e, 1, CRT_COLOR_NORMAL); #if 0 c->sh.dir = 0; #endif } void crt_scroll_up (CRT * c, CRT_Pos s, CRT_Pos e, int ea, int color) { int l, n; int p; s.x = 0; e.x = CRT_COLS - 1; #if 0 c->sh.s = s; c->sh.e = e; c->sh.dir = -1; #endif l = e.x - s.x; l++; l *= sizeof (CRT_CA); n = e.y - s.y; p = CRT_ADDR_POS (&s); while (n--) { memcpy (&c->screen[p], &c->screen[p + CRT_COLS], l); p += CRT_COLS; } s.y = e.y; crt_erase (c, s, e, ea, color); } void crt_scroll_down (CRT * c, CRT_Pos s, CRT_Pos e, int ea, int color) { int l, n; int p; s.x = 0; e.x = CRT_COLS - 1; #if 0 c->sh.s = s; c->sh.e = e; c->sh.dir = 1; #endif l = e.x - s.x; l++; l *= sizeof (CRT_CA); n = e.y - s.y; // n++; p = CRT_ADDR_POS (&e); while (n--) { p -= CRT_COLS; memcpy (&c->screen[p], &c->screen[p - CRT_COLS], l); } e.y = s.y; crt_erase (c, s, e, ea, color); } void crt_reset (CRT * c) { crt_cls (c); c->pos.x = 0; c->pos.y = 0; c->hide_cursor = 1; c->size.x = CRT_COLS; c->size.y = CRT_ROWS; #if 0 c->sh.dir = 0; #endif } void crt_insert (CRT * c, CRT_CA ca) { if (c->pos.x < 0) c->pos.x = 0; if (c->pos.x >= CRT_COLS) c->pos.x = CRT_COLS - 1; if (c->pos.y < 0) c->pos.y = 0; if (c->pos.y >= CRT_ROWS) c->pos.y = CRT_ROWS - 1; c->screen[CRT_ADDR (c->pos.y, c->pos.x)] = ca; #if 0 c->sh.dir = 0; #endif } work/src/crt.h0000664000000000000000000000627513337271225010477 0ustar /* * crt.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: crt.h,v 1.18 2008/03/10 11:49:33 james Exp $ */ /* * $Log: crt.h,v $ * Revision 1.18 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.17 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.16 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.15 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.14 2008/02/28 16:57:51 james * *** empty log message *** * * Revision 1.13 2008/02/27 09:42:22 james * *** empty log message *** * * Revision 1.12 2008/02/26 23:23:17 james * *** empty log message *** * * Revision 1.11 2008/02/26 19:08:27 james * *** empty log message *** * * Revision 1.10 2008/02/24 00:42:53 james * *** empty log message *** * * Revision 1.9 2008/02/20 19:25:09 james * *** empty log message *** * * Revision 1.8 2008/02/13 09:12:21 james * *** empty log message *** * * Revision 1.7 2008/02/13 01:08:18 james * *** empty log message *** * * Revision 1.6 2008/02/07 13:22:51 james * *** empty log message *** * * Revision 1.5 2008/02/07 12:41:06 james * *** empty log message *** * * Revision 1.4 2008/02/07 12:16:04 james * *** empty log message *** * * Revision 1.3 2008/02/06 11:30:37 james * *** empty log message *** * * Revision 1.2 2008/02/04 20:23:55 james * *** empty log message *** * * Revision 1.1 2008/02/03 23:31:25 james * *** empty log message *** * */ #ifndef __CRT_H__ #define __CRT_H__ #define CRT_ROWS 60 #define CRT_COLS 132 #define CRT_CELS (CRT_ROWS*CRT_COLS) #define CRT_ADDR(r,c) (((r)*CRT_COLS)+(c)) #define CRT_ADDR_POS(p) ((((p)->y)*CRT_COLS)+((p)->x)) #define CRT_ATTR_NORMAL 0x0 #define CRT_ATTR_UNDERLINE 0x1 #define CRT_ATTR_REVERSE 0x2 #define CRT_ATTR_BLINK 0x4 #define CRT_ATTR_BOLD 0x8 #define CRT_COLOR_BLACK 0x0 #define CRT_COLOR_RED 0x1 #define CRT_COLOR_GREEN 0x2 #define CRT_COLOR_YELLOW 0x3 #define CRT_COLOR_BLUE 0x4 #define CRT_COLOR_MAGENTA 0x5 #define CRT_COLOR_CYAN 0x6 #define CRT_COLOR_WHITE 0x7 #define CRT_COLOR_INTENSITY 0x8 #define CRT_COLOR_FG_MASK 0xf0 #define CRT_COLOR_FG_SHIFT 4 #define CRT_COLOR_BG_MASK 0xf #define CRT_COLOR_BG_SHIFT 0 #define CRT_COLOR_BG(a) (((a) & CRT_COLOR_BG_MASK) >> CRT_COLOR_BG_SHIFT) #define CRT_COLOR_FG(a) (((a) & CRT_COLOR_FG_MASK) >> CRT_COLOR_FG_SHIFT) #define CRT_MAKE_COLOR(f,b) (((f) << CRT_COLOR_FG_SHIFT)|(b)) #define CRT_BGCOLOR_NORMAL CRT_COLOR_BLACK #define CRT_FGCOLOR_NORMAL CRT_COLOR_WHITE #define CRT_COLOR_NORMAL CRT_MAKE_COLOR(CRT_FGCOLOR_NORMAL,CRT_BGCOLOR_NORMAL) typedef struct __attribute__ ((packed)) { uint32_t chr; uint8_t attr; uint8_t color; } CRT_CA; typedef struct { int x; int y; } CRT_Pos; typedef struct { CRT_Pos s; CRT_Pos e; int dir; } CRT_ScrollHint; typedef struct CRT_struct { CRT_CA screen[CRT_CELS]; CRT_Pos pos; int hide_cursor; CRT_Pos size; } CRT; static inline int crt_ca_cmp (CRT_CA a, CRT_CA b) { return memcmp (&a, &b, sizeof (a)); } static inline int crt_pos_cmp (CRT_Pos a, CRT_Pos b) { return memcmp (&a, &b, sizeof (a)); } #endif /* __CRT_H__ */ work/src/history.c0000664000000000000000000000274413337271225011400 0ustar /* * history.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: history.c,v 1.7 2008/03/07 13:16:02 james Exp $"; /* * $Log: history.c,v $ * Revision 1.7 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.6 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.5 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.4 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.3 2008/02/13 16:57:29 james * *** empty log message *** * * Revision 1.2 2008/02/12 22:36:46 james * *** empty log message *** * * Revision 1.1 2008/02/08 15:06:42 james * *** empty log message *** * */ #include "project.h" History * history_new (int n) { History *ret; ret = (History *) xmalloc (sizeof (History)); ret->lines = xmalloc (n * sizeof (History_ent)); memset (ret->lines, 0, n * sizeof (History_ent)); ret->wptr = 0; ret->nlines = n; return ret; } void history_free (History * h) { if (!h) return; if (h->lines) free (h->lines); free (h); } void history_add (History * h, CRT_CA * c) { History_ent *e; if (!h) return; e = &h->lines[h->wptr]; HISTORY_INC (h, h->wptr); memcpy (e->line, c, sizeof (CRT_CA) * CRT_COLS); time (&e->t); e->valid = 1; #if 0 { int i = CRT_COLS; while (i--) { fputc (c->chr, stderr); c++; } fputc ('\n', stderr); } #endif } work/src/history.h0000664000000000000000000000204713337271225011401 0ustar /* * history.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: history.h,v 1.7 2008/03/10 11:49:33 james Exp $ */ /* * $Log: history.h,v $ * Revision 1.7 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.6 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.5 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.4 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.3 2008/02/13 16:57:29 james * *** empty log message *** * * Revision 1.2 2008/02/12 22:36:46 james * *** empty log message *** * * Revision 1.1 2008/02/08 15:06:42 james * *** empty log message *** * */ #ifndef __HISTORY_H__ #define __HISTORY_H__ typedef struct { int valid; time_t t; CRT_CA line[CRT_COLS]; } History_ent; typedef struct { History_ent *lines; int nlines; int wptr; } History; #define HISTORY_INC(h,a) do { (a)++; if ((a)==((h)->nlines)) { (a)=0; }; } while (0) #endif /* __HISTORY_H__ */ work/src/html.c0000664000000000000000000001120413337271225010632 0ustar /* * html.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: html.c,v 1.15 2008/03/07 13:16:02 james Exp $"; /* * $Log: html.c,v $ * Revision 1.15 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.14 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.13 2008/03/06 16:49:39 james * *** empty log message *** * * Revision 1.12 2008/03/06 16:49:05 james * *** empty log message *** * * Revision 1.11 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.10 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.9 2008/02/27 09:42:22 james * *** empty log message *** * * Revision 1.8 2008/02/27 01:52:38 james * *** empty log message *** * * Revision 1.7 2008/02/27 01:52:08 james * *** empty log message *** * * Revision 1.6 2008/02/20 23:42:05 staffcvs * *** empty log message *** * * Revision 1.5 2008/02/20 23:31:48 staffcvs * *** empty log message *** * * Revision 1.4 2008/02/20 22:54:22 staffcvs * *** empty log message *** * * Revision 1.3 2008/02/20 20:16:07 james * *** empty log message *** * * Revision 1.2 2008/02/04 02:05:06 james * *** empty log message *** * * Revision 1.1 2008/02/03 23:31:25 james * *** empty log message *** * */ #include "project.h" #define V(i) (((i)==0)?0x80:(((i)==1)?0xc0:0xff)) #define COLOR(r,g,b,i) ((((r)?(V(i)):0) << 0)| (((g)?(V(i)):0) << 8)| (((b)?(V(i)):0) << 16)) static int colormap[] = { [CRT_COLOR_BLACK] = COLOR (0, 0, 0, 0), [CRT_COLOR_RED] = COLOR (0, 0, 1, 0), [CRT_COLOR_GREEN] = COLOR (0, 1, 0, 0), [CRT_COLOR_YELLOW] = COLOR (0, 1, 1, 0), [CRT_COLOR_BLUE] = COLOR (1, 0, 0, 0), [CRT_COLOR_MAGENTA] = COLOR (1, 0, 1, 0), [CRT_COLOR_CYAN] = COLOR (1, 1, 0, 0), [CRT_COLOR_WHITE] = COLOR (1, 1, 1, 1), [CRT_COLOR_BLACK | CRT_COLOR_INTENSITY] = COLOR (1, 1, 1, 0), [CRT_COLOR_RED | CRT_COLOR_INTENSITY] = COLOR (0, 0, 1, 2), [CRT_COLOR_GREEN | CRT_COLOR_INTENSITY] = COLOR (0, 1, 0, 2), [CRT_COLOR_YELLOW | CRT_COLOR_INTENSITY] = COLOR (0, 1, 1, 2), [CRT_COLOR_BLUE | CRT_COLOR_INTENSITY] = COLOR (1, 0, 0, 2), [CRT_COLOR_MAGENTA | CRT_COLOR_INTENSITY] = COLOR (1, 0, 1, 2), [CRT_COLOR_CYAN | CRT_COLOR_INTENSITY] = COLOR (1, 1, 0, 2), [CRT_COLOR_WHITE | CRT_COLOR_INTENSITY] = COLOR (1, 1, 1, 2), }; static void html_entity (FILE * f, int c) { switch (c) { case 32: fprintf (f, " "); break; case 38: fprintf (f, "&"); break; case 60: fprintf (f, "<"); break; case 62: fprintf (f, ">"); break; default: if ((c >= 32) && (c < 127)) { fputc (c, f); } else if (c > 127) { fprintf (f, "&#x%04x;", c); } else { fputc (' ', f); } } } static void html_render (FILE * f, CRT_CA c) { int fg, bg; if (c.attr & CRT_ATTR_REVERSE) { fg = CRT_COLOR_BG (c.color); bg = CRT_COLOR_FG (c.color); } else { fg = CRT_COLOR_FG (c.color); bg = CRT_COLOR_BG (c.color); if (c.attr & CRT_ATTR_BOLD) fg |= CRT_COLOR_INTENSITY; } #ifdef CSS fprintf (f, "", colormap[fg], colormap[bg]); #else fprintf (f, "", colormap[bg], colormap[fg]); fprintf (f, ""); #endif if (c.attr & CRT_ATTR_UNDERLINE) fprintf (f, "
    "); if (c.attr & CRT_ATTR_BOLD) fprintf (f, ""); html_entity (f, c.chr); if (c.attr & CRT_ATTR_BOLD) fprintf (f, ""); if (c.attr & CRT_ATTR_UNDERLINE) fprintf (f, "
"); if (c.attr & CRT_ATTR_REVERSE) { fprintf (f, "
"); } #ifdef CSS fprintf (f, "
"); #else fprintf (f, ""); fprintf (f, ""); #endif } static void html_draw (FILE * f, CRT * c) { CRT_Pos p; int o; #ifdef CSS fprintf (f, "
");
#else
  fprintf (f, "\n");
#endif
  for (p.y = 0; p.y < c->size.y; ++p.y) {
    o = CRT_ADDR (p.y, 0);
#ifndef CSS
    fprintf (f, "");
#endif
    for (p.x = 0; p.x < c->size.x; ++p.x, ++o) {
      html_render (f, c->screen[o]);
    }
#ifdef CSS
    fprintf (f, "\n");
#else
    fprintf (f, "\n");
#endif
  }
#ifdef CSS
  fprintf (f, "\n");
#else
  fprintf (f, "
"); #endif } static int html_one_shot (ANSI * a, CRT * c) { html_draw (a->file, c); return 0; } static void ansi_free (ANSI * a) { free (a); } ANSI * ansi_new_html (FILE * f) { ANSI *ret; ret = xmalloc (sizeof (ANSI)); memset (ret, 0, sizeof (ANSI)); ret->file = f; ret->close = ansi_free; ret->one_shot = html_one_shot; return ret; } work/src/ipc.c0000664000000000000000000001174613337271225010454 0ustar /* * ipc.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: ipc.c,v 1.11 2008/03/07 14:13:40 james Exp $"; /* * $Log: ipc.c,v $ * Revision 1.11 2008/03/07 14:13:40 james * *** empty log message *** * * Revision 1.10 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.9 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.8 2008/03/03 18:16:16 james * *** empty log message *** * * Revision 1.7 2008/03/03 18:15:19 james * *** empty log message *** * * Revision 1.6 2008/02/28 16:57:51 james * *** empty log message *** * * Revision 1.5 2008/02/28 11:27:48 james * *** empty log message *** * * Revision 1.4 2008/02/22 17:07:00 james * *** empty log message *** * * Revision 1.3 2008/02/15 23:52:12 james * *** empty log message *** * * Revision 1.2 2008/02/15 03:32:07 james * *** empty log message *** * * Revision 1.1 2008/02/14 12:17:42 james * *** empty log message *** * */ #include "project.h" IPC_Msg * ipc_check_for_message_in_slide (Slide * s) { IPC_Msg *m; if (SLIDE_BYTES (s) < sizeof (IPC_Msg_hdr)) return NULL; m = (IPC_Msg *) SLIDE_RPTR (s); if (SLIDE_BYTES (s) < m->hdr.size) return NULL; if (m->hdr.size < sizeof (IPC_Msg_hdr)) crash_out ("ipc_check_for_message_in_slide test failed"); return m; } void ipc_consume_message_in_slide (Slide * s) { IPC_Msg *m = ipc_check_for_message_in_slide (s); if (!m) crash_out ("ipc_consume_message_in_slide test failed"); slide_consume (s, m->hdr.size); } int ipc_msg_send (Socket * s, IPC_Msg * m) { int len = m->hdr.size; return (socket_write (s, m, len) == len) ? 0 : -1; } int ipc_msg_send_debug (Socket * s, char *msg) { char buf[sizeof (IPC_Msg_hdr) + IPC_MAX_BUF]; IPC_Msg_debug *m; int len; m = (IPC_Msg_debug *) buf; m->type = IPC_MSG_TYPE_DEBUG; strncpy (m->msg, msg, IPC_MAX_BUF); m->msg[IPC_MAX_BUF - 1] = 0; m->size = sizeof (IPC_Msg_hdr) + strlen (m->msg) + 1; return ipc_msg_send (s, (IPC_Msg *) m); } int ipc_msg_send_initialize (Socket * s) { IPC_Msg_initialize m; m.size = sizeof (m); m.type = IPC_MSG_TYPE_INITIALIZE; return ipc_msg_send (s, (IPC_Msg *) & m); } int ipc_msg_send_history (Socket * s, History_ent * l) { IPC_Msg_history m; int len; m.type = IPC_MSG_TYPE_HISTORY; m.history = *l; m.size = sizeof (m); return ipc_msg_send (s, (IPC_Msg *) & m); } int ipc_msg_send_vt102 (Socket * s, VT102 * v) { IPC_Msg_VT102 m; int len; m.type = IPC_MSG_TYPE_VT102; m.len = sizeof (VT102); m.vt102 = *v; m.size = sizeof (m); return ipc_msg_send (s, (IPC_Msg *) & m); } int ipc_msg_send_key (Socket * s, int key) { IPC_Msg_key m; m.size = sizeof (m); m.type = IPC_MSG_TYPE_KEY; m.key = key; return ipc_msg_send (s, (IPC_Msg *) & m); } int ipc_msg_send_term (Socket * s, void *buf, int len) { char mbuf[IPC_MAX_BUF + sizeof (IPC_Msg_hdr)]; IPC_Msg_term *m = (IPC_Msg_term *) mbuf; if (!len) return 0; m->size = len + sizeof (IPC_Msg_hdr); m->type = IPC_MSG_TYPE_TERM; m->len = len; memcpy (m->term, buf, len); return ipc_msg_send (s, (IPC_Msg *) & m); } int ipc_msg_send_status (Socket * s, char *buf) { char mbuf[IPC_MAX_BUF + sizeof (IPC_Msg_hdr)]; IPC_Msg_status *m = (IPC_Msg_status *) mbuf; int len; if (!buf) return 0; len = strlen (buf) + 1; m->size = len + sizeof (IPC_Msg_hdr); m->type = IPC_MSG_TYPE_STATUS; strncpy (m->status, buf, IPC_MAX_BUF - 1); m->status[IPC_MAX_BUF - 1] = 0; return ipc_msg_send (s, (IPC_Msg *) & m); } int ipc_msg_send_setbaud (Socket * s, int baud) { IPC_Msg_setbaud m; m.size = sizeof (m); m.type = IPC_MSG_TYPE_SETBAUD; m.baud = baud; return ipc_msg_send (s, (IPC_Msg *) & m); } int ipc_msg_send_sendbreak (Socket * s) { IPC_Msg_sendbreak m; m.size = sizeof (m); m.type = IPC_MSG_TYPE_SENDBREAK; return ipc_msg_send (s, (IPC_Msg *) & m); } int ipc_msg_send_setflow (Socket * s, int flow) { IPC_Msg_setflow m; m.size = sizeof (m); m.type = IPC_MSG_TYPE_SETFLOW; m.flow = flow; return ipc_msg_send (s, (IPC_Msg *) & m); } int ipc_msg_send_setansi (Socket * s, int ansi) { IPC_Msg_setansi m; m.size = sizeof (m); m.type = IPC_MSG_TYPE_SETANSI; m.ansi = ansi; return ipc_msg_send (s, (IPC_Msg *) & m); } int ipc_msg_send_hangup (Socket * s) { IPC_Msg_hangup m; m.size = sizeof (m); m.type = IPC_MSG_TYPE_HANGUP; return ipc_msg_send (s, (IPC_Msg *) & m); } int ipc_msg_send_setsize (Socket * s, CRT_Pos size) { IPC_Msg_setsize m; m.size = sizeof (m); m.type = IPC_MSG_TYPE_SETSIZE; m.winsize = size; return ipc_msg_send (s, (IPC_Msg *) & m); } int ipc_msg_send_reset (Socket * s) { IPC_Msg_reset m; m.size = sizeof (m); m.type = IPC_MSG_TYPE_RESET; return ipc_msg_send (s, (IPC_Msg *) & m); } int ipc_msg_send_killme (Socket * s) { IPC_Msg_killme m; m.size = sizeof (m); m.type = IPC_MSG_TYPE_KILLME; return ipc_msg_send (s, (IPC_Msg *) & m); } work/src/ipc.h0000664000000000000000000000674113337271225010460 0ustar /* * ipc.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: ipc.h,v 1.12 2008/03/10 11:49:33 james Exp $ */ /* * $Log: ipc.h,v $ * Revision 1.12 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.11 2008/03/07 14:13:40 james * *** empty log message *** * * Revision 1.10 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.9 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.8 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.7 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.6 2008/02/28 11:27:48 james * *** empty log message *** * * Revision 1.5 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.4 2008/02/22 17:07:00 james * *** empty log message *** * * Revision 1.3 2008/02/15 23:52:12 james * *** empty log message *** * * Revision 1.2 2008/02/15 03:32:07 james * *** empty log message *** * * Revision 1.1 2008/02/14 12:17:42 james * *** empty log message *** * */ #ifndef __IPC_H__ #define __IPC_H__ #define IPC_MAX_BUF 1024 #define IPC_MSG_TYPE_NOOP 0 #define IPC_MSG_TYPE_DEBUG 1 #define IPC_MSG_TYPE_INITIALIZE 2 #define IPC_MSG_TYPE_VT102 3 #define IPC_MSG_TYPE_HISTORY 4 #define IPC_MSG_TYPE_KEY 5 #define IPC_MSG_TYPE_TERM 6 #define IPC_MSG_TYPE_STATUS 7 #define IPC_MSG_TYPE_SETBAUD 8 #define IPC_MSG_TYPE_SENDBREAK 9 #define IPC_MSG_TYPE_SETFLOW 10 #define IPC_MSG_TYPE_SETANSI 11 #define IPC_MSG_TYPE_HANGUP 12 #define IPC_MSG_TYPE_SETSIZE 13 #define IPC_MSG_TYPE_RESET 14 #define IPC_MSG_TYPE_KILLME 15 typedef struct { int32_t size; int32_t type; uint8_t payload[0]; } IPC_Msg_hdr; typedef struct { int32_t size; int32_t type; } IPC_Msg_noop; typedef struct { int32_t size; int32_t type; char msg[0]; } IPC_Msg_debug; typedef struct { int32_t size; int32_t type; char msg[0]; } IPC_Msg_initialize; typedef struct { int32_t size; int32_t type; History_ent history; } IPC_Msg_history; typedef struct { int32_t size; int32_t type; int32_t len; VT102 vt102; } IPC_Msg_VT102; typedef struct { int32_t size; int32_t type; int32_t key; } IPC_Msg_key; typedef struct { int32_t size; int32_t type; int32_t len; uint8_t term[0]; } IPC_Msg_term; typedef struct { int32_t size; int32_t type; char status[0]; } IPC_Msg_status; typedef struct { int32_t size; int32_t type; int32_t baud; } IPC_Msg_setbaud; typedef struct { int32_t size; int32_t type; } IPC_Msg_sendbreak; typedef struct { int32_t size; int32_t type; int32_t flow; } IPC_Msg_setflow; typedef struct { int32_t size; int32_t type; int32_t ansi; } IPC_Msg_setansi; typedef struct { int32_t size; int32_t type; } IPC_Msg_hangup; typedef struct { int32_t size; int32_t type; CRT_Pos winsize; } IPC_Msg_setsize; typedef struct { int32_t size; int32_t type; } IPC_Msg_reset; typedef struct { int32_t size; int32_t type; } IPC_Msg_killme; typedef union { IPC_Msg_hdr hdr; IPC_Msg_noop noop; IPC_Msg_debug debug; IPC_Msg_initialize initialize; IPC_Msg_history history; IPC_Msg_VT102 vt102; IPC_Msg_key key; IPC_Msg_term term; IPC_Msg_status status; IPC_Msg_setbaud setbaud; IPC_Msg_sendbreak sendbreak; IPC_Msg_setflow setflow; IPC_Msg_setansi setansi; IPC_Msg_hangup hangup; IPC_Msg_setsize setsize; IPC_Msg_reset reset; IPC_Msg_killme killme; } IPC_Msg; #endif /* __IPC_H__ */ work/src/keydis.c0000664000000000000000000001306513337271225011165 0ustar /* * keydis.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: keydis.c,v 1.16 2008/03/10 11:49:33 james Exp $"; /* * $Log: keydis.c,v $ * Revision 1.16 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.15 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.14 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.13 2008/03/03 18:16:16 james * *** empty log message *** * * Revision 1.12 2008/03/03 18:15:19 james * *** empty log message *** * * Revision 1.11 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.10 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.9 2008/02/28 22:00:42 james * *** empty log message *** * * Revision 1.8 2008/02/28 16:57:52 james * *** empty log message *** * * Revision 1.7 2008/02/28 16:37:16 james * *** empty log message *** * * Revision 1.6 2008/02/28 12:12:25 james * *** empty log message *** * * Revision 1.5 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.4 2008/02/22 17:07:00 james * *** empty log message *** * * Revision 1.3 2008/02/15 23:52:12 james * *** empty log message *** * * Revision 1.2 2008/02/15 03:32:07 james * *** empty log message *** * * Revision 1.1 2008/02/14 02:46:44 james * *** empty log message *** * * Revision 1.1 2008/02/14 01:55:57 james * *** empty log message *** * */ #include "project.h" #define CMD_BUFLEN 128 typedef struct { KEYDIS_SIGNATURE; } KeyDis_VT102; typedef struct { KEYDIS_SIGNATURE; Socket *s; } KeyDis_IPC; static void keydis_close (KeyDis * t) { free (t); } static int keydis_ipc_key (KeyDis * _t, Context * c, int key) { KeyDis_IPC *t = (KeyDis_IPC *) _t; return ipc_msg_send_key (t->s, key); } static int keydis_ipc_set_baud (KeyDis * _t, Context * c, int baud) { KeyDis_IPC *t = (KeyDis_IPC *) _t; ipc_msg_send_setbaud (t->s, baud); return 0; } static int keydis_ipc_send_break (KeyDis * _t, Context * c) { KeyDis_IPC *t = (KeyDis_IPC *) _t; ipc_msg_send_sendbreak (t->s); return 0; } static int keydis_ipc_set_flow (KeyDis * _t, Context * c, int flow) { KeyDis_IPC *t = (KeyDis_IPC *) _t; ipc_msg_send_setflow (t->s, flow); return 0; } static int keydis_ipc_set_ansi (KeyDis * _t, Context * c, int ansi) { KeyDis_IPC *t = (KeyDis_IPC *) _t; vt102_set_ansi (c->v, ansi); ipc_msg_send_setansi (t->s, ansi); return 0; } static int keydis_ipc_hangup (KeyDis * _t, Context * c) { KeyDis_IPC *t = (KeyDis_IPC *) _t; ipc_msg_send_hangup (t->s); return 0; } static int keydis_ipc_set_size (KeyDis * _t, Context * c, int w, int h) { CRT_Pos p = { w, h }; KeyDis_IPC *t = (KeyDis_IPC *) _t; vt102_resize (c, p); ipc_msg_send_setsize (t->s, p); return 0; } static int keydis_ipc_reset (KeyDis * _t, Context * c) { KeyDis_IPC *t = (KeyDis_IPC *) _t; vt102_reset (c); ipc_msg_send_reset (t->s); return 0; } static int keydis_vt102_key (KeyDis * _t, Context * c, int key) { KeyDis_VT102 *t = (KeyDis_VT102 *) _t; vt102_send (c, key); return 0; } static int keydis_vt102_set_baud (KeyDis * _t, Context * c, int baud) { KeyDis_VT102 *t = (KeyDis_VT102 *) _t; tty_set_baud (c->t, baud); tty_parse_reset (c); log_f (c->l, "", baud); return 0; } static int keydis_vt102_send_break (KeyDis * _t, Context * c) { KeyDis_VT102 *t = (KeyDis_VT102 *) _t; log_f (c->l, ""); tty_send_break (c->t); return 0; } static int keydis_vt102_set_flow (KeyDis * _t, Context * c, int flow) { KeyDis_VT102 *t = (KeyDis_VT102 *) _t; log_f (c->l, "", flow ? "on" : "off"); tty_set_flow (c->t, flow); return 0; } static int keydis_vt102_set_ansi (KeyDis * _t, Context * c, int ansi) { KeyDis_VT102 *t = (KeyDis_VT102 *) _t; if (c->v) c->v->xn_glitch = ansi ? 0 : 1; return 0; } static int keydis_vt102_hangup (KeyDis * _t, Context * c) { KeyDis_VT102 *t = (KeyDis_VT102 *) _t; log_f (c->l, ""); tty_hangup (c->t); return 0; } static int keydis_vt102_set_size (KeyDis * _t, Context * c, int w, int h) { KeyDis_VT102 *t = (KeyDis_VT102 *) _t; CRT_Pos p = { w, h }; vt102_resize (c, p); return 0; } static int keydis_vt102_reset (KeyDis * _t, Context * c) { KeyDis_VT102 *t = (KeyDis_VT102 *) _t; vt102_reset (c); return 0; } KeyDis * keydis_vt102_new (void) { KeyDis_VT102 *t = xmalloc (sizeof (KeyDis_VT102)); t->key = keydis_vt102_key; t->close = keydis_close; t->set_baud = keydis_vt102_set_baud; t->send_break = keydis_vt102_send_break; t->set_flow = keydis_vt102_set_flow; t->set_ansi = keydis_vt102_set_ansi; t->hangup = keydis_vt102_hangup; t->set_size = keydis_vt102_set_size; t->reset = keydis_vt102_reset; return (KeyDis *) t; } KeyDis * keydis_ipc_new (Socket * s) { KeyDis_IPC *t = xmalloc (sizeof (KeyDis_IPC)); t->key = keydis_ipc_key; t->close = keydis_close; t->set_baud = keydis_ipc_set_baud; t->send_break = keydis_ipc_send_break; t->set_flow = keydis_ipc_set_flow; t->set_ansi = keydis_ipc_set_ansi; t->hangup = keydis_ipc_hangup; t->set_size = keydis_ipc_set_size; t->reset = keydis_ipc_reset; t->s = s; return (KeyDis *) t; } #if 0 int keydis_key (KeyDis * t, Context * c, int key) { if (!c->d) return t->key (t, c, key); cmd_show_status (c->d, c); if (c->d->active) return cmd_key (c->d, c, key); if (key == CMD_KEY) return cmd_activate (c->d, c); return t->key (t, c, key); } #endif work/src/keydis.h0000664000000000000000000000351313337271225011167 0ustar /* * keydis.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: keydis.h,v 1.10 2008/03/10 11:49:33 james Exp $ */ /* * $Log: keydis.h,v $ * Revision 1.10 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.9 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.8 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.7 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.6 2008/02/28 11:27:48 james * *** empty log message *** * * Revision 1.5 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.4 2008/02/22 17:07:00 james * *** empty log message *** * * Revision 1.3 2008/02/15 23:52:12 james * *** empty log message *** * * Revision 1.2 2008/02/15 03:32:07 james * *** empty log message *** * * Revision 1.1 2008/02/14 02:46:44 james * *** empty log message *** * * Revision 1.1 2008/02/14 01:55:57 james * *** empty log message *** * */ #ifndef __KEYDIS_H__ #define __KEYDIS_H__ struct Context_struct; #define KEYDIS_SIGNATURE \ void (*close)(struct KeyDis_struct *); \ int (*key)(struct KeyDis_struct *,struct Context_struct *,int key); \ int (*set_baud)(struct KeyDis_struct *,struct Context_struct *,int rate); \ int (*send_break)(struct KeyDis_struct *,struct Context_struct *); \ int (*set_flow)(struct KeyDis_struct *,struct Context_struct *,int flow); \ int (*set_ansi)(struct KeyDis_struct *,struct Context_struct *,int ansi); \ int (*hangup)(struct KeyDis_struct *,struct Context_struct *); \ int (*reset)(struct KeyDis_struct *,struct Context_struct *); \ int (*set_size)(struct KeyDis_struct *,struct Context_struct *,int width, int height) typedef struct KeyDis_struct { KEYDIS_SIGNATURE; } KeyDis; #endif /* __KEYDIS_H__ */ work/src/keys.h0000664000000000000000000001040713337271225010652 0ustar /* * src/keys.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: keys.h,v 1.10 2008/03/07 14:16:44 james Exp $ */ /* * $Log: keys.h,v $ * Revision 1.10 2008/03/07 14:16:44 james * *** empty log message *** * * Revision 1.9 2008/03/07 14:13:40 james * *** empty log message *** * * Revision 1.8 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.7 2008/03/06 16:49:39 james * *** empty log message *** * * Revision 1.6 2008/03/06 01:49:19 james * *** empty log message *** * * Revision 1.5 2008 /03 /06 01:41:48 james * *** empty log message *** * * Revision 1.4 2008 /02 /07 00:44:07 james * *** empty log message *** * */ #ifndef __KEYS_H__ #define __KEYS_H__ #define KEY_UP 128 /* A */ #define KEY_DOWN 129 /* B */ #define KEY_RIGHT 130 /* C */ #define KEY_LEFT 131 /* D */ #define KEY_MIDDLE 132 /* E */ #define KEY_END 133 /* F */ #define KEY_134 134 /* G */ #define KEY_HOME 135 /* H */ #define KEY_136 136 /* I */ #define KEY_137 137 /* J */ #define KEY_138 138 /* K */ #define KEY_139 139 /* L */ #define KEY_ENTER 140 /* M */ #define KEY_141 141 /* N */ #define KEY_142 142 /* O */ #define KEY_PF1 143 /* P */ /* Also F1 */ #define KEY_PF2 144 /* Q */ /* Also F2 */ #define KEY_PF3 145 /* R */ /* Also F3 */ #define KEY_PF4 146 /* S */ /* Also F4 */ #define KEY_147 147 /* T */ #define KEY_148 148 /* U */ #define KEY_149 149 /* V */ #define KEY_150 150 /* W */ #define KEY_151 151 /* X */ #define KEY_152 152 /* Y */ #define KEY_153 153 /* Z */ #define KEY_154 154 /* a */ #define KEY_155 155 /* b */ #define KEY_156 156 /* c */ #define KEY_157 157 /* d */ #define KEY_158 158 /* e */ #define KEY_159 159 /* f */ #define KEY_160 160 /* g */ #define KEY_161 161 /* h */ #define KEY_162 162 /* i */ #define KEY_STAR 163 /* j */ #define KEY_PLUS 164 /* k */ #define KEY_COMMA 165 /* l */ #define KEY_MINUS 166 /* m */ #define KEY_PERIOD 167 /* n */ #define KEY_DIVIDE 168 /* o */ #define KEY_0 169 /* p */ #define KEY_1 170 /* q */ #define KEY_2 171 /* r */ #define KEY_3 172 /* s */ #define KEY_4 173 /* t */ #define KEY_5 174 /* u */ #define KEY_6 175 /* v */ #define KEY_7 176 /* w */ #define KEY_8 177 /* x */ #define KEY_9 178 /* y */ #define KEY_179 179 /* z */ #define KEY_180 180 /* 0 */ #define KEY_VT220_HOME 181 /* 1 */ #define KEY_INSERT 182 /* 2 */ #define KEY_DELETE 183 /* 3 */ #define KEY_VT220_END 184 /* 4 */ #define KEY_PGUP 185 /* 5 */ #define KEY_PGDN 186 /* 6 */ #define KEY_187 187 /* 7 */ #define KEY_188 188 /* 8 */ #define KEY_189 189 /* 9 */ #define KEY_190 190 /* 10 */ #define KEY_F1 191 /* 11 */ #define KEY_F2 192 /* 12 */ #define KEY_F3 193 /* 13 */ #define KEY_F4 194 /* 14 */ #define KEY_F5 195 /* 15 */ #define KEY_196 196 /* 16 */ #define KEY_F6 197 /* 17 */ #define KEY_F7 198 /* 18 */ #define KEY_F8 199 /* 19 */ #define KEY_F9 200 /* 20 */ #define KEY_F10 201 /* 21 */ #define KEY_202 202 /* 22 */ #define KEY_F11 203 /* 23 */ #define KEY_F12 204 /* 24 */ #define KEY_F13 205 /* 25 */ #define KEY_F14 206 /* 26 */ #define KEY_207 207 /* 27 */ #define KEY_F15 208 /* 28 */ #define KEY_F16 209 /* 29 */ #define KEY_210 210 /* 30 */ #define KEY_F17 211 /* 31 */ #define KEY_F18 212 /* 32 */ #define KEY_F19 213 /* 33 */ #define KEY_F20 214 /* 34 */ #define KEY_NUM 215 #endif /* __KEYS_H__ */ work/src/libsympathy.c0000664000000000000000000000324413337271225012240 0ustar /* * libsympathy.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: libsympathy.c,v 1.19 2008/03/07 12:37:04 james Exp $"; /* * $Log: libsympathy.c,v $ * Revision 1.19 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.18 2008/02/14 00:57:58 james * *** empty log message *** * * Revision 1.17 2008/02/13 16:57:29 james * *** empty log message *** * * Revision 1.16 2008/02/13 09:12:21 james * *** empty log message *** * * Revision 1.15 2008/02/13 01:08:18 james * *** empty log message *** * * Revision 1.14 2008/02/12 22:36:46 james * *** empty log message *** * * Revision 1.13 2008/02/08 15:06:42 james * *** empty log message *** * * Revision 1.12 2008/02/07 13:26:35 james * *** empty log message *** * * Revision 1.11 2008/02/07 13:22:51 james * *** empty log message *** * * Revision 1.10 2008/02/07 11:32:41 james * *** empty log message *** * * Revision 1.9 2008/02/07 11:11:14 staffcvs * *** empty log message *** * * Revision 1.8 2008/02/07 00:43:27 james * *** empty log message *** * * Revision 1.7 2008/02/07 00:39:13 james * *** empty log message *** * * Revision 1.6 2008/02/06 20:26:58 james * *** empty log message *** * * Revision 1.5 2008/02/06 17:53:28 james * *** empty log message *** * * Revision 1.4 2008/02/04 20:23:55 james * *** empty log message *** * * Revision 1.3 2008/02/04 05:45:55 james * :: * * Revision 1.2 2008/02/04 02:05:06 james * *** empty log message *** * * Revision 1.1 2008/02/03 16:20:24 james * *** empty log message *** * * */ #include "project.h" work/src/lockfile.c0000664000000000000000000002361613337271225011470 0ustar /* * lockfile.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: lockfile.c,v 1.17 2010/07/16 11:04:10 james Exp $"; /* * $Log: lockfile.c,v $ * Revision 1.17 2010/07/16 11:04:10 james * ignore tedious return values * * Revision 1.16 2008/05/09 12:56:11 james * *** empty log message *** * * Revision 1.15 2008/03/07 14:13:40 james * *** empty log message *** * * Revision 1.14 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.13 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.12 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.11 2008/03/02 10:38:18 james * *** empty log message *** * * Revision 1.10 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.9 2008/02/15 23:52:12 james * *** empty log message *** * * Revision 1.8 2008/02/15 20:52:36 james * *** empty log message *** * * Revision 1.7 2008/02/15 19:51:30 james * *** empty log message *** * * Revision 1.6 2008/02/15 19:09:00 james * *** empty log message *** * * Revision 1.5 2008/02/15 18:26:49 james * *** empty log message *** * * Revision 1.4 2008/02/15 18:16:48 james * *** empty log message *** * * Revision 1.3 2008/02/15 18:16:35 james * *** empty log message *** * * Revision 1.2 2008/02/15 16:48:56 james * *** empty log message *** * * Revision 1.1 2008/02/15 15:09:17 james * *** empty log message *** * */ #define LOCK_ASCII #undef LOCK_BINARY #define STALE_CHECK_INTERVAL 10 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lockfile.h" extern void *xmalloc (size_t); Filelist * filelist_new (void) { Filelist *fl = (Filelist *) xmalloc (sizeof (Filelist)); fl->head = NULL; return fl; } void filelist_remove (Filelist * fl, Filelist_ent * fle) { Filelist_ent **ep; for (ep = &fl->head; *ep; ep = &((*ep)->next)) if (fle == *ep) break; if (!*ep) return; *ep = fle->next; free (fle); } void filelist_add (Filelist * fl, char *fn) { Filelist_ent *fle; int i = strlen (fn); if (i >= FILE_LIST_MAX_LEN) return; for (fle = fl->head; fle; fle = fle->next) if (!strcmp (fle->name, fn)) return; fle = xmalloc (sizeof (Filelist_ent)); strcpy (fle->name, fn); fle->next = fl->head; fl->head = fle; } void filelist_free (Filelist * fl) { while (fl->head) filelist_remove (fl, fl->head); free (fl); } void filelist_print (Filelist * fl, FILE * f) { Filelist_ent *fle; if (!fl) { fprintf (f, "(empty list)\n"); return; } for (fle = fl->head; fle; fle = fle->next) fprintf (f, "%s\n", fle->name); } static int chown_uucp (fd) int fd; { static int uuid = -1, ugid; struct passwd *pw; if (uuid < 0) { if (pw = getpwnam ("uucp")) { uuid = pw->pw_uid; ugid = pw->pw_gid; } else { return -1; } } return fchown (fd, uuid, ugid); } int lockfile_make (char *name) { char buf[1024], tmpfn[1024]; char *ptr; int fd; int i; strcpy (tmpfn, name); ptr = rindex (tmpfn, '/'); if (!ptr) return -1; ptr++; ptr += sprintf (ptr, "LTMP.%d", getpid ()); *ptr = 0; i = sprintf (buf, "%10d\n", getpid ()); unlink (tmpfn); fd = open (tmpfn, O_WRONLY | O_CREAT | O_TRUNC, 0444); if (fd < 0) { unlink (tmpfn); return -1; } int result; result = write (fd, buf, i); fchmod (fd, 044); #if 0 if (chown_uucp (fd)) { close (fd); unlink (tmpfn); return -1; } #else chown_uucp (fd); #endif close (fd); if (link (tmpfn, name) < 0) { unlink (tmpfn); return -1; } unlink (tmpfn); return 0; } void lockfile_add_places (Filelist * fl, char *leaf) { char buf[1024]; struct stat stbuf; char *lock_dirs[] = { "/var/lock/uucp", "/var/spool/lock", "/var/spool/uucp", "/etc/locks", "/usr/spool/uucp", "/var/spool/locks", "/usr/spool/lock", "/usr/spool/locks", "/usr/spool/uucp/LCK", "/var/lock" }; int i; for (i = 0; i < (sizeof (lock_dirs) / sizeof (char *)); ++i) { if (stat (lock_dirs[i], &stbuf)) continue; strcpy (buf, lock_dirs[i]); strcat (buf, "/"); strcat (buf, leaf); filelist_add (fl, buf); } } static void do_tedious_mangling (Filelist * fl, char *buf, char *ptr, char inv, int lower) { while (*ptr) { if (lower && (*ptr >= 'A') && (*ptr <= 'Z')) *ptr |= 32; if (*ptr == '/') *ptr = inv; ptr++; } lockfile_add_places (fl, buf); } void lockfile_regularize_and_add (Filelist * fl, char *leaf) { char buf[1024] = "LCK.."; char *ptr; if (*leaf == '/') leaf++; ptr = buf; while (*ptr) ptr++; strcpy (ptr, leaf); do_tedious_mangling (fl, buf, ptr, '_', 0); strcpy (ptr, leaf); do_tedious_mangling (fl, buf, ptr, '_', 1); strcpy (ptr, leaf); do_tedious_mangling (fl, buf, ptr, '.', 0); strcpy (ptr, leaf); do_tedious_mangling (fl, buf, ptr, '.', 1); } void lockfile_add_name_from_path (Filelist * fl, char *file) { char *ptr = file; if (*ptr == '/') ptr++; lockfile_regularize_and_add (fl, ptr); if (!strncmp (ptr, "dev/", 4)) { ptr += 4; lockfile_regularize_and_add (fl, ptr); } } void lockfile_add_name_from_dev (Filelist * fl, dev_t dev) { char buf[1024]; sprintf (buf, "LCK.%03d.%03d", major (dev), minor (dev)); lockfile_add_places (fl, buf); } void lockfile_check_dir_for_dev (Filelist * fl, char *dir, dev_t dev) { char buf[1024]; struct stat ent_stat; struct dirent *de; DIR *d; d = opendir (dir); if (!d) return; while ((de = readdir (d))) { strcpy (buf, dir); strcat (buf, de->d_name); if (stat (buf, &ent_stat)) continue; if (!S_ISCHR (ent_stat.st_mode)) continue; if (ent_stat.st_rdev != dev) continue; lockfile_add_name_from_path (fl, buf); } closedir (d); } Filelist * lockfile_make_list (char *device) { struct stat dev_stat; Filelist *ret = NULL; if (stat (device, &dev_stat)) return ret; if (!S_ISCHR (dev_stat.st_mode)) return ret; ret = filelist_new (); if (ret) { lockfile_add_name_from_dev (ret, dev_stat.st_rdev); lockfile_add_name_from_path (ret, device); lockfile_check_dir_for_dev (ret, "/dev/", dev_stat.st_rdev); lockfile_check_dir_for_dev (ret, "/dev/usb/", dev_stat.st_rdev); lockfile_check_dir_for_dev (ret, "/dev/tts/", dev_stat.st_rdev); } return ret; } static void remove_stale_lock (char *path) { int fd; int pid; char apid[20]; int length; fd = open (path, O_RDONLY); if (fd < 0) return; length = read (fd, apid, sizeof (apid) - 1); if (length < 0) length = 0; apid[length] = 0; pid = 0; if (length == sizeof (pid) || sscanf (apid, "%d", &pid) != 1 || pid == 0) { pid = *((int *) apid); #ifdef LOCK_ASCII fprintf (stderr, "compiled with ascii locks, found binary lock file (length=%d, pid=%d)!", length, pid); #endif } #ifdef LOCK_BINARY else { fprintf (stderr, "compiled with binary locks, found ascii lock file (length=%d, pid=%d)!", length, pid); } #endif close (fd); if ((kill (pid, 0) < 0) && (errno == ESRCH)) { fprintf (stderr, "removing stale lock file %s\n", path); unlink (path); } } void lockfile_remove_stale (Filelist * fl) { Filelist_ent *fle; struct stat buf; for (fle = fl->head; fle; fle = fle->next) { if (stat (fle->name, &buf)) continue; remove_stale_lock (fle->name); } } Filelist * lockfile_lock (Filelist * fl) { Filelist *ret; Filelist_ent *fle; ret = filelist_new (); if (ret) { lockfile_remove_stale (fl); for (fle = fl->head; fle; fle = fle->next) { if (lockfile_make (fle->name)) { fprintf (stderr, "Failed to get lockfile %s\n", fle->name); filelist_free (ret); return NULL; } filelist_add (ret, fle->name); } } return ret; } void lockfile_unlock (Filelist * fl) { while (fl->head) { unlink (fl->head->name); filelist_remove (fl, fl->head); } } /* If we have a passive lock, check noone has an */ /* active one, returns 1 if he does, 0 if he doesnt */ int serial_lock_check (Serial_lock * l) { Filelist_ent *fle; int locks_found = 0; struct stat buf; struct timeval now, dif; if (l->mode == SERIAL_LOCK_ACTIVE) return 0; for (fle = l->locks_to_check->head; fle; fle = fle->next) { if (!stat (fle->name, &buf)) locks_found++; } if (!locks_found) return 0; gettimeofday (&now, NULL); timersub (&now, &l->last_stale_purge, &dif); if (dif.tv_sec > STALE_CHECK_INTERVAL) { lockfile_remove_stale (l->locks_to_check); l->last_stale_purge = now; } return 1; } void serial_lock_free (Serial_lock * l) { if (!l) return; if (l->locks_held) { lockfile_unlock (l->locks_held); filelist_free (l->locks_held); } if (l->locks_to_check) { filelist_free (l->locks_to_check); } free (l); } Serial_lock * serial_lock_new (char *dev, int mode) { Filelist *fl = lockfile_make_list (dev); Serial_lock *l; if (!fl) return NULL; l = (Serial_lock *) xmalloc (sizeof (Serial_lock)); l->mode = mode; l->locks_to_check = fl; l->locks_held = NULL; memset (&l->last_stale_purge, 0, sizeof (l->last_stale_purge)); if (mode == SERIAL_LOCK_PASSIVE) return l; l->locks_held = lockfile_lock (l->locks_to_check); if (!l->locks_held) { serial_lock_free (l); return NULL; } return l; } #if 0 int main (int argc, char *argv[]) { Filelist *fl = lockfile_make_list ("/dev/ttyS0"); Filelist *fll; Filelist_ent *fle; filelist_print (fl, stdout); fll = lockfile_lock (fl); filelist_print (fll, stdout); } #endif work/src/lockfile.h0000664000000000000000000000276713337271225011501 0ustar /* * lockfile.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: lockfile.h,v 1.11 2008/03/10 11:49:33 james Exp $ */ /* * $Log: lockfile.h,v $ * Revision 1.11 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.10 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.9 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.8 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.7 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.6 2008/02/15 23:52:12 james * *** empty log message *** * * Revision 1.5 2008/02/15 20:52:36 james * *** empty log message *** * * Revision 1.4 2008/02/15 19:51:30 james * *** empty log message *** * * Revision 1.3 2008/02/15 18:16:36 james * *** empty log message *** * * Revision 1.2 2008/02/15 16:48:56 james * *** empty log message *** * * Revision 1.1 2008/02/15 15:09:17 james * *** empty log message *** * */ #ifndef __LOCKFILE_H__ #define __LOCKFILE_H__ #define SERIAL_LOCK_PASSIVE 0 #define SERIAL_LOCK_ACTIVE 1 #define FILE_LIST_MAX_LEN 1024 typedef struct Filelist_ent { char name[FILE_LIST_MAX_LEN]; struct Filelist_ent *next; } Filelist_ent; typedef struct { Filelist_ent *head; } Filelist; typedef struct { int mode; int i; struct timeval last_stale_purge; Filelist *locks_to_check; Filelist *locks_held; } Serial_lock; #endif /* __LOCKFILE_H__ */ work/src/log.c0000664000000000000000000001256413337271225010461 0ustar /* * log.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: log.c,v 1.17 2011/02/04 16:14:16 james Exp $"; /* * $Log: log.c,v $ * Revision 1.17 2011/02/04 16:14:16 james * *** empty log message *** * * Revision 1.16 2010/07/27 14:49:35 james * add support for byte logging * * Revision 1.15 2010/07/16 11:04:10 james * ignore tedious return values * * Revision 1.14 2008/03/11 17:56:04 james * *** empty log message *** * * Revision 1.13 2008/03/11 16:56:29 james * *** empty log message *** * * Revision 1.12 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.11 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.10 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.9 2008/03/03 06:20:14 james * *** empty log message *** * * Revision 1.8 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.7 2008/03/03 06:04:18 james * *** empty log message *** * * Revision 1.6 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.5 2008/02/27 01:31:14 james * *** empty log message *** * * Revision 1.4 2008/02/27 00:54:16 james * *** empty log message *** * * Revision 1.3 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.2 2008/02/22 14:51:54 james * *** empty log message *** * * Revision 1.1 2008/02/14 12:14:50 james * *** empty log message *** * */ #include "project.h" typedef struct { LOG_SIGNATURE; int do_close; int rotate; FILE *fp; char *filename; int needs_newline; } File_Log; static Log *loggers = NULL; static void sighup (int dummy) { Log *l; for (l = loggers; l; l = l->next) { if (l->sighup) l->sighup (l); } } void log_register_handlers (void) { struct sigaction sa = { 0 }; sa.sa_handler = sighup; sa.sa_flags = SA_RESTART; sigaction (SIGHUP, &sa, NULL); } void log_add (Log * l) { log_register_handlers (); l->next = loggers; loggers = l; } void log_remove (Log * l) { Log **ptr = &loggers; /* Take out of sighup list */ while (*ptr && (*ptr != l)) ptr = &((*ptr)->next); if (*ptr) *ptr = l->next; } static void flog_newline(Log *_l,int force) { File_Log *l = (File_Log *) _l; if (force || !l->needs_newline) return; l->needs_newline=0; fputc ('\n', l->fp); fflush (l->fp); } static void flog_sighup (Log * _l) { File_Log *l = (File_Log *) _l; if (!l->fp) return; log_f (_l, ""); fclose (l->fp); l->fp = fopen (l->filename, "a+"); log_f (_l, ""); } static void flog_emit_stamp(Log *_l) { File_Log *l = (File_Log *) _l; struct timeval tv = { 0 }; struct tm *tm; time_t t; static const char *days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; static const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; if (!l->fp) return; flog_newline(_l,0); gettimeofday (&tv, NULL); t = tv.tv_sec; tm = localtime (&t); fprintf (l->fp, "%s %2d %02d:%02d:%02d.%06d ", months[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec,(int) tv.tv_usec); } static void flog_check_rotate(Log *_l) { File_Log *l = (File_Log *) _l; if (l->rotate && rotate_check (l->filename)) { fclose (l->fp); rotate (l->filename); l->fp = fopen (l->filename, "a+"); } } static void flog_log_bytes (Log * _l, void *_buf,int len) { File_Log *l = (File_Log *) _l; uint8_t *buf=(uint8_t *) _buf; if (!l->fp) return; while (len--) { if (*buf=='\n') { flog_newline(_l,1); flog_check_rotate(_l); flog_emit_stamp(_l); } else { l->needs_newline++; fputc (*buf, l->fp); } buf++; } } static void flog_log (Log * _l, char *buf) { File_Log *l = (File_Log *) _l; if (!l->fp) return; flog_emit_stamp(_l); fputs (buf, l->fp); fputc ('\n', l->fp); fflush (l->fp); flog_check_rotate(_l); } static void flog_close (Log * _l) { File_Log *l = (File_Log *) _l; if (l->fp && l->do_close) fclose (l->fp); if (l->filename) free (l->filename); free (l); } Log * file_log_new (char *fn, int rotate) { File_Log *l; int dc = 1; l = xmalloc (sizeof (File_Log)); if (fn && strcmp (fn, "-")) { l->fp = fopen (fn, "a+"); if (!l->fp) { free (l); return NULL; } l->sighup = flog_sighup; } else { l->fp = stderr; dc = 0; } l->log = flog_log; l->log_bytes = flog_log_bytes; l->close = flog_close; l->do_close = dc; l->rotate = rotate; l->filename = strdup (fn); l->needs_newline=0; fput_cp (l->fp, 0xffef); log_add ((Log *) l); return (Log *) l; } void log_f (Log * log, char *fmt, ...) { int n; static char *buf; va_list ap; static int size; if (!log) return; if (!size) { size = 128; buf = malloc (size); } if (!buf) return; while (1) { va_start (ap, fmt); n = vsnprintf (buf, size, fmt, ap); va_end (ap); if (n > -1 && n < size) { log->log (log, buf); return; } if (n > -1) /* glibc 2.1 */ size = n + 1; else /* glibc 2.0 */ size *= 2; /* twice the old size */ buf = xrealloc (buf, size); if (!buf) return; } } work/src/log.h0000664000000000000000000000206513337271225010461 0ustar /* * log.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: log.h,v 1.7 2010/07/27 14:49:35 james Exp $ */ /* * $Log: log.h,v $ * Revision 1.7 2010/07/27 14:49:35 james * add support for byte logging * * Revision 1.6 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.5 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.4 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.3 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.2 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.1 2008/02/14 12:14:50 james * *** empty log message *** * */ #ifndef __LOG_H__ #define __LOG_H__ #define LOG_SIGNATURE \ struct Log_struct *next; \ void (*log)(struct Log_struct *,char *); \ void (*log_bytes)(struct Log_struct *,void *,int); \ void (*sighup)(struct Log_struct *); \ void (*close)(struct Log_struct *) typedef struct Log_struct { LOG_SIGNATURE; } Log; #endif /* __LOG_H__ */ work/src/project.h0000664000000000000000000000346413337271225011352 0ustar /* * project.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: project.h,v 1.11 2008/03/07 12:37:04 james Exp $ */ /* * $Log: project.h,v $ * Revision 1.11 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.10 2008/02/22 14:51:54 james * *** empty log message *** * * Revision 1.9 2008/02/13 18:05:06 james * *** empty log message *** * * Revision 1.8 2008/02/13 16:57:29 james * *** empty log message *** * * Revision 1.7 2008/02/13 09:12:21 james * *** empty log message *** * * Revision 1.6 2008/02/09 15:47:28 james * *** empty log message *** * * Revision 1.5 2008/02/07 00:39:13 james * *** empty log message *** * * Revision 1.4 2008/02/06 20:26:58 james * *** empty log message *** * * Revision 1.3 2008/02/04 05:45:55 james * :: * * Revision 1.2 2008/02/04 02:05:06 james * *** empty log message *** * * Revision 1.1 2008/02/03 16:20:24 james * *** empty log message *** * * */ #ifndef __PROJECT_H__ #define __PROJECT_H__ #include "config.h" #ifdef TM_IN_SYS_TIME #include #ifdef TIME_WITH_SYS_TIME #include #endif #else #ifdef TIME_WITH_SYS_TIME #include #endif #include #endif #include #include #ifdef HAVE_MALLOC_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #if defined(HAVE_STDINT_H) #include #elif defined(HAVE_SYS_INT_TYPES_H) #include #endif #include #include #include #include #include #include #include #include #include "sympathy.h" #endif /* __PROJECT_H__ */ work/src/prototypes.h0000664000000000000000000002106513337271225012131 0ustar /* ansi.c */ extern ANSI *ansi_new_from_terminal (TTY * t, int utf8); /* crt.c */ extern void crt_erase (CRT * c, CRT_Pos s, CRT_Pos e, int ea, int color); extern void crt_cls (CRT * c); extern void crt_scroll_up (CRT * c, CRT_Pos s, CRT_Pos e, int ea, int color); extern void crt_scroll_down (CRT * c, CRT_Pos s, CRT_Pos e, int ea, int color); extern void crt_reset (CRT * c); extern void crt_insert (CRT * c, CRT_CA ca); /* html.c */ extern ANSI *ansi_new_html (FILE * f); /* libsympathy.c */ /* render.c */ /* version.c */ extern char *libsympathy_version (void); /* vt102.c */ extern int vt102_cmd_length[128]; extern int vt102_cmd_termination[128]; extern void vt102_crt_update (Context * c); extern void vt102_do_resize (Context * c); extern void vt102_log_line (Context * c, int line); extern void vt102_history (Context * c, CRT_Pos t, CRT_Pos b); extern void vt102_clip_cursor (VT102 * v, CRT_Pos tl, CRT_Pos br); extern void vt102_cursor_normalize (VT102 * v); extern void vt102_cursor_carriage_return (VT102 * v); extern void vt102_cursor_advance_line (Context * c); extern void vt102_cursor_retreat_line (Context * c); extern void vt102_do_pending_wrap (Context * c); extern void vt102_cursor_advance (Context * c); extern void vt102_cursor_retreat (VT102 * v); extern void vt102_reset_tabs (VT102 * v); extern void vt102_cursor_advance_tab (VT102 * v); extern void vt102_cursor_retreat_tab (VT102 * v); extern void vt102_cursor_home (VT102 * v); extern void vt102_cursor_absolute (VT102 * v, int x, int y); extern void vt102_cursor_relative (VT102 * v, int x, int y); extern void vt102_delete_from_line (VT102 * v, CRT_Pos p); extern void vt102_insert_into_line (VT102 * v, CRT_Pos p); extern void vt102_change_mode (Context * c, int private, char *ns, int set); extern void vt102_parse_mode_string (Context * c, char *buf, int len); extern void vt102_change_attr (VT102 * v, char *na); extern void vt102_parse_attr_string (VT102 * v, char *buf, int len); extern void vt102_save_state (VT102 * v); extern void vt102_restore_state (VT102 * v); extern void vt102_regular_char (Context * c, VT102 * v, uint32_t ch); extern void vt102_send_id (Context * c, char *buf); extern void vt102_scs (Context * c, int g, int s); extern void vt102_status_line (VT102 * v, char *str); extern void vt102_parser_reset (VT102_parser * p); extern void vt102_reset_state (Context * c); extern int vt102_rx_hook (Context * c, int ch); extern int vt102_parse_char (Context * c, int ch); extern void vt102_send (Context * c, uint8_t key); extern void vt102_reset (Context * c); extern VT102 *vt102_new (CRT_Pos * size); extern void vt102_set_ansi (VT102 * v, int ansi); extern void vt102_resize (Context * c, CRT_Pos size); extern void vt102_free (VT102 * v); /* tty.c */ extern void tty_pre_select (TTY * t, fd_set * rfds, fd_set * wfds); extern int tty_get_status (TTY * t, TTY_Status * s); extern int tty_get_baud (TTY * t); extern void tty_set_baud (TTY * t, int rate); extern void tty_send_break (TTY * t); extern void tty_set_flow (TTY * t, int flow); extern void tty_hangup (TTY * t); extern void tty_length (TTY * t, int l); extern void tty_winch (TTY * t, CRT_Pos size); extern void tty_parse_reset (Context * c); extern void tty_analyse (Context * c); extern TTY_Parser *tty_parser_new (void); extern int tty_parse (Context * c, uint8_t * buf, int len); /* keydis.c */ extern KeyDis *keydis_vt102_new (void); extern KeyDis *keydis_ipc_new (Socket * s); /* history.c */ extern History *history_new (int n); extern void history_free (History * h); extern void history_add (History * h, CRT_CA * c); /* ring.c */ extern int ring_read (Ring * r, void *b, int n); extern int ring_write (Ring * r, void *b, int n); extern int ring_space (Ring * r); extern int ring_bytes (Ring * r); extern Ring *ring_new (int n); /* ptty.c */ extern TTY *ptty_open (char *path, char *argv[], CRT_Pos * size); /* terminal.c */ extern int terminal_winches; extern void terminal_atexit (void); extern void terminal_getsize (TTY * _t); extern void terminal_dispatch (void); extern void terminal_register_handlers (void); extern TTY *terminal_open (int rfd, int wfd); /* util.c */ extern int wrap_read (int fd, void *buf, int len); extern int wrap_write (int fd, void *buf, int len); extern void set_nonblocking (int fd); extern void set_blocking (int fd); extern void default_termios (struct termios *termios); extern void client_termios (struct termios *termios); extern int fput_cp (FILE * f, uint32_t ch); extern void crash_out (char *why); extern void *xmalloc (size_t s); extern void *xrealloc (void *p, size_t s); extern char *xstrdup (const char *s); /* log.c */ extern Log *file_log_new (char *fn, int rotate); extern void log_f (Log * log, char *fmt, ...); /* ipc.c */ extern IPC_Msg *ipc_check_for_message_in_slide (Slide * s); extern void ipc_consume_message_in_slide (Slide * s); extern int ipc_msg_send (Socket * s, IPC_Msg * m); extern int ipc_msg_send_debug (Socket * s, char *msg); extern int ipc_msg_send_initialize (Socket * s); extern int ipc_msg_send_history (Socket * s, History_ent * l); extern int ipc_msg_send_vt102 (Socket * s, VT102 * v); extern int ipc_msg_send_key (Socket * s, int key); extern int ipc_msg_send_term (Socket * s, void *buf, int len); extern int ipc_msg_send_status (Socket * s, char *buf); extern int ipc_msg_send_setbaud (Socket * s, int baud); extern int ipc_msg_send_sendbreak (Socket * s); extern int ipc_msg_send_setflow (Socket * s, int flow); extern int ipc_msg_send_setansi (Socket * s, int ansi); extern int ipc_msg_send_hangup (Socket * s); extern int ipc_msg_send_setsize (Socket * s, CRT_Pos size); extern int ipc_msg_send_reset (Socket * s); extern int ipc_msg_send_killme (Socket * s); /* slide.c */ extern void slide_free (Slide * s); extern void slide_consume (Slide * s, int n); extern void slide_added (Slide * s, int n); extern Slide *slide_new (int n); extern void slide_expand (Slide * s, int n); /* symsocket.c */ extern int wrap_recv (int fd, void *buf, int len); extern int wrap_send (int fd, void *buf, int len); extern void socket_free (Socket * s); extern void socket_free_parent (Socket * s); extern Socket *socket_listen (char *path); extern Socket *socket_accept (Socket * l); extern Socket *socket_connect (char *path); extern void socket_consume_msg (Socket * s); extern void socket_pre_select (Socket * s, fd_set * rfds, fd_set * wfds); extern int socket_post_select (Socket * s, fd_set * rfds, fd_set * wfds); extern int socket_write (Socket * s, void *buf, int len); /* serial.c */ extern TTY *serial_open (char *path, int lock_mode); /* cmd.c */ extern int cmd_parse (Cmd * c, Context * ctx, ANSI * a, char *buf); extern void cmd_show_status (Cmd * c, Context * ctx); extern int cmd_key (Cmd * c, Context * ctx, ANSI * a, int key); extern int cmd_deactivate (Cmd * c, Context * ctx); extern int cmd_activate (Cmd * c, Context * ctx); extern void cmd_new_status (Cmd * c, Context * ctx, char *msg); extern Cmd *cmd_new (void); /* lockfile.c */ extern Filelist *filelist_new (void); extern void filelist_remove (Filelist * fl, Filelist_ent * fle); extern void filelist_add (Filelist * fl, char *fn); extern void filelist_free (Filelist * fl); extern void filelist_print (Filelist * fl, FILE * f); extern int lockfile_make (char *name); extern void lockfile_add_places (Filelist * fl, char *leaf); extern void lockfile_regularize_and_add (Filelist * fl, char *leaf); extern void lockfile_add_name_from_path (Filelist * fl, char *file); extern void lockfile_add_name_from_dev (Filelist * fl, dev_t dev); extern void lockfile_check_dir_for_dev (Filelist * fl, char *dir, dev_t dev); extern Filelist *lockfile_make_list (char *device); extern void lockfile_remove_stale (Filelist * fl); extern Filelist *lockfile_lock (Filelist * fl); extern void lockfile_unlock (Filelist * fl); extern int serial_lock_check (Serial_lock * l); extern void serial_lock_free (Serial_lock * l); extern Serial_lock *serial_lock_new (char *dev, int mode); /* utf8.c */ extern int utf8_flush (Context * c); extern int utf8_parse (Context * c, uint32_t ch); extern UTF8 *utf8_new (void); extern int utf8_encode (char *ptr, int ch); extern int utf8_emit (TTY * t, int ch); /* vt102_charset.c */ extern uint32_t vt102_charset_c0[128]; extern uint32_t vt102_charset_us[128]; extern uint32_t vt102_charset_uk[128]; extern uint32_t vt102_charset_vt52[128]; extern uint32_t vt102_charset_gl[128]; extern uint32_t *charset_from_csid[]; /* rotate.c */ extern void rotate_gzip (char *file); extern void rotate (char *file); extern int rotate_check (char *file); /* raw.c */ extern RX *rx_new_raw (int rfd, int wfd); extern TTY *terminal_new_raw (int rfd, int wfd); extern ANSI *ansi_new_raw (int rfd, int wfd); work/src/ptty.c0000664000000000000000000001066713337271225010702 0ustar /* * ptty.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: ptty.c,v 1.23 2008/03/12 01:30:23 james Exp $"; /* * $Log: ptty.c,v $ * Revision 1.23 2008/03/12 01:30:23 james * *** empty log message *** * * Revision 1.22 2008/03/12 01:26:56 james * *** empty log message *** * * Revision 1.21 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.20 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.19 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.18 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.17 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.16 2008/02/28 16:57:52 james * *** empty log message *** * * Revision 1.15 2008/02/27 09:42:53 james * *** empty log message *** * * Revision 1.14 2008/02/27 09:42:22 james * *** empty log message *** * * Revision 1.13 2008/02/27 01:31:38 james * *** empty log message *** * * Revision 1.12 2008/02/27 01:31:14 james * *** empty log message *** * * Revision 1.11 2008/02/26 23:23:17 james * *** empty log message *** * * Revision 1.10 2008/02/24 00:42:53 james * *** empty log message *** * * Revision 1.9 2008/02/23 13:05:58 staffcvs * *** empty log message *** * * Revision 1.8 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.7 2008/02/22 17:07:00 james * *** empty log message *** * * Revision 1.6 2008/02/22 14:51:54 james * *** empty log message *** * * Revision 1.5 2008/02/15 23:52:12 james * *** empty log message *** * * Revision 1.4 2008/02/14 10:39:14 james * *** empty log message *** * * Revision 1.3 2008/02/13 09:12:21 james * *** empty log message *** * * Revision 1.2 2008/02/12 22:36:46 james * *** empty log message *** * * Revision 1.1 2008/02/09 15:47:28 james * *** empty log message *** * * Revision 1.2 2008/02/07 11:11:14 staffcvs * *** empty log message *** * * Revision 1.1 2008/02/07 01:02:52 james * *** empty log message *** * * Revision 1.3 2008/02/06 17:53:28 james * *** empty log message *** * * Revision 1.2 2008/02/04 02:05:06 james * *** empty log message *** * * Revision 1.1 2008/02/04 01:32:39 james * *** empty log message *** * */ #include "project.h" typedef struct { TTY_SIGNATURE; int fd; pid_t child; } PTTY; static void ptty_close (TTY * _t) { PTTY *t = (PTTY *) _t; if (!t) return; close (t->fd); free (t); } static int ptty_read (TTY * _t, void *buf, int len) { PTTY *t = (PTTY *) _t; int red, done = 0; do { red = wrap_read (t->fd, buf, len); if (red < 0) return -1; if (!red) return done; buf += red; len -= red; done += red; } while (len); return done; } static int ptty_write (TTY * _t, void *buf, int len) { int writ, done = 0; PTTY *t = (PTTY *) _t; do { writ = wrap_write (t->fd, buf, len); if (writ < 0) return -1; if (!writ) sleep (1); buf += writ; len -= writ; done += writ; } while (len); return done; } TTY * ptty_open (char *path, char *argv[], CRT_Pos * size) { PTTY *t; pid_t child; char name[1024]; struct winsize winsize = { 0 }; struct termios ctermios = { 0 }; int fd; char *default_argv[] = { "-", (char *) 0 }; client_termios (&ctermios); winsize.ws_row = size ? size->y : VT102_ROWS_24; winsize.ws_col = size ? size->x : VT102_COLS_80; child = forkpty (&fd, name, &ctermios, &winsize); switch (child) { case -1: /* boo hiss */ return NULL; case 0: /* waaah */ setenv ("TERM", "xterm", 1); if (!path) path = "/bin/sh"; if (!argv) argv = default_argv; if (path[0] == '/') execv (path, argv); else execvp (path, argv); _exit (-1); } set_nonblocking (fd); #if 0 { struct termios termios = { 0 }; tcgetattr (fd, &termios); default_termios (&termios); tcsetattr (fd, TCSANOW, &termios); } #endif t = (PTTY *) xmalloc (sizeof (PTTY)); strncpy (t->name, name, sizeof (t->name)); t->name[sizeof (t->name) - 1] = 0; t->recv = ptty_read; t->xmit = ptty_write; t->close = ptty_close; t->fd = fd; t->child = child; t->rfd = t->fd; t->wfd = t->fd; t->size.x = winsize.ws_row; t->size.y = winsize.ws_col; t->blocked = 0; t->hanging_up = 0; return (TTY *) t; } work/src/raw.c0000664000000000000000000000754013337271225010467 0ustar /* * raw.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: raw.c,v 1.10 2011/02/28 18:10:43 james Exp $"; /* * $Log: raw.c,v $ * Revision 1.10 2011/02/28 18:10:43 james * *** empty log message *** * * Revision 1.9 2011/02/06 16:51:22 james * *** empty log message *** * * Revision 1.8 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.7 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.6 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.5 2008/03/06 21:34:09 james * *** empty log message *** * * Revision 1.4 2008/03/06 21:33:02 james * *** empty log message *** * * Revision 1.3 2008/03/06 17:21:41 james * *** empty log message *** * * Revision 1.2 2008/03/06 16:49:39 james * *** empty log message *** * * Revision 1.1 2008/03/06 16:49:05 james * *** empty log message *** * * */ #include "project.h" typedef struct { RX_SIGNATURE; int rfd; int wfd; } RX_Raw; typedef struct { TTY_SIGNATURE; } RAW_TERMINAL; static int rx_raw_rx (RX * _r, int ch) { RX_Raw *r = (RX_Raw *) _r; int ret; uint8_t c = ch; set_blocking (r->wfd); ret = (write (r->wfd, &c, 1) == 1) ? 0 : -1; } static void rx_raw_close (RX * r) { free (r); } RX * rx_new_raw (int rfd, int wfd) { RX_Raw *ret; ret = xmalloc (sizeof (RX_Raw)); memset (ret, 0, sizeof (RX_Raw)); ret->rx = rx_raw_rx; ret->close = rx_raw_close; ret->rfd = rfd; ret->wfd = wfd; return (RX *) ret; } static int my_wrap_read (int fd, void *buf, int len) { int red; red = read (fd, buf, len); #if 1 if (!red) return -1; #endif if ((red < 0) && (errno == EAGAIN)) red = 0; return red; } static int raw_terminal_read (TTY * _t, void *buf, int len) { RAW_TERMINAL *t = (RAW_TERMINAL *) _t; int red, done = 0; set_nonblocking (t->rfd); do { red = my_wrap_read (t->rfd, buf, len); if (red < 0) return done ? done:-1; if (!red) return done; buf += red; len -= red; done += red; } while (len); return done; } static int raw_terminal_write (TTY * _t, void *buf, int len) { int writ, done = 0; RAW_TERMINAL *t = (RAW_TERMINAL *) _t; set_blocking (t->wfd); do { writ = wrap_write (t->wfd, buf, len); if (writ < 0) return -1; if (!writ) usleep (1000); buf += writ; len -= writ; done += writ; } while (len); return done; } static void raw_terminal_close (TTY * _t) { RAW_TERMINAL *t = (RAW_TERMINAL *) _t; set_blocking (t->rfd); set_blocking (t->wfd); free (t); } TTY * terminal_new_raw (int rfd, int wfd) { RAW_TERMINAL *t; t = (RAW_TERMINAL *) malloc (sizeof (RAW_TERMINAL)); memset (t, 0, sizeof (t)); strcpy (t->name, "raw"); t->rfd = rfd; t->wfd = wfd; set_nonblocking (rfd); set_nonblocking (wfd); t->recv = raw_terminal_read; // t->xmit = raw_terminal_write; t->close = raw_terminal_close; t->blocked = 0; return (TTY *) t; } static void ansi_raw_one_shot (ANSI * a, CRT * c) { } static int ansi_raw_key (ANSI * a, Context * c, int key) { return c->k->key (c->k, c, key); } static void ansi_raw_parse (ANSI * a, Context * c, uint8_t * buf, int red) { while (red--) ansi_raw_key (a, c, *(buf++)); } static int ansi_raw_dispatch (ANSI * a, Context * c) { char buf[1024]; int red; if (!a->terminal) return 0; red = a->terminal->recv (a->terminal, buf, sizeof (buf)); if (red <= 0) return red; ansi_raw_parse (a, c, buf, red); return 0; } static void ansi_raw_free (ANSI * a) { free (a); } ANSI * ansi_new_raw (int rfd, int wfd) { ANSI *ret; ret = malloc (sizeof (ANSI)); memset (ret, 0, sizeof (ANSI)); ret->terminal = terminal_new_raw (rfd, wfd); ret->dispatch = ansi_raw_dispatch; ret->close = ansi_raw_free; return ret; } work/src/render.c0000664000000000000000000000070313337271225011147 0ustar /* * render.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: render.c,v 1.3 2008/03/07 12:37:04 james Exp $"; /* * $Log: render.c,v $ * Revision 1.3 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.2 2008/02/04 02:05:06 james * *** empty log message *** * * Revision 1.1 2008/02/03 23:31:25 james * *** empty log message *** * */ work/src/ring.c0000664000000000000000000000304613337271225010632 0ustar /* * ring.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: ring.c,v 1.8 2008/03/07 13:16:02 james Exp $"; /* * $Log: ring.c,v $ * Revision 1.8 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.7 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.6 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.5 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.4 2008/02/13 16:57:29 james * *** empty log message *** * * Revision 1.3 2008/02/13 09:12:21 james * *** empty log message *** * * Revision 1.2 2008/02/12 22:36:46 james * *** empty log message *** * * Revision 1.1 2008/02/08 15:06:42 james * *** empty log message *** * */ #include "project.h" int ring_read (Ring * r, void *b, int n) { int red = 0; while (n--) { if (!ring_read_one (r, b)) break; b++; red++; } return red; } int ring_write (Ring * r, void *b, int n) { int writ = 0; while (n--) { if (!ring_write_one (r, b)) break; b++; writ++; } return writ; } int ring_space (Ring * r) { int i; i = r->size - RING_NEXT_W (r) + r->rptr; i %= r->size; return i; } int ring_bytes (Ring * r) { int i; i = r->size + r->wptr - r->rptr; i %= r->size; return i; } Ring * ring_new (int n) { Ring *ret = (Ring *) xmalloc (sizeof (Ring)); ret->ring = (uint8_t *) xmalloc (n); ret->size = n; ret->wptr = ret->rptr = 0; return ret; } work/src/ring.h0000664000000000000000000000260113337271225010633 0ustar /* * ring.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: ring.h,v 1.6 2008/03/10 11:49:33 james Exp $ */ /* * $Log: ring.h,v $ * Revision 1.6 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.5 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.4 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.3 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.2 2008/02/12 22:36:46 james * *** empty log message *** * * Revision 1.1 2008/02/08 15:06:42 james * *** empty log message *** * */ #ifndef __RING_H__ #define __RING_H__ typedef struct { uint8_t *ring; int wptr; int rptr; int size; } Ring; #define RING_NEXT(r,a) (((a)+1) % ((r)->size)) #define RING_NEXT_R(r) RING_NEXT(r,r->rptr) #define RING_NEXT_W(r) RING_NEXT(r,r->wptr) #define RING_EMPTY(r) (((r)->wptr) == ((r)->rptr)) #define RING_FULL(r) (RING_NEXT_W(r) == ((r)->rptr)) static inline int ring_write_one (Ring * r, uint8_t * c) { if (RING_FULL (r)) return 0; r->ring[r->wptr++] = *c; if (r->wptr == r->size) r->wptr = 0; return 1; } static inline int ring_read_one (Ring * r, uint8_t * c) { if (RING_EMPTY (r)) return 0; *c = r->ring[r->rptr++]; if (r->rptr == r->size) r->rptr = 0; return 1; } #endif /* __RING_H__ */ work/src/rotate.c0000664000000000000000000000424513337271225011173 0ustar /* * rotate.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: rotate.c,v 1.11 2010/07/16 11:04:10 james Exp $"; /* * $Log: rotate.c,v $ * Revision 1.11 2010/07/16 11:04:10 james * ignore tedious return values * * Revision 1.10 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.9 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.8 2008/03/06 01:41:48 james * *** empty log message *** * * Revision 1.7 2008/03/03 18:16:16 james * *** empty log message *** * * Revision 1.6 2008/03/03 06:30:15 staffcvs * *** empty log message *** * * Revision 1.5 2008/03/03 06:26:05 staffcvs * *** empty log message *** * * Revision 1.4 2008/03/03 06:22:51 james * *** empty log message *** * * Revision 1.3 2008/03/03 06:20:14 james * *** empty log message *** * * Revision 1.2 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.1 2008/03/03 06:04:18 james * *** empty log message *** * */ #include "project.h" #include #define ROTATE_IF_OVER (4*1024*1024) #define NUM_FILES_TO_KEEP 10 #define GZIP_AFTER 2 void rotate_gzip (char *file) { switch (fork ()) { case 0: break; case -1: default: return; } int result; result = daemon (1, 0); execlp ("gzip", "gzip", file, (char *) 0); _exit (-1); } void rotate (char *file) { char *buf1, *buf2; int i; if (!file) return; i = strlen (file) + 32; buf1 = xmalloc (i); buf2 = xmalloc (i); for (i = NUM_FILES_TO_KEEP; i > 0; --i) { sprintf (buf1, "%s.%d", file, i - 1); sprintf (buf2, "%s.%d", file, i); rename (buf1, buf2); sprintf (buf1, "%s.%d.gz", file, i - 1); sprintf (buf2, "%s.%d.gz", file, i); rename (buf1, buf2); } sprintf (buf1, "%s.%d", file, 0); rename (file, buf1); sprintf (buf1, "%s.%d", file, GZIP_AFTER); if (!access (buf1, R_OK)) rotate_gzip (buf1); free (buf2); free (buf1); } int rotate_check (char *file) { struct stat st; if (!file) return 0; if (stat (file, &st)) return 0; if (st.st_size <= ROTATE_IF_OVER) return 0; return 1; } work/src/rx.h0000664000000000000000000000142513337271225010330 0ustar /* * rx.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: rx.h,v 1.5 2008/03/10 11:49:33 james Exp $ */ /* * $Log: rx.h,v $ * Revision 1.5 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.4 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.3 2008/03/06 16:49:39 james * *** empty log message *** * * Revision 1.2 2008/03/06 16:49:05 james * *** empty log message *** * * Revision 1.1 2008/03/06 15:17:26 james * *** empty log message *** * * */ #ifndef __RX_H__ #define __RX_H__ #define RX_SIGNATURE \ int (*rx)(struct RX_struct *,int); \ void (*close)(struct RX_struct *); typedef struct RX_struct { RX_SIGNATURE; } RX; #endif /* __RX_H__ */ work/src/serial.c0000664000000000000000000001035213337271225011150 0ustar /* * serial.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: serial.c,v 1.18 2011/02/06 16:51:22 james Exp $"; /* * $Log: serial.c,v $ * Revision 1.18 2011/02/06 16:51:22 james * *** empty log message *** * * Revision 1.17 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.16 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.15 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.14 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.13 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.12 2008/02/28 16:57:52 james * *** empty log message *** * * Revision 1.11 2008/02/26 23:23:17 james * *** empty log message *** * * Revision 1.10 2008/02/24 00:47:14 james * *** empty log message *** * * Revision 1.9 2008/02/24 00:42:53 james * *** empty log message *** * * Revision 1.8 2008/02/23 13:05:58 staffcvs * *** empty log message *** * * Revision 1.7 2008/02/15 23:52:12 james * *** empty log message *** * * Revision 1.6 2008/02/15 19:51:30 james * *** empty log message *** * * Revision 1.5 2008/02/15 19:09:00 james * *** empty log message *** * * Revision 1.4 2008/02/15 16:48:56 james * *** empty log message *** * * Revision 1.3 2008/02/15 03:32:07 james * *** empty log message *** * * Revision 1.2 2008/02/14 16:21:17 james * *** empty log message *** * * Revision 1.1 2008/02/14 12:51:14 james * *** empty log message *** * * Revision 1.4 2008/02/14 10:39:14 james * *** empty log message *** * * Revision 1.3 2008/02/13 09:12:21 james * *** empty log message *** * * Revision 1.2 2008/02/12 22:36:46 james * *** empty log message *** * * Revision 1.1 2008/02/09 15:47:28 james * *** empty log message *** * * Revision 1.2 2008/02/07 11:11:14 staffcvs * *** empty log message *** * * Revision 1.1 2008/02/07 01:02:52 james * *** empty log message *** * * Revision 1.3 2008/02/06 17:53:28 james * *** empty log message *** * * Revision 1.2 2008/02/04 02:05:06 james * *** empty log message *** * * Revision 1.1 2008/02/04 01:32:39 james * *** empty log message *** * */ #include "project.h" #include #include #include typedef struct { TTY_SIGNATURE; Serial_lock *lock; int fd; } Serial; static void serial_close (TTY * _t) { Serial *t = (Serial *) _t; if (!t) return; tcflush (t->fd, TCIOFLUSH); close (t->fd); free (t); } static int serial_read (TTY * _t, void *buf, int len) { Serial *t = (Serial *) _t; int red, done = 0; t->blocked = serial_lock_check (t->lock); if (t->blocked) return 0; do { red = wrap_read (t->fd, buf, len); if (red < 0) return done ? done:-1; if (!red) return done; buf += red; len -= red; done += red; } while (len); return done; } static int serial_write (TTY * _t, void *buf, int len) { int writ, done = 0; Serial *t = (Serial *) _t; t->blocked = serial_lock_check (t->lock); if (t->blocked) return 0; do { writ = wrap_write (t->fd, buf, len); if (writ < 0) return -1; if (!writ) sleep (1); buf += writ; len -= writ; done += writ; } while (len); return done; } TTY * serial_open (char *path, int lock_mode) { Serial *t; pid_t child; char name[1024]; struct winsize winsize = { 0 }; struct termios termios; int fd; Serial_lock *l; l = serial_lock_new (path, lock_mode); if (!l) return NULL; fd = open (path, O_RDWR | O_NOCTTY | O_NONBLOCK); set_nonblocking (fd); if (tcgetattr (fd, &termios)) { close (fd); return NULL; } default_termios (&termios); if (tcsetattr (fd, TCSANOW, &termios)) { close (fd); return NULL; } t = (Serial *) xmalloc (sizeof (Serial)); t->lock = l; strncpy (t->name, path, sizeof (t->name)); t->name[sizeof (t->name) - 1] = 0; t->recv = serial_read; t->xmit = serial_write; t->close = serial_close; t->fd = fd; t->rfd = t->fd; t->wfd = t->fd; t->size.x = VT102_COLS_80; t->size.y = VT102_ROWS_24; t->blocked = serial_lock_check (t->lock); t->hanging_up = 0; return (TTY *) t; } work/src/slide.c0000664000000000000000000000360513337271225010774 0ustar /* * slide.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: slide.c,v 1.8 2008/03/07 14:13:40 james Exp $"; /* * $Log: slide.c,v $ * Revision 1.8 2008/03/07 14:13:40 james * *** empty log message *** * * Revision 1.7 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.6 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.5 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.4 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.3 2008/02/14 02:46:44 james * *** empty log message *** * * Revision 1.2 2008/02/14 00:57:58 james * *** empty log message *** * * Revision 1.1 2008/02/13 16:57:29 james * *** empty log message *** * * Revision 1.3 2008/02/13 09:12:21 james * *** empty log message *** * * Revision 1.2 2008/02/12 22:36:46 james * *** empty log message *** * * Revision 1.1 2008/02/08 15:06:42 james * *** empty log message *** * */ #include "project.h" void slide_free (Slide * s) { free (s->slide); free (s); } void slide_consume (Slide * s, int n) { s->nbytes -= n; if (s->nbytes < 0) crash_out ("slide_consume called with -ve number of bytes"); memmove (s->slide, s->slide + n, s->nbytes); if ((s->size > s->target_size) && (s->nbytes <= s->target_size)) { s->size = s->target_size; s->slide = realloc (s->slide, s->size); } } void slide_added (Slide * s, int n) { s->nbytes += n; } Slide * slide_new (int n) { Slide *ret = (Slide *) xmalloc (sizeof (Slide)); ret->slide = (uint8_t *) xmalloc (n); ret->size = n; ret->target_size = n; ret->nbytes = 0; return ret; } void slide_expand (Slide * s, int n) { n += s->nbytes; if (n <= s->size) return; while (n > s->size) s->size <<= 1; s->slide = xrealloc (s->slide, s->size); } work/src/slide.h0000664000000000000000000000220413337271225010773 0ustar /* * ring.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: slide.h,v 1.5 2008/03/10 11:49:33 james Exp $ */ /* * $Log: slide.h,v $ * Revision 1.5 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.4 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.3 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.2 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.1 2008/02/13 16:57:29 james * *** empty log message *** * * Revision 1.2 2008/02/12 22:36:46 james * *** empty log message *** * * Revision 1.1 2008/02/08 15:06:42 james * *** empty log message *** * */ #ifndef __SLIDE_H__ #define __SLIDE_H__ typedef struct { uint8_t *slide; int nbytes; int target_size; int size; } Slide; #define SLIDE_FULL(s) ((s)->nbytes==(s)->size) #define SLIDE_EMPTY(s) (!((s)->nbytes)) #define SLIDE_SPACE(s) (((s)->size)-((s)->nbytes)) #define SLIDE_BYTES(s) ((s)->nbytes) #define SLIDE_RPTR(s) ((s)->slide) #define SLIDE_WPTR(s) (((s)->slide)+((s)->nbytes)) #endif /* __SLIDE_H__ */ work/src/stamp-h10000664000000000000000000000003313337271225011075 0ustar timestamp for src/config.h work/src/sympathy.h.head.in0000664000000000000000000000335113337271225013062 0ustar /* * sympathy.h.head.in: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: sympathy.h.head.in,v 1.4 2010/07/16 11:06:39 james Exp $ */ /* * $Log: sympathy.h.head.in,v $ * Revision 1.4 2010/07/16 11:06:39 james * add missing G2 * * Revision 1.3 2008/03/07 14:13:40 james * *** empty log message *** * * Revision 1.2 2008/02/13 18:05:06 james * *** empty log message *** * * Revision 1.1 2008/02/13 16:57:29 james * *** empty log message *** * * Revision 1.1 2008/02/03 16:20:24 james * *** empty log message *** * * */ /* MAKE ABSOLUTELY SURE THAT YOU ARE EDITING THE sympathy.h.in */ /* FILE FROM WHICH THIS IS GENERATED - OTHERWISE YOUR EDITS */ /* WILL BE LOST */ #ifndef __SYMPATHY_H__ #define __SYMPATHY_H__ #ifdef __cplusplus extern "C" { #endif #include #include #include /* the integer constants here are set by configure */ /* get uint32_t and friends defined */ #if @G2_HAVE_STDINT_H@ #include #elif @G2_HAVE_SYS_INT_TYPES_H@ #include #endif #if @G2_HAVE_UNISTD_H@ #include #endif /* If the following is <> then configure failed to find where */ /* struct tm was defined - report it as a bug */ /* get struct tm defined */ #include <@G2_TM_H@> #if @G2_TM_IN_SYS_TIME@ #include #if @G2_TIME_WITH_SYS_TIME@ #include #endif #else #if @G2_TIME_WITH_SYS_TIME@ #include #endif #include #endif #if @G2_HAVE_MALLOC_H@ #include #endif #if @G2_HAVE_UNISTD_H@ #include #endif #if @G2_HAVE_STDINT_H@ #include #elif @G2_HAVE_SYS_INT_TYPES_H@ #include #endif #include #include work/src/sympathy.h.tail0000664000000000000000000000007113337271225012501 0ustar #ifdef __cplusplus } #endif #endif /* __SYMPATHY_H__ */ work/src/symsocket.c0000664000000000000000000001370713337271225011721 0ustar /* * symsocket.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: symsocket.c,v 1.13 2008/03/07 14:13:40 james Exp $"; /* * $Log: symsocket.c,v $ * Revision 1.13 2008/03/07 14:13:40 james * *** empty log message *** * * Revision 1.12 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.11 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.10 2008/03/03 18:16:16 james * *** empty log message *** * * Revision 1.9 2008/03/03 18:15:19 james * *** empty log message *** * * Revision 1.8 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.7 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.6 2008/02/27 00:27:22 james * *** empty log message *** * * Revision 1.5 2008/02/20 22:54:22 staffcvs * *** empty log message *** * * Revision 1.4 2008/02/20 18:31:53 james * *** empty log message *** * * Revision 1.3 2008/02/14 02:46:44 james * *** empty log message *** * * Revision 1.2 2008/02/14 00:57:58 james * *** empty log message *** * * Revision 1.1 2008/02/13 18:05:06 james * *** empty log message *** * */ #include "project.h" #include #include #define BUF_SIZE 65536 #define MAX_TXN 4096 int wrap_recv (int fd, void *buf, int len) { int red; red = recv (fd, buf, len, 0); if (!red) return -1; if ((red < 0) && (errno == EAGAIN)) red = 0; return red; } int wrap_send (int fd, void *buf, int len) { int writ; errno = 0; writ = send (fd, buf, len, MSG_NOSIGNAL); if (!writ) return -1; if ((writ < 0) && (errno == EAGAIN)) writ = 0; return writ; } void socket_free (Socket * s) { if (!s) return; if (s->read_buf) slide_free (s->read_buf); if (s->write_buf) slide_free (s->write_buf); if (s->path_to_unlink) { unlink (s->path_to_unlink); free (s->path_to_unlink); } close (s->fd); free (s); } void socket_free_parent (Socket * s) { if (!s) return; if (s->read_buf) slide_free (s->read_buf); if (s->write_buf) slide_free (s->write_buf); if (s->path_to_unlink) free (s->path_to_unlink); close (s->fd); free (s); } Socket * socket_listen (char *path) { int fd; struct sockaddr_un *sun; Socket *ret; int n; unlink (path); fd = socket (PF_UNIX, SOCK_STREAM, 0); if (fd < 0) return NULL; n = strlen (path) + sizeof (struct sockaddr_un); sun = (struct sockaddr_un *) xmalloc (n); memset (sun, 0, n); sun->sun_family = AF_UNIX; strcpy (sun->sun_path, path); if (bind (fd, (struct sockaddr *) sun, SUN_LEN (sun)) < 0) { free (sun); close (fd); return NULL; } free (sun); if (listen (fd, 5) < 0) { close (fd); return NULL; } set_nonblocking (fd); ret = (Socket *) xmalloc (sizeof (Socket)); memset (ret, 0, sizeof (Socket)); ret->read_buf = NULL; ret->write_buf = NULL; ret->fd = fd; ret->path_to_unlink = strdup (path); return ret; } Socket * socket_accept (Socket * l) { Socket *ret; int len; int fd; struct sockaddr_un sun; len = sizeof (struct sockaddr_un); fd = accept (l->fd, (struct sockaddr *) &sun, &len); if (fd < 0) return NULL; ret = (Socket *) xmalloc (sizeof (Socket)); memset (ret, 0, sizeof (Socket)); set_nonblocking (fd); ret->fd = fd; ret->read_buf = slide_new (BUF_SIZE); ret->write_buf = slide_new (BUF_SIZE); ret->msg = 0; return ret; } /* Blocking for now */ Socket * socket_connect (char *path) { int n; int fd; struct sockaddr_un *sun; Socket *ret; fd = socket (PF_UNIX, SOCK_STREAM, 0); if (fd < 0) return NULL; n = strlen (path) + sizeof (struct sockaddr_un); sun = (struct sockaddr_un *) xmalloc (n); memset (sun, 0, n); sun->sun_family = AF_UNIX; strcpy (sun->sun_path, path); if (connect (fd, (struct sockaddr *) sun, SUN_LEN (sun))) { free (sun); close (fd); return NULL; } free (sun); set_nonblocking (fd); ret = (Socket *) xmalloc (sizeof (Socket)); memset (ret, 0, sizeof (Socket)); ret->fd = fd; ret->read_buf = slide_new (BUF_SIZE); ret->write_buf = slide_new (BUF_SIZE); ret->msg = 0; return ret; } void socket_consume_msg (Socket * s) { int n; if (!s->msg) return; ipc_consume_message_in_slide (s->read_buf); s->msg = ipc_check_for_message_in_slide (s->read_buf); } void socket_pre_select (Socket * s, fd_set * rfds, fd_set * wfds) { char buf[1024]; int n; /* Server socket */ if (SOCKET_IS_LISTENER (s)) { FD_SET (s->fd, rfds); return; } if (!SLIDE_EMPTY (s->write_buf)) FD_SET (s->fd, wfds); if (!SLIDE_FULL (s->read_buf)) FD_SET (s->fd, rfds); } int socket_post_select (Socket * s, fd_set * rfds, fd_set * wfds) { char buf[1024]; int n; int error = 0; if ((!SLIDE_EMPTY (s->write_buf)) && FD_ISSET (s->fd, wfds)) { n = (SLIDE_BYTES (s->write_buf) > MAX_TXN) ? MAX_TXN : SLIDE_BYTES (s->write_buf); n = wrap_send (s->fd, SLIDE_RPTR (s->write_buf), n); if (n > 0) slide_consume (s->write_buf, n); if (n < 0) error = -1; } if (!SLIDE_FULL (s->read_buf) && FD_ISSET (s->fd, rfds)) { n = (SLIDE_SPACE (s->read_buf) > MAX_TXN) ? MAX_TXN : SLIDE_SPACE (s->read_buf); n = wrap_recv (s->fd, SLIDE_WPTR (s->read_buf), n); if (n > 0) slide_added (s->read_buf, n); if (n < 0) error = -1; } s->msg = ipc_check_for_message_in_slide (s->read_buf); return error; } int socket_write (Socket * s, void *buf, int len) { int n; slide_expand (s->write_buf, len); memcpy (SLIDE_WPTR (s->write_buf), buf, len); slide_added (s->write_buf, len); n = (SLIDE_BYTES (s->write_buf) > MAX_TXN) ? MAX_TXN : SLIDE_BYTES (s->write_buf); n = wrap_send (s->fd, SLIDE_RPTR (s->write_buf), n); { uint8_t *c = SLIDE_RPTR (s->write_buf); } if (n > 0) slide_consume (s->write_buf, n); if (n < 0) return -1; return len; } work/src/symsocket.h0000664000000000000000000000163413337271225011722 0ustar /* * symsocket.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: symsocket.h,v 1.6 2008/03/10 11:49:33 james Exp $ */ /* * $Log: symsocket.h,v $ * Revision 1.6 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.5 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.4 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.3 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.2 2008/02/20 18:31:53 james * *** empty log message *** * * Revision 1.1 2008/02/13 18:05:06 james * *** empty log message *** * */ #ifndef __SYMSOCKET_H__ #define __SYMSOCKET_H__ typedef struct { int fd; Slide *read_buf; Slide *write_buf; IPC_Msg *msg; char *path_to_unlink; } Socket; #define SOCKET_IS_LISTENER(s) (!((s)->read_buf)) #endif /* __SYMSOCKET_H__ */ work/src/terminal.c0000664000000000000000000001364313337271225011512 0ustar /* * terminal.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: terminal.c,v 1.24 2008/03/12 10:47:26 james Exp $"; /* * $Log: terminal.c,v $ * Revision 1.24 2008/03/12 10:47:26 james * @@ * * Revision 1.23 2008/03/12 01:30:23 james * *** empty log message *** * * Revision 1.22 2008/03/11 17:56:50 james * *** empty log message *** * * Revision 1.21 2008/03/11 17:56:04 james * *** empty log message *** * * Revision 1.20 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.19 2008/03/07 14:16:44 james * *** empty log message *** * * Revision 1.18 2008/03/07 14:13:40 james * *** empty log message *** * * Revision 1.17 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.16 2008/03/07 12:42:08 james * *** empty log message *** * * Revision 1.15 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.14 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.13 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.12 2008/02/28 16:57:52 james * *** empty log message *** * * Revision 1.11 2008/02/26 23:56:12 james * *** empty log message *** * * Revision 1.10 2008/02/26 23:23:17 james * *** empty log message *** * * Revision 1.9 2008/02/15 03:32:07 james * *** empty log message *** * * Revision 1.8 2008/02/14 10:39:14 james * *** empty log message *** * * Revision 1.7 2008/02/14 01:55:57 james * *** empty log message *** * * Revision 1.6 2008/02/14 00:57:58 james * *** empty log message *** * * Revision 1.5 2008/02/13 18:05:06 james * *** empty log message *** * * Revision 1.4 2008/02/13 16:57:29 james * *** empty log message *** * * Revision 1.3 2008/02/13 09:12:21 james * *** empty log message *** * * Revision 1.2 2008/02/13 01:08:18 james * *** empty log message *** * * Revision 1.1 2008/02/12 22:36:46 james * *** empty log message *** * * Revision 1.1 2008/02/09 15:47:28 james * *** empty log message *** * * Revision 1.2 2008/02/07 11:11:14 staffcvs * *** empty log message *** * * Revision 1.1 2008/02/07 01:02:52 james * *** empty log message *** * * Revision 1.3 2008/02/06 17:53:28 james * *** empty log message *** * * Revision 1.2 2008/02/04 02:05:06 james * *** empty log message *** * * Revision 1.1 2008/02/04 01:32:39 james * *** empty log message *** * */ #include "project.h" typedef struct TERMINAL_struct { TTY_SIGNATURE; struct termios orig_termios; struct TERMINAL_struct *next; } TERMINAL; static TERMINAL *terminal_list = NULL; int terminal_winches; static void terminal_close (TTY * _t) { char buf[32]; int i; TERMINAL *t = (TERMINAL *) _t; TERMINAL **ptr = &terminal_list; if (!t) return; /* Take out of cleanup list */ while (*ptr && (*ptr != t)) ptr = &((*ptr)->next); if (*ptr) *ptr = t->next; tcsetattr (t->wfd, TCSANOW, &t->orig_termios); set_nonblocking (t->wfd); t->xmit (_t, "\033%@", 3); // Leave UTF-8 t->xmit (_t, "\033(B", 3); // US-ASCII in G0 t->xmit (_t, "\033)B", 3); // US-ASCII in G1 t->xmit (_t, "\017", 1); // Select G0 t->xmit (_t, "\033[?25h", 6); // Show cursor t->xmit (_t, "\033[r", 3); // No margins t->xmit (_t, "\033[0m", 4); // Default attributes i = sprintf (buf, "\033[%d;%dH", t->displayed_length ? (t->displayed_length + 1) : (CRT_ROWS + 1), 1); // Cursor to bottom t->xmit (_t, buf, i); t->xmit (_t, "\033[J", 3); // erase rest of screen set_blocking (t->rfd); set_blocking (t->wfd); free (t); } void terminal_atexit (void) { while (terminal_list) terminal_close ((TTY *) terminal_list); } static void sigint (int dummy) { terminal_atexit (); exit (-1); } static void sigwinch (int not) { terminal_winches++; } void terminal_getsize (TTY * _t) { TERMINAL *t = (TERMINAL *) _t; struct winsize sz = { 0 }; if (!t) return; if (ioctl (t->wfd, TIOCGWINSZ, &sz)) { t->size.x = CRT_COLS; t->size.y = CRT_ROWS; } else { t->size.x = sz.ws_col; t->size.y = sz.ws_row; } } void terminal_dispatch (void) { TERMINAL *t; if (!terminal_winches) return; terminal_winches = 0; for (t = terminal_list; t; t = t->next) terminal_getsize ((TTY *) t); } static int terminal_read (TTY * _t, void *buf, int len) { TERMINAL *t = (TERMINAL *) _t; int red, done = 0; terminal_dispatch (); set_nonblocking (t->rfd); do { red = wrap_read (t->rfd, buf, len); if (red < 0) return -1; if (!red) return done; buf += red; len -= red; done += red; } while (len); return done; } static int terminal_write (TTY * _t, void *buf, int len) { int writ, done = 0; TERMINAL *t = (TERMINAL *) _t; terminal_dispatch (); set_blocking (t->wfd); do { writ = wrap_write (t->wfd, buf, len); if (writ < 0) return -1; if (!writ) usleep (1000); buf += writ; len -= writ; done += writ; } while (len); return done; } void terminal_register_handlers (void) { struct sigaction sa = { 0 }; sa.sa_handler = sigwinch; sa.sa_flags = SA_RESTART; sigaction (SIGWINCH, &sa, NULL); sa.sa_handler = sigint; sa.sa_flags = SA_RESTART; sigaction (SIGINT, &sa, NULL); } TTY * terminal_open (int rfd, int wfd) { TERMINAL *t; pid_t child; struct termios termios; t = (TERMINAL *) xmalloc (sizeof (TERMINAL)); strcpy (t->name, "terminal"); t->rfd = rfd; t->wfd = wfd; tcgetattr (wfd, &t->orig_termios); t->next = terminal_list; terminal_list = t; tcgetattr (wfd, &termios); set_nonblocking (rfd); set_nonblocking (wfd); cfmakeraw (&termios); // raw_termios (&termios); tcsetattr (wfd, TCSANOW, &termios); t->recv = terminal_read; t->xmit = terminal_write; t->close = terminal_close; t->blocked = 0; terminal_getsize ((TTY *) t); return (TTY *) t; } work/src/tty.c0000664000000000000000000002234013337271225010511 0ustar /* * tty.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: tty.c,v 1.27 2010/07/27 14:49:35 james Exp $"; /* * $Log: tty.c,v $ * Revision 1.27 2010/07/27 14:49:35 james * add support for byte logging * * Revision 1.26 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.25 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.24 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.23 2008/03/06 16:49:39 james * *** empty log message *** * * Revision 1.22 2008/03/06 16:49:05 james * *** empty log message *** * * Revision 1.21 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.20 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.19 2008/02/28 16:57:52 james * *** empty log message *** * * Revision 1.18 2008/02/28 16:37:16 james * *** empty log message *** * * Revision 1.17 2008/02/28 15:37:06 james * *** empty log message *** * * Revision 1.16 2008/02/28 12:12:25 james * *** empty log message *** * * Revision 1.15 2008/02/28 00:10:44 james * *** empty log message *** * * Revision 1.14 2008/02/23 13:05:58 staffcvs * *** empty log message *** * * Revision 1.13 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.12 2008/02/22 23:39:27 james * *** empty log message *** * * Revision 1.11 2008/02/20 18:31:53 james * *** empty log message *** * * Revision 1.10 2008/02/15 23:52:12 james * *** empty log message *** * * Revision 1.9 2008/02/15 03:32:07 james * *** empty log message *** * * Revision 1.8 2008/02/14 10:36:18 james * *** empty log message *** * * Revision 1.7 2008/02/14 10:34:30 james * *** empty log message *** * * Revision 1.6 2008/02/13 16:59:34 james * *** empty log message *** * * Revision 1.5 2008/02/13 16:57:29 james * *** empty log message *** * * Revision 1.4 2008/02/12 22:36:46 james * *** empty log message *** * * Revision 1.3 2008/02/09 15:47:28 james * *** empty log message *** * */ #include "project.h" static int speed_t_to_baud (speed_t s) { switch (s) { #ifdef B0 case B0: return 0; #endif #ifdef B50 case B50: return 50; #endif #ifdef B75 case B75: return 75; #endif #ifdef B110 case B110: return 110; #endif #ifdef B134 case B134: return 134; #endif #ifdef B150 case B150: return 150; #endif #ifdef B200 case B200: return 200; #endif #ifdef B300 case B300: return 300; #endif #ifdef B600 case B600: return 600; #endif #ifdef B1200 case B1200: return 1200; #endif #ifdef B1800 case B1800: return 1800; #endif #ifdef B2400 case B2400: return 2400; #endif #ifdef B4800 case B4800: return 4800; #endif #ifdef B9600 case B9600: return 9600; #endif #ifdef B19200 case B19200: return 19200; #endif #ifdef B38400 case B38400: return 38400; #endif #ifdef B57600 case B57600: return 57600; #endif #ifdef B115200 case B115200: return 115200; #endif #ifdef B230400 case B230400: return 230400; #endif } return -1; } static speed_t baud_to_speed_t (int baud) { switch (baud) { #ifdef B0 case 0: return B0; #endif #ifdef B50 case 50: return B50; #endif #ifdef B75 case 75: return B75; #endif #ifdef B110 case 110: return B110; #endif #ifdef B134 case 134: return B134; #endif #ifdef B150 case 150: return B150; #endif #ifdef B200 case 200: return B200; #endif #ifdef B300 case 300: return B300; #endif #ifdef B600 case 600: return B600; #endif #ifdef B1200 case 1200: return B1200; #endif #ifdef B1800 case 1800: return B1800; #endif #ifdef B2400 case 2400: return B2400; #endif #ifdef B4800 case 4800: return B4800; #endif #ifdef B9600 case 9600: return B9600; #endif #ifdef B19200 case 19200: return B19200; #endif #ifdef B38400 case 38400: return B38400; #endif #ifdef B57600 case 57600: return B57600; #endif #ifdef B115200 case 115200: return B115200; #endif #ifdef B230400 case 230400: return B230400; #endif } return -1; } void tty_pre_select (TTY * t, fd_set * rfds, fd_set * wfds) { int line; struct timeval now, dif; if (t->hanging_up) { gettimeofday (&now, NULL); timersub (&now, &t->hangup_clock, &dif); if (dif.tv_sec) { line = TIOCM_DTR; ioctl (t->rfd, TIOCMBIS, &line); t->hanging_up = 0; } } FD_SET (t->rfd, rfds); } int tty_get_status (TTY * t, TTY_Status * s) { s->lines = 0; ioctl (t->rfd, TIOCMGET, &s->lines); if (tcgetattr (t->rfd, &s->termios)) return -1; s->baud = speed_t_to_baud (cfgetispeed (&s->termios)); s->blocked = t->blocked; return 0; } int tty_get_baud (TTY * t) { struct termios tios = { 0 }; if (tcgetattr (t->rfd, &tios)) return -1; return speed_t_to_baud (cfgetispeed (&tios)); } void tty_set_baud (TTY * t, int rate) { struct termios tios = { 0 }; speed_t s = baud_to_speed_t (rate); if (s == (speed_t) - 1) return; if (tcgetattr (t->rfd, &tios)) return; cfsetispeed (&tios, s); cfsetospeed (&tios, s); tcsetattr (t->rfd, TCSANOW, &tios); } void tty_send_break (TTY * t) { tcsendbreak (t->wfd, 0); } void tty_set_flow (TTY * t, int flow) { struct termios tios = { 0 }; if (tcgetattr (t->rfd, &tios)) return; if (flow) tios.c_cflag |= CRTSCTS; else tios.c_cflag &= ~CRTSCTS; tcsetattr (t->rfd, TCSANOW, &tios); } void tty_hangup (TTY * t) { int line; line = TIOCM_DTR; ioctl (t->rfd, TIOCMBIC, &line); t->hanging_up = 1; gettimeofday (&t->hangup_clock, NULL); } void tty_length (TTY * t, int l) { t->displayed_length = l; } void tty_winch (TTY * t, CRT_Pos size) { struct winsize sz = { 0 }; sz.ws_col = size.x; sz.ws_row = size.y; ioctl (t->wfd, TIOCSWINSZ, &sz); } #if 0 typedef struct { int in_dle; int in_errmark; int bit_edge_frequency[8]; int errs; } #endif #define DLE 0377 #define bit(p,b,z,o) \ do { \ if ((b && z)) { \ p->bitfreq[z]++; \ z = 0; \ } \ \ if ((!b && o)) \ { \ p->bitfreq[z]++; \ o = 0; \ } \ \ if (b) \ o++; \ else \ z++; \ } \ while (0) static void tty_bit_analyse (Context * c, int err, int ch) { int d; int zc = 0, oc = 0; TTY_Parser *p = c->tp; bit (p, 0, zc, oc); for (d = 1; d < 0x100; d <<= 1) { bit (p, ch & d, zc, oc); } bit (p, 1, zc, oc); if (err) { p->biterrs++; gettimeofday (&p->lasterr, NULL); } if (p->biterrs) { log_f (c->l, "", ch & 0x01 ? 1 : 0, ch & 0x02 ? 1 : 0, ch & 0x04 ? 1 : 0, ch & 0x08 ? 1 : 0, ch & 0x10 ? 1 : 0, ch & 0x20 ? 1 : 0, ch & 0x40 ? 1 : 0, ch & 0x80 ? 1 : 0, p->bitfreq[0], p->bitfreq[1], p->bitfreq[2], p->bitfreq[3], p->bitfreq[4], p->bitfreq[5], p->bitfreq[6], p->bitfreq[7], p->bitfreq[8], p->bitfreq[9]); } } void tty_parse_reset (Context * c) { TTY_Parser *p = c->tp; memset (p->bitfreq, 0, sizeof (p->bitfreq)); p->biterrs = 0; p->guessed_baud = 0; } void tty_analyse (Context * c) { TTY_Parser *p = c->tp; struct timeval now, dif; int i, j, max; if (!p->biterrs) { p->guessed_baud = 0; return; } gettimeofday (&now, NULL); timersub (&now, &p->lasterr, &dif); if (dif.tv_sec > 10) { tty_parse_reset (c); return; } max = -1; j = 0; for (i = 0; i < TTY_BITFREQ_LEN; ++i) { if (p->bitfreq[i] > max) { max = p->bitfreq[i]; j = i; } } if (c->t) i = tty_get_baud (c->t); else i = -1; if (j == 1) { /* Closest bit edge is one bit, so the baud rate is too low */ p->guessed_baud = -1; } else { if (i > 0 && j > 0) p->guessed_baud = i / j; else p->guessed_baud = 0; } if (p->guessed_baud == -1) { log_f (c->l, "", p->biterrs, i); } else { log_f (c->l, "", p->biterrs, i, p->guessed_baud); } } TTY_Parser * tty_parser_new (void) { TTY_Parser *p; p = (TTY_Parser *) xmalloc (sizeof (TTY_Parser)); memset (p, 0, sizeof (TTY_Parser)); return p; } int tty_parse (Context * c, uint8_t * buf, int len) { TTY_Parser *p; int err = 0; p = c->tp; while (len--) { if (p->in_dle) { p->in_dle = 0; switch (*buf) { case DLE: tty_bit_analyse (c, 0, *buf); err += utf8_parse (c, *buf); break; case 0: p->in_errmark = 1; break; default: log_f (c->l, "%s:%d DLE parsing error: \\377 \\%03o", __FILE__, __LINE__, *buf); } } else if (p->in_errmark) { p->in_errmark = 0; log_f (c->l, "", __FILE__, __LINE__, *buf); tty_bit_analyse (c, 1, *buf); tty_analyse (c); err += utf8_parse (c, *buf); err += utf8_parse (c, SYM_CHAR_RESET); } else if (*buf == DLE) { p->in_dle = 1; } else { tty_bit_analyse (c, 0, *buf); tty_analyse (c); err += utf8_parse (c, *buf); } buf++; } return err; } work/src/tty.h0000664000000000000000000000421413337271225010516 0ustar /* * tty.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: tty.h,v 1.16 2008/03/10 11:49:33 james Exp $ */ /* * $Log: tty.h,v $ * Revision 1.16 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.15 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.14 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.13 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.12 2008/02/28 16:57:52 james * *** empty log message *** * * Revision 1.11 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.10 2008/02/22 23:39:27 james * *** empty log message *** * * Revision 1.9 2008/02/22 19:12:05 james * *** empty log message *** * * Revision 1.8 2008/02/15 23:52:12 james * *** empty log message *** * * Revision 1.7 2008/02/14 10:36:18 james * *** empty log message *** * * Revision 1.6 2008/02/14 10:34:30 james * *** empty log message *** * * Revision 1.5 2008/02/13 09:12:21 james * *** empty log message *** * * Revision 1.4 2008/02/13 01:08:18 james * *** empty log message *** * * Revision 1.3 2008/02/09 15:47:28 james * *** empty log message *** * * Revision 1.2 2008/02/07 00:43:27 james * *** empty log message *** * * Revision 1.1 2008/02/06 20:26:58 james * *** empty log message *** * */ #ifndef __TTY_H__ #define __TTY_H__ #define SYM_CHAR_RESET (-1) #define TTY_SIGNATURE \ char name[1024]; \ int blocked; \ CRT_Pos size; \ void (*close)(struct TTY_struct *); \ int (*recv)(struct TTY_struct *,void *buf,int len); \ int (*xmit)(struct TTY_struct *,void *buf,int len); \ int rfd; \ int wfd; \ int hanging_up; \ struct timeval hangup_clock; \ int displayed_length; #define TTY_BITFREQ_LEN 10 typedef struct { int in_dle; int in_errmark; int bitfreq[TTY_BITFREQ_LEN]; int biterrs; struct timeval lasterr; int guessed_baud; } TTY_Parser; typedef struct TTY_struct { TTY_SIGNATURE; } TTY; typedef struct { int lines; int blocked; struct termios termios; int baud; } TTY_Status; #endif /* __TTY_H__ */ work/src/utf8.c0000664000000000000000000001114013337271225010553 0ustar /* * utf8.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: utf8.c,v 1.16 2010/07/27 14:49:35 james Exp $"; /* * $Log: utf8.c,v $ * Revision 1.16 2010/07/27 14:49:35 james * add support for byte logging * * Revision 1.15 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.14 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.13 2008/03/06 16:49:39 james * *** empty log message *** * * Revision 1.12 2008/03/06 16:49:05 james * *** empty log message *** * * Revision 1.11 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.10 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.9 2008/02/27 01:31:14 james * *** empty log message *** * * Revision 1.8 2008/02/27 00:54:16 james * *** empty log message *** * * Revision 1.7 2008/02/26 23:56:12 james * *** empty log message *** * * Revision 1.6 2008/02/26 23:23:17 james * *** empty log message *** * * Revision 1.5 2008/02/24 00:42:53 james * *** empty log message *** * * Revision 1.4 2008/02/23 13:05:58 staffcvs * *** empty log message *** * * Revision 1.3 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.2 2008/02/22 23:39:27 james * *** empty log message *** * * Revision 1.1 2008/02/22 19:12:05 james * *** empty log message *** * */ #include "project.h" int utf8_flush (Context * c) { UTF8 *u = c->u; int i; int err = 0; switch (u->utf_ptr) { case 1: log_f (c->l, "", u->utf_buf[0]); break; case 2: log_f (c->l, "", u->utf_buf[0], u->utf_buf[1]); break; case 3: log_f (c->l, "", u->utf_buf[0], u->utf_buf[1], u->utf_buf[2]); break; case 4: log_f (c->l, "", u->utf_buf[0], u->utf_buf[1], u->utf_buf[2], u->utf_buf[3]); break; } for (i = 0; i < u->utf_ptr; ++i) err += vt102_parse_char (c, u->utf_buf[i]); u->utf_ptr = 0; u->in_utf8 = 0; return err; } int utf8_parse (Context * c, uint32_t ch) { UTF8 *u = c->u; int err = 0; if (ch == SYM_CHAR_RESET) { u->in_utf8 = 0; err += vt102_parse_char (c, ch); return err; } if (c->l && c->byte_logging) { uint8_t ch8=(uint8_t) ch; c->l->log_bytes(c->l,&ch8,1); } if (!u->in_utf8) { /* FIXME: for the moment we bodge utf8 support - need to do */ /* L->R and R->L and double width characters */ if (ch == 0xb9) // FIXME - OTHER 8 bit control chars { /* CSI, not a valid utf8 start char */ err += vt102_parse_char (c, ch); } else if ((ch & 0xe0) == 0xc0) { /* Start of two byte unicode sequence */ u->in_utf8 = 1; u->utf_ptr = 0; u->utf_buf[u->utf_ptr++] = ch; u->ch = (ch & 0x1f) << 6; u->sh = 0; } else if ((ch & 0xf0) == 0xe0) { /* Start of three byte unicode sequence */ u->in_utf8 = 2; u->utf_ptr = 0; u->utf_buf[u->utf_ptr++] = ch; u->ch = (ch & 0x0f) << 12; u->sh = 6; } else if ((ch & 0xf8) == 0xf0) { u->in_utf8 = 3; u->utf_ptr = 0; u->utf_buf[u->utf_ptr++] = ch; u->ch = (ch & 0x07) << 18; u->sh = 12; } else { err += vt102_parse_char (c, ch); } } else { if ((ch & 0xc0) != 0x80) { err += utf8_flush (c); err += vt102_parse_char (c, ch); } else { u->utf_buf[u->utf_ptr++] = ch; u->ch |= (ch & 0x3f) << u->sh; u->sh -= 6; u->in_utf8--; if (!u->in_utf8) err += vt102_parse_char (c, u->ch); } } return err; } UTF8 * utf8_new (void) { UTF8 *ret; ret = (UTF8 *) xmalloc (sizeof (UTF8)); ret->in_utf8 = 0; } int utf8_encode (char *ptr, int ch) { if (ch < 0x80) { ptr[0] = ch; return 1; } else if (ch < 0x800) { ptr[0] = 0xc0 | (ch >> 6); ptr[1] = 0x80 | (ch & 0x3f); return 2; } else if (ch < 0x10000) { ptr[0] = 0xe0 | (ch >> 12); ptr[1] = 0x80 | ((ch >> 6) & 0x3f); ptr[2] = 0x80 | (ch & 0x3f); return 3; } else if (ch < 0x1fffff) { ptr[0] = 0xf0 | (ch >> 18); ptr[1] = 0x80 | ((ch >> 12) & 0x3f); ptr[2] = 0x80 | ((ch >> 6) & 0x3f); ptr[3] = 0x80 | (ch & 0x3f); return 4; } return 0; } int utf8_emit (TTY * t, int ch) { uint8_t buf[4]; int i; i = utf8_encode (buf, ch); if (!i) return 0; if (t->xmit (t, buf, i) != i) return -1; return 0; } work/src/utf8.h0000664000000000000000000000173013337271225010564 0ustar /* * utf8.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: utf8.h,v 1.8 2008/03/10 11:49:33 james Exp $ */ /* * $Log: utf8.h,v $ * Revision 1.8 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.7 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.6 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.5 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.4 2008/02/24 00:42:53 james * *** empty log message *** * * Revision 1.3 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.2 2008/02/22 23:39:27 james * *** empty log message *** * * Revision 1.1 2008/02/22 19:12:05 james * *** empty log message *** * * */ #ifndef __UTF8_H__ #define __UTF8_H__ typedef struct { int in_utf8; uint8_t utf_buf[4]; int utf_ptr; uint32_t ch; int sh; } UTF8; #endif /* __UTF8_H__ */ work/src/util.c0000664000000000000000000000744213337271225010654 0ustar /* * util.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: util.c,v 1.11 2008/03/07 14:13:40 james Exp $"; /* * $Log: util.c,v $ * Revision 1.11 2008/03/07 14:13:40 james * *** empty log message *** * * Revision 1.10 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.9 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.8 2008/03/02 10:50:32 staffcvs * *** empty log message *** * * Revision 1.7 2008/02/27 01:31:14 james * *** empty log message *** * * Revision 1.6 2008/02/27 00:54:16 james * *** empty log message *** * * Revision 1.5 2008/02/24 00:42:53 james * *** empty log message *** * * Revision 1.4 2008/02/23 13:05:58 staffcvs * *** empty log message *** * * Revision 1.3 2008/02/13 16:57:29 james * *** empty log message *** * * Revision 1.2 2008/02/13 09:12:21 james * *** empty log message *** * * Revision 1.1 2008/02/13 01:08:38 james * *** empty log message *** * */ #include "project.h" int wrap_read (int fd, void *buf, int len) { int red; red = read (fd, buf, len); #if 0 if (!red) return -1; #endif if ((red < 0) && (errno == EAGAIN)) red = 0; return red; } int wrap_write (int fd, void *buf, int len) { int writ; errno = 0; writ = write (fd, buf, len); if (!writ) return -1; if ((writ < 0) && (errno == EAGAIN)) writ = 0; return writ; } void set_nonblocking (int fd) { long arg; arg = fcntl (fd, F_GETFL, arg); arg |= O_NONBLOCK; fcntl (fd, F_SETFL, arg); } void set_blocking (int fd) { long arg; arg = fcntl (fd, F_GETFL, arg); arg &= ~O_NONBLOCK; fcntl (fd, F_SETFL, arg); } void default_termios (struct termios *termios) { termios->c_iflag = PARMRK | INPCK; termios->c_oflag = NL0 | CR0 | TAB0 | BS0 | VT0 | FF0; termios->c_lflag = 0; termios->c_cflag = CS8 | CREAD | CLOCAL; termios->c_cc[VINTR] = 003; termios->c_cc[VQUIT] = 034; termios->c_cc[VERASE] = 0177; termios->c_cc[VKILL] = 025; termios->c_cc[VEOF] = 004; termios->c_cc[VEOL] = 0; termios->c_cc[VEOL2] = 0; termios->c_cc[VSTART] = 021; termios->c_cc[VSTOP] = 023; termios->c_cc[VSUSP] = 032; termios->c_cc[VLNEXT] = 026; termios->c_cc[VWERASE] = 027; termios->c_cc[VREPRINT] = 022; termios->c_cc[VDISCARD] = 017; } void client_termios (struct termios *termios) { memset (termios, 0, sizeof (termios)); termios->c_iflag = ICRNL | IXON | PARMRK | INPCK; termios->c_oflag = OPOST | ONLCR | NL0 | CR0 | TAB0 | BS0 | VT0 | FF0; termios->c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE; termios->c_cflag = CS8 | CREAD | CLOCAL; termios->c_cc[VINTR] = 003; termios->c_cc[VQUIT] = 034; termios->c_cc[VERASE] = 0177; termios->c_cc[VKILL] = 025; termios->c_cc[VEOF] = 004; termios->c_cc[VEOL] = 0; termios->c_cc[VEOL2] = 0; termios->c_cc[VSTART] = 021; termios->c_cc[VSTOP] = 023; termios->c_cc[VSUSP] = 032; termios->c_cc[VLNEXT] = 026; termios->c_cc[VWERASE] = 027; termios->c_cc[VREPRINT] = 022; termios->c_cc[VDISCARD] = 017; cfsetispeed (termios, B9600); cfsetospeed (termios, B9600); } int fput_cp (FILE * f, uint32_t ch) { char buf[4]; int i; i = utf8_encode (buf, ch); if (!i) return 0; return fwrite (buf, i, 1, f); } void crash_out (char *why) { terminal_atexit (); fprintf (stderr, "sympathy is aborting: %s\n", why ? why : ""); exit (1); } void * xmalloc (size_t s) { void *ret = malloc (s); if (!ret) crash_out ("malloc failed"); return ret; } void * xrealloc (void *p, size_t s) { p = realloc (p, s); if (!p) crash_out ("realloc failed"); return p; } char * xstrdup (const char *s) { char *ret = strdup (s); if (!ret) crash_out ("strdup failed"); return ret; } work/src/version-num0000664000000000000000000000001013337271225011720 0ustar 1.2.1-E work/src/version.c0000664000000000000000000000114413337271225011355 0ustar /* * version.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: version.c,v 1.4 2008/03/07 12:37:04 james Exp $"; /* * $Log: version.c,v $ * Revision 1.4 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.3 2008/02/27 09:42:22 james * *** empty log message *** * * Revision 1.2 2008/02/04 02:05:06 james * *** empty log message *** * * Revision 1.1 2008/02/03 16:20:24 james * *** empty log message *** * * */ #include "version.h" char * libsympathy_version (void) { return VERSION; } work/src/version.h0000664000000000000000000000006413337271225011362 0ustar #define VERSION "libsympathy Version 1.2.1 + Edits" work/src/vt102.c0000664000000000000000000013607313337271225010556 0ustar /* * vt102.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: vt102.c,v 1.67 2010/07/27 14:49:35 james Exp $"; /* * $Log: vt102.c,v $ * Revision 1.67 2010/07/27 14:49:35 james * add support for byte logging * * Revision 1.66 2008/03/07 13:16:02 james * *** empty log message *** * * Revision 1.65 2008/03/07 12:42:08 james * *** empty log message *** * * Revision 1.64 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.63 2008/03/07 12:00:58 james * *** empty log message *** * * Revision 1.62 2008/03/06 21:34:09 james * *** empty log message *** * * Revision 1.61 2008/03/06 17:21:41 james * *** empty log message *** * * Revision 1.60 2008/03/06 16:49:39 james * *** empty log message *** * * Revision 1.59 2008/03/06 16:49:05 james * *** empty log message *** * * Revision 1.58 2008/03/06 01:41:48 james * *** empty log message *** * * Revision 1.57 2008/03/03 06:20:14 james * *** empty log message *** * * Revision 1.56 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.55 2008/03/02 12:32:57 staffcvs * *** empty log message *** * * Revision 1.54 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.53 2008/02/29 18:33:39 james * *** empty log message *** * * Revision 1.52 2008/02/28 16:57:52 james * *** empty log message *** * * Revision 1.51 2008/02/28 16:37:16 james * *** empty log message *** * * Revision 1.50 2008/02/28 12:12:25 james * *** empty log message *** * * Revision 1.49 2008/02/28 11:27:48 james * *** empty log message *** * * Revision 1.48 2008/02/27 09:42:53 james * *** empty log message *** * * Revision 1.47 2008/02/27 09:42:22 james * *** empty log message *** * * Revision 1.46 2008/02/27 01:31:38 james * *** empty log message *** * * Revision 1.45 2008/02/27 01:31:14 james * *** empty log message *** * * Revision 1.44 2008/02/27 00:54:16 james * *** empty log message *** * * Revision 1.43 2008/02/27 00:27:22 james * *** empty log message *** * * Revision 1.42 2008/02/26 23:56:12 james * *** empty log message *** * * Revision 1.41 2008/02/26 23:23:17 james * *** empty log message *** * * Revision 1.40 2008/02/26 19:00:59 james * *** empty log message *** * * Revision 1.39 2008/02/26 16:54:06 james * *** empty log message *** * * Revision 1.38 2008/02/26 16:53:24 james * *** empty log message *** * * Revision 1.37 2008/02/24 12:22:53 james * *** empty log message *** * * Revision 1.36 2008/02/24 12:22:42 james * *** empty log message *** * * Revision 1.35 2008/02/24 00:42:53 james * *** empty log message *** * * Revision 1.34 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.33 2008/02/22 23:39:27 james * *** empty log message *** * * Revision 1.32 2008/02/22 19:12:05 james * *** empty log message *** * * Revision 1.31 2008/02/22 17:07:00 james * *** empty log message *** * * Revision 1.30 2008/02/22 14:51:54 james * *** empty log message *** * * Revision 1.29 2008/02/15 03:32:07 james * *** empty log message *** * * Revision 1.28 2008/02/14 10:34:30 james * *** empty log message *** * * Revision 1.27 2008/02/14 02:46:45 james * *** empty log message *** * * Revision 1.26 2008/02/14 01:55:57 james * *** empty log message *** * * Revision 1.25 2008/02/13 16:57:29 james * *** empty log message *** * * Revision 1.24 2008/02/13 09:12:21 james * *** empty log message *** * * Revision 1.23 2008/02/07 13:26:35 james * *** empty log message *** * * Revision 1.22 2008/02/07 13:22:51 james * *** empty log message *** * * Revision 1.21 2008/02/07 12:21:16 james * *** empty log message *** * * Revision 1.20 2008/02/07 12:16:04 james * *** empty log message *** * * Revision 1.19 2008/02/07 11:27:02 james * *** empty log message *** * * Revision 1.18 2008/02/07 01:59:25 james * *** empty log message *** * * Revision 1.17 2008/02/07 01:58:28 james * *** empty log message *** * * Revision 1.16 2008/02/07 01:57:46 james * *** empty log message *** * * Revision 1.15 2008/02/07 00:43:27 james * *** empty log message *** * * Revision 1.14 2008/02/07 00:40:23 james * *** empty log message *** * * Revision 1.13 2008/02/07 00:39:59 james * *** empty log message *** * * Revision 1.12 2008/02/07 00:39:13 james * *** empty log message *** * * Revision 1.11 2008/02/06 20:26:58 james * *** empty log message *** * * Revision 1.10 2008/02/06 17:53:28 james * *** empty log message *** * * Revision 1.9 2008/02/06 15:53:22 james * *** empty log message *** * * Revision 1.8 2008/02/06 11:49:47 james * *** empty log message *** * * Revision 1.7 2008/02/06 11:30:37 james * *** empty log message *** * * Revision 1.6 2008/02/05 01:11:46 james * *** empty log message *** * * Revision 1.5 2008/02/04 20:23:55 james * *** empty log message *** * * Revision 1.4 2008/02/04 05:45:55 james * :: * * Revision 1.3 2008/02/04 02:05:06 james * *** empty log message *** * * Revision 1.2 2008/02/04 01:32:39 james * *** empty log message *** * * Revision 1.1 2008/02/03 23:36:41 james * *** empty log message *** * */ /* * Termcap he say: * * VT102: * * vt102|dec vt102:\ :mi:\ * :al=\E[L:dc=\E[P:dl=\E[M:ei=\E[4l:im=\E[4h:tc=vt100: * * vt100|vt100-am|dec vt100 (w/advanced video):\ :am:bs:ms:xn:xo:\ * :co#80:it#8:li#24:vt#3:\ * :DO=\E[%dB:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:\ :UP=\E[%dA:\ * :ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\ * :ae=^O:as=^N:bl=^G:cb=\E[1K:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\ * :cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:do=^J:\ * :eA=\E(B\E)0:ho=\E[H:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:\ * :kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:\ * :me=\E[m\017:mr=\E[7m:nd=\E[C:rc=\E8:\ * :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:sc=\E7:se=\E[m:\ * :sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:ue=\E[m:up=\E[A:\ * :us=\E[4m:tc=vt100+fnkeys: * * vt100+fnkeys|dec vt100 numeric keypad:\ * :k0=\EOy:k5=\EOt:k6=\EOu:k7=\EOv:k8=\EOl:k9=\EOw:k;=\EOx:\ * :tc=vt100+pfkeys: * * vt100+pfkeys|dec vt100 numeric keypad:\ * :@8=\EOM:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:tc=vt100+keypad: * * vt100+keypad|dec vt100 numeric keypad no fkeys:\ * :K1=\EOq:K2=\EOr:K3=\EOs:K4=\EOp:K5=\EOn: * */ /* * so the parser needs to be able to at least do CTRL-G CTRL-H CTRL-I * CTRL-J CTRL-M CTRL-N * * CTRL-O ESC7 ESC8 ESCH ESCM ESC> * * ESC[%dA ESC[%dB ESC[%dC ESC[%dD ESC[H ESC[%d;%dH ESC[J ESC[K ESC[1K * ESC[L ESC[M ESC[P * * ESC[3g ESC[4h ESC[4l ESC[m ESC[1m ESC[4m ESC[5m ESC[7m ESC[%d;%dr * * * ESC[?3l ESC[?4l ESC[?5l ESC[?7h ESC[?7h ESC[?7l ESC[?8h * * ESC(B ESC)0 * * * TODO: * * ESC(B ESC)0 * * CTRL-O * * ANSI: * * * * ansi|ansi/pc-term compatible with color:\ * :u6=\E[%i%d;%dR:u7=\E[6n:u9=\E[c:tc=ecma+color:\ * :tc=klone+sgr:tc=ansi-m: ansi-m|ansi-mono|ANSI X3.64-1979 terminal with * ANSI.SYS compatible attributes:\ :5i:\ * :AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\ * :LE=\E[%dD:RI=\E[%dC:SF=\E[%dS:SR=\E[%dT:UP=\E[%dA:\ * :cb=\E[1K:ch=\E[%i%dG:ct=\E[2g:cv=\E[%i%dd:ec=\E[%dX:ei=:\ * :im=:kB=\E[Z:kI=\E[L:kb=^H:kd=\E[B:kl=\E[D:kr=\E[C:ku=\E[A:\ * :nw=\r\E[S:pf=\E[4i:po=\E[5i:s0=\E(B:s1=\E)B:s2=\E*B:\ * :s3=\E+B:ta=\E[I:tc=pcansi-m: pcansi-m|pcansi-mono|ibm-pc terminal * programs claiming to be ansi (mono mode):\ :am:bs:mi:ms:\ * :co#80:it#8:li#24:\ * :al=\E[L:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\ * :cm=\E[%i%d;%dH:cr=^M:ct=\E[2g:dc=\E[P:dl=\E[M:do=\E[B:\ * :ho=\E[H:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\ * :le=\E[D:nd=\E[C:sf=^J:st=\EH:ta=^I:up=\E[A:\ :tc=klone+sgr-dumb: * klone+sgr-dumb|attribute control for ansi.sys displays (no ESC [ 11 * m):\ :as=\E[12m:mb=\E[5m:md=\E[1m:me=\E[0;10m:mk=\E[8m:\ * :mr=\E[7m:se=\E[m:so=\E[7m:ue=\E[m:us=\E[4m:tc=klone+acs: * klone+acs|alternate character set for ansi.sys displays:\ * :ac=+\020,\021-\030.^Y0\333`\004a\261f\370g\361h\260j\331k\277l\332m\300n\305o~p\304q\304r\304s_t\303u\264v\301w\302x\263y\363z\362{\343|\330}\234~\376:\ * :ae=\E[10m:as=\E[11m: ecma+color|color control for ECMA-48-compatible terminals:\ :Co#8:NC#3:pa#64:\ :AB=\E[4%dm:AF=\E[3%dm:op=\E[39;49m: * * * Ignoreing ones in the VT102 spec * * ESC[%d@ ESC[I ESC[....R ESC[%dS ESC[%dT ESC[X ESC[Z * * ESC[c *ESC[%db ESC[....d ESC[....f ESC[2g ESC[4i ESC[5i ESC[6n * * ESC(B ESC)B ESC*B ESC+B * * */ #include "project.h" #include "syslog.h" #define TABLE_LENGTH 128 #undef DEBUG static char terminal_id[] = "vt102"; /* * number of aditional chars after \033 ... to complete the escape if it's * fixed length */ int vt102_cmd_length[TABLE_LENGTH] = { ['('] = 1, [')'] = 1, ['+'] = 1, ['*'] = 1, ['%'] = 1, ['#'] = 1, ['Y'] = 2, }; /* * method for determining end if if's not fixed length, -ve numbers from * #defines, +ve are literals */ #define CSI_ENDER -1 int vt102_cmd_termination[TABLE_LENGTH] = { [']'] = 7, ['['] = CSI_ENDER, }; static inline int safe_ch (int c) { if (c < 32) return ' '; if (c > 126) return ' '; return c; } static inline int csi_ender (int c) { if ((c >= 'a') && (c <= 'z')) return 1; if ((c >= 'A') && (c <= 'Z')) return 1; if ((c == '@')) return 1; return 0; } static inline int ctrl_chr (int ch, int term) { if ((term > 0) && (ch == term)) return 0; if (ch == 033) return 0; if ((ch > 0) && (ch < 040)) return 1; return 0; } static inline int in_margins (VT102 * v, CRT_Pos p) { if (v->pos.x < v->top_margin.x) return 0; if (v->pos.y < v->top_margin.y) return 0; if (v->pos.x > v->bottom_margin.x) return 0; if (v->pos.y > v->bottom_margin.y) return 0; return 1; } void vt102_crt_update (Context * c) { VT102 *v = c->v; v->crt.pos = v->pos; v->crt.hide_cursor = v->private_modes[VT102_PRIVATE_MODE_SHOW_CURSOR] ? 0 : 1; if (v->current_line.y != v->pos.y) { vt102_log_line (c, v->current_line.y); v->current_line = v->pos; } if (c->d) cmd_show_status (c->d, c); } void vt102_do_resize (Context * c) { VT102 *v = c->v; v->crt.size = v->current_size; v->crt.size.y++; v->screen_end = v->current_size; v->screen_end.x--; v->screen_end.y--; v->top_margin = v->screen_start; v->bottom_margin = v->screen_end; vt102_cursor_home (v); crt_cls (&v->crt); if (c->t) tty_winch (c->t, v->current_size); log_f (c->l, "", v->current_size.x, v->current_size.y); vt102_crt_update (c); } void vt102_log_line (Context * c, int line) { CRT_Pos e = { c->v->current_size.x - 1, line }; CRT_Pos p = { 0, line }; char logbuf[4 * (VT102_MAX_COLS + 1)], *logptr = logbuf; if (!c->l || c->byte_logging) return; for (; e.x > 0; --e.x) { if (c->v->crt.screen[CRT_ADDR_POS (&e)].chr != ' ') break; } for (; p.x <= e.x; ++p.x) { int ch = c->v->crt.screen[CRT_ADDR_POS (&p)].chr; if (ch < 32) ch = ' '; logptr += utf8_encode (logptr, ch); } *logptr = 0; c->l->log (c->l, logbuf); } /* * Called for every upward scroll with same args */ void vt102_history (Context * c, CRT_Pos t, CRT_Pos b) { /* * Only log if it scrolls off the top */ if (t.y) return; t.x = 0; history_add (c->h, &(c->v->crt.screen[CRT_ADDR_POS (&t)])); } void vt102_clip_cursor (VT102 * v, CRT_Pos tl, CRT_Pos br) { if (v->pos.x < tl.x) v->pos.x = tl.x; if (v->pos.y < tl.y) v->pos.y = tl.y; if (v->pos.x > br.x) v->pos.x = br.x; if (v->pos.y > br.y) v->pos.y = br.y; } void vt102_cursor_normalize (VT102 * v) { CRT_Pos *top, *bottom; if (v->private_modes[VT102_PRIVATE_MODE_ORIGIN_MODE]) { vt102_clip_cursor (v, v->top_margin, v->bottom_margin); } else { vt102_clip_cursor (v, v->screen_start, v->screen_end); } } void vt102_cursor_carriage_return (VT102 * v) { v->pos.x = v->top_margin.x; v->pending_wrap = 0; } void vt102_cursor_advance_line (Context * c) { VT102 *v = c->v; int couldscroll = in_margins (v, v->pos); /* have wraped off end of last line in scrolling region */ /* not necessary, but shuts compiler up */ if (((v->pos.y == v->bottom_margin.y) || (v->pos.y == v->screen_end.y)) && (couldscroll)) { vt102_log_line (c, v->pos.y); vt102_history (c, v->top_margin, v->bottom_margin); crt_scroll_up (&v->crt, v->top_margin, v->bottom_margin, 1, v->color); return; } if (v->pos.y != v->screen_end.y) v->pos.y++; v->pending_wrap = 0; } void vt102_cursor_retreat_line (Context * c) { VT102 *v = c->v; int couldscroll = in_margins (v, v->pos); /* have wraped off end of first line in scrolling region */ /* (|| not necessary, but shuts compiler up */ if (((v->pos.y == v->top_margin.y) || (v->pos.y == v->screen_start.y)) && (couldscroll)) { vt102_log_line (c, v->pos.y); crt_scroll_down (&v->crt, v->top_margin, v->bottom_margin, 1, v->color); return; } if (v->pos.y != v->screen_start.y) v->pos.y--; v->pending_wrap = 0; } void vt102_do_pending_wrap (Context * c) { VT102 *v = c->v; int couldscroll = in_margins (v, v->pos); int autowrap = v->private_modes[VT102_PRIVATE_MODE_AUTO_WRAP]; if (!v->pending_wrap) return; /* End of line but no autowrap, nothing to do */ if (!autowrap) return; /* End of screen and not allowed to scroll, nothing to do */ if ((v->pos.y == v->screen_end.y) && (!couldscroll)) return; if (couldscroll) { v->pos.x = v->top_margin.x; } else { v->pos.x = 0; } vt102_cursor_advance_line (c); } void vt102_cursor_advance (Context * c) { VT102 *v = c->v; if (v->pos.x < v->bottom_margin.x) { /* Normal advance */ v->pos.x++; v->pending_wrap = 0; return; } v->pending_wrap++; if (!c->v->xn_glitch) vt102_do_pending_wrap (c); } void vt102_cursor_retreat (VT102 * v) { if (v->pos.x != v->top_margin.x) { v->pos.x--; } v->pending_wrap = 0; } void vt102_reset_tabs (VT102 * v) { int i; memset (v->tabs, 0, sizeof (v->tabs)); for (i = 0; i < VT102_MAX_COLS; i += 8) { v->tabs[i]++; } } void vt102_cursor_advance_tab (VT102 * v) { if (v->pos.x == v->bottom_margin.x) return; while (v->pos.x < v->bottom_margin.x) { v->pos.x++; if (v->tabs[v->pos.x]) break; } v->pending_wrap = 0; } void vt102_cursor_retreat_tab (VT102 * v) { if (v->pos.x == v->top_margin.x) return; while (v->pos.x > v->top_margin.x) { v->pos.x--; if (v->tabs[v->pos.x]) break; } v->pending_wrap = 0; } void vt102_cursor_home (VT102 * v) { v->pos = v->top_margin; vt102_cursor_normalize (v); v->pending_wrap = 0; } void vt102_cursor_absolute (VT102 * v, int x, int y) { if (v->private_modes[VT102_PRIVATE_MODE_ORIGIN_MODE]) { v->pos.x = x + v->top_margin.x; v->pos.y = y + v->top_margin.y; } else { v->pos.x = x; v->pos.y = y; } vt102_cursor_normalize (v); v->pending_wrap = 0; } void vt102_cursor_relative (VT102 * v, int x, int y) { v->pos.x += x; v->pos.y += y; vt102_cursor_normalize (v); v->pending_wrap = 0; } void vt102_delete_from_line (VT102 * v, CRT_Pos p) { int n = v->bottom_margin.x - p.x; if (n < 0) return; if (n) { memmove (&v->crt.screen[CRT_ADDR_POS (&p)], &v->crt.screen[CRT_ADDR_POS (&p) + 1], sizeof (CRT_CA) * n); } v->crt.screen[CRT_ADDR (p.y, v->bottom_margin.x)].chr = ' '; /* But not attr due to vt102 bug */ } void vt102_insert_into_line (VT102 * v, CRT_Pos p) { int n = v->bottom_margin.x - p.x; if (n < 0) return; if (n) { memmove (&v->crt.screen[CRT_ADDR_POS (&p) + 1], &v->crt.screen[CRT_ADDR_POS (&p)], sizeof (CRT_CA) * n); } v->crt.screen[CRT_ADDR_POS (&p)].chr = ' '; v->crt.screen[CRT_ADDR_POS (&p)].attr = CRT_ATTR_NORMAL; v->crt.screen[CRT_ADDR_POS (&p)].color = CRT_COLOR_NORMAL; } void vt102_change_mode (Context * c, int private, char *ns, int set) { VT102 *v = c->v; int m; if (*ns) { m = atoi (ns); } else { m = 1; } if (m < 0) return; if (m >= VT102_NMODES) return; if (private) { v->private_modes[m] = set; switch (m) { case VT102_PRIVATE_MODE_CURSOR_MODE: if (v->application_keypad_mode) v->private_modes[m] = 0; break; case VT102_PRIVATE_MODE_ORIGIN_MODE: vt102_cursor_home (v); break; case VT102_PRIVATE_MODE_132COLS: v->current_size.x = v-> private_modes[VT102_PRIVATE_MODE_132COLS] ? VT102_COLS_132 : VT102_COLS_80; vt102_do_resize (c); break; } } else v->modes[m] = set; } void vt102_parse_mode_string (Context * c, char *buf, int len) { VT102 *v = c->v; int private = 0; char last = buf[len - 1]; char num[4]; int o; memset (num, 0, sizeof (num)); o = sizeof (num) - 1; len--; if (*buf == '?') { private++; buf++; len--; } if (len < 0) return; while (len--) { if (*buf == ';') { vt102_change_mode (c, private, &num[o], last == 'h'); memset (num, 0, sizeof (num)); o = sizeof (num) - 1; buf++; continue; } num[0] = num[1]; num[1] = num[2]; num[2] = *buf; if (o) o--; buf++; } vt102_change_mode (c, private, &num[o], last == 'h'); } void vt102_change_attr (VT102 * v, char *na) { int a; if (*na) { a = atoi (na); } else { a = 0; } switch (a) { case 0: v->attr = CRT_ATTR_NORMAL; v->color = CRT_COLOR_NORMAL; break; case 1: v->attr |= CRT_ATTR_BOLD; break; case 21: case 22: v->attr &= ~CRT_ATTR_BOLD; break; case 4: v->attr |= CRT_ATTR_UNDERLINE; break; case 24: v->attr &= ~CRT_ATTR_UNDERLINE; break; case 5: v->attr |= CRT_ATTR_BLINK; break; case 25: v->attr &= ~CRT_ATTR_BLINK; break; case 7: v->attr |= CRT_ATTR_REVERSE; break; case 27: v->attr &= ~CRT_ATTR_REVERSE; break; case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: v->color &= ~CRT_COLOR_FG_MASK; v->color |= ((a - 30) << CRT_COLOR_FG_SHIFT) & CRT_COLOR_FG_MASK; break; case 90: case 91: case 92: case 93: case 94: case 95: case 96: case 97: v->color &= ~CRT_COLOR_FG_MASK; v->color |= (((a - 90) | CRT_COLOR_INTENSITY) << CRT_COLOR_FG_SHIFT) & CRT_COLOR_FG_MASK; break; case 39: case 99: v->color &= ~CRT_COLOR_FG_MASK; v->color |= (CRT_FGCOLOR_NORMAL << CRT_COLOR_FG_SHIFT) & CRT_COLOR_FG_MASK; break; case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: v->color &= ~CRT_COLOR_BG_MASK; v->color |= ((a - 40) << CRT_COLOR_BG_SHIFT) & CRT_COLOR_BG_MASK; break; case 100: case 101: case 102: case 103: case 104: case 105: case 106: case 107: v->color &= ~CRT_COLOR_BG_MASK; v->color |= (((a - 100) | CRT_COLOR_INTENSITY) << CRT_COLOR_BG_SHIFT) & CRT_COLOR_BG_MASK; break; case 49: case 109: v->color &= ~CRT_COLOR_BG_MASK; v->color |= (CRT_BGCOLOR_NORMAL << CRT_COLOR_BG_SHIFT) & CRT_COLOR_BG_MASK; break; } } void vt102_parse_attr_string (VT102 * v, char *buf, int len) { int private = 0; char last = buf[len - 1]; char num[4]; int o; memset (num, 0, sizeof (num)); o = sizeof (num) - 1; len--; if (len < 0) return; while (len--) { if (*buf == ';') { vt102_change_attr (v, &num[o]); memset (num, 0, sizeof (num)); o = sizeof (num) - 1; buf++; continue; } num[0] = num[1]; num[1] = num[2]; num[2] = *buf; if (o) o--; buf++; } vt102_change_attr (v, &num[o]); } void vt102_save_state (VT102 * v) { v->saved.pos = v->pos; v->saved.attr = v->attr; v->saved.color = v->color; v->saved.origin_mode = v->private_modes[VT102_PRIVATE_MODE_ORIGIN_MODE]; } void vt102_restore_state (VT102 * v) { v->pos = v->saved.pos; v->attr = v->saved.attr; v->color = v->saved.color; v->private_modes[VT102_PRIVATE_MODE_ORIGIN_MODE] = v->saved.origin_mode; vt102_cursor_normalize (v); v->pending_wrap = 0; } void vt102_regular_char (Context * c, VT102 * v, uint32_t ch) { vt102_do_pending_wrap (c); if (v->modes[VT102_MODE_INSERT]) vt102_insert_into_line (v, v->pos); v->last_reg_char = ch; if (ch < VT102_CHARSET_SIZE) { int cs; if ((cs = vt102_charset_c0[ch])) { ch = cs; } else if ((cs = charset_from_csid[v->g[v->cs]][ch])) { ch = cs; } } v->crt.screen[CRT_ADDR_POS (&v->pos)].chr = ch; v->crt.screen[CRT_ADDR_POS (&v->pos)].attr = v->attr; v->crt.screen[CRT_ADDR_POS (&v->pos)].color = v->color; vt102_cursor_advance (c); } void vt102_send_id (Context * c, char *buf) { if (c->t) { int l = strlen (buf); c->t->xmit (c->t, buf, l); } } void vt102_scs (Context * c, int g, int s) { VT102 *v = c->v; int cs = VT102_CSID_US; switch (s) { case 'A': cs = VT102_CSID_UK; break; case '1': case '2': case 'B': cs = VT102_CSID_US; break; case '0': cs = VT102_CSID_GL; break; } switch (g) { case '(': v->g[0] = cs; break; case ')': v->g[1] = cs; break; } } static int vt102_parse_csi (Context * c, char *buf, int len) { char last; char *ptr; char *arg = buf + 1; int narg; int err = 0; VT102 *v = c->v; buf[len] = 0; last = buf[len - 1]; if (len > 2) { narg = atoi (arg); } else { narg = 1; } switch (buf[0]) { case '[': /* CSI */ switch (last) { case '@': /* ICH */ while (narg--) vt102_insert_into_line (v, v->pos); break; case 'A': /* CUU */ vt102_cursor_relative (v, 0, -narg); break; case 'e': /* VPR */ case 'B': /* CUD */ vt102_cursor_relative (v, 0, narg); break; case 'a': /* HPR */ case 'C': /* CUF */ vt102_cursor_relative (v, narg, 0); break; case 'D': /* CUB */ vt102_cursor_relative (v, -narg, 0); break; case 'E': /* CNL */ vt102_cursor_relative (v, 0, narg); vt102_cursor_carriage_return (v); break; case 'F': /* CPL */ vt102_cursor_relative (v, 0, -narg); vt102_cursor_carriage_return (v); break; case 'G': /* CHG */ vt102_cursor_absolute (v, narg - 1, v->pos.y); break; case 'H': /* CUP */ case 'f': /* HVP */ { int x, y; y = narg - 1; ptr = index (arg, ';'); if (ptr) x = atoi (ptr + 1) - 1; else x = 0; vt102_cursor_absolute (v, x, y); } break; case 'I': /* CHT */ while (narg--) vt102_cursor_advance_tab (c->v); break; case 'J': /* ED */ /* Different default */ if (len == 2) narg = 0; switch (narg) { case 0: crt_erase (&v->crt, v->pos, v->screen_end, 1, v->color); break; case 1: crt_erase (&v->crt, v->screen_start, v->pos, 1, v->color); break; case 2: crt_erase (&v->crt, v->screen_start, v->screen_end, 1, v->color); break; } break; case 'K': /* EL */ { CRT_Pos ls = { 0, v->pos.y }; CRT_Pos le = { v->current_size.x - 1, v->pos.y }; /* Different default */ if (len == 2) narg = 0; switch (narg) { case 0: crt_erase (&v->crt, v->pos, le, 1, v->color); break; case 1: crt_erase (&v->crt, ls, v->pos, 1, v->color); break; case 2: crt_erase (&v->crt, ls, le, 1, v->color); break; } } break; case 'L': /* IL */ if ((v->pos.y >= v->top_margin.y) && (v->pos.y <= v->bottom_margin.y)) { while (narg--) crt_scroll_down (&v->crt, v->pos, v->bottom_margin, 1, v->color); } break; case 'M': /* DL */ if ((v->pos.y >= v->top_margin.y) && (v->pos.y <= v->bottom_margin.y)) { while (narg--) { vt102_history (c, v->pos, v->bottom_margin); crt_scroll_up (&v->crt, v->pos, v->bottom_margin, 1, v->color); } } break; case 'P': /* DCH */ while (narg--) vt102_delete_from_line (v, v->pos); break; case 'S': /* SU */ while (narg--) { vt102_history (c, v->top_margin, v->bottom_margin); crt_scroll_up (&v->crt, v->top_margin, v->bottom_margin, 1, v->color); } break; case 'T': /* SD */ while (narg--) crt_scroll_down (&v->crt, v->top_margin, v->bottom_margin, 1, v->color); break; case 'X': /* ECH */ { CRT_Pos end = v->pos; if (!narg) narg++; end.x += narg - 1; if (end.x > v->bottom_margin.x) end.x = v->bottom_margin.x; crt_erase (&v->crt, v->pos, end, 1, v->color); } break; case 'Z': /* CBT */ while (narg--) vt102_cursor_retreat_tab (c->v); break; case '`': /* HPA */ vt102_cursor_absolute (v, narg - 1, v->pos.y); break; case 'b': /* REP */ while (narg--) { vt102_regular_char (c, v, v->last_reg_char); err += vt102_rx_hook (c, v->last_reg_char); } break; case 'c': /* DA */ /* For some obscure reason some programs seem to send */ /* CSI [ ? .. c, which we ignore */ if (buf[1] != '?') vt102_send_id (c, "\033[?2c"); break; case 'd': /* VPA */ vt102_cursor_absolute (v, v->pos.x, narg - 1); break; case 'g': /* TBC */ /* Different default */ if (len == 2) narg = 0; switch (narg) { case 0: v->tabs[v->pos.x] = 0; break; case 2: // FIXME: - LA120 says current line only WTF? case 3: memset (v->tabs, 0, sizeof (v->tabs)); break; } break; case 'i': /* MC */ // Printer commands // FIXME break; case 'h': /* SM */ case 'l': /* RM */ vt102_parse_mode_string (c, &buf[1], len - 1); break; case 'm': /* SGR */ vt102_parse_attr_string (v, &buf[1], len - 1); break; case 'n': /* DSR */ // Device status report switch (buf[1]) { case '5': vt102_send_id (c, "\033[0n"); break; case '6': /* CPR */ if (c->t) { char buf[10 + 2*sizeof(int)*3]; int i; i = sprintf (buf, "\033[%d;%dR", v->pos.y + 1, v->pos.x + 1); c->t->xmit (c->t, buf, i); } break; default: // ?15n printer status log_f (c->l, "<%s:%d unhandled DSR: \\033%s>", __FILE__, __LINE__, buf); } break; case 'q': /* DECLL */ // Load LED on off break; case 'r': /* DECSTBM */ v->top_margin = v->screen_start; v->bottom_margin = v->screen_end; if ((len > 2) && (ptr = index (arg, ';'))) { ptr++; v->top_margin.y = narg - 1; v->bottom_margin.y = atoi (ptr) - 1; } if (v->top_margin.y < v->screen_start.y) v->top_margin.y = v->screen_start.y; if (v->top_margin.y > v->screen_end.y) v->top_margin.y = v->screen_end.y; if (v->bottom_margin.y < v->screen_start.y) v->bottom_margin.y = v->screen_start.y; if (v->bottom_margin.y > v->screen_end.y) v->bottom_margin.y = v->screen_end.y; vt102_cursor_home (v); break; case 's': /* SCP */ v->saved.pos = v->pos; break; case 'u': /* RCP */ v->pos = v->saved.pos; vt102_cursor_normalize (v); v->pending_wrap = 0; break; case 'y': /* DECTST */ // Invoke confidence test break; case 'z': /* DECVERP */ // request terminal parameters break; default: log_f (c->l, "<%s:%d unhandled CSI: \\033%s>", __FILE__, __LINE__, buf); ; } break; default: log_f (c->l, "<%s:%d unhandled sequence: \\033%s>", __FILE__, __LINE__, buf); ; } return err; } static int vt102_parse_esc (Context * c) { int err = 0; VT102 *v = c->v; VT102_parser *p = &v->parser; #ifdef DEBUG p->cmd_buf[p->cmd_ptr] = 0; log_f (c->l, "%s >", v->pos.x, v->pos.y, v->pending_wrap, !v->private_modes[VT102_PRIVATE_MODE_VT52], p->cmd_buf); #endif if (!v->private_modes[VT102_PRIVATE_MODE_VT52]) { int ate = 1; switch (p->cmd_buf[0]) { case 'A': /* CURSOR UP */ vt102_cursor_relative (v, 0, -1); break; case 'B': /* CURSOR DOWN */ vt102_cursor_relative (v, 0, 1); break; case 'C': /* CURSOR RIGHT */ vt102_cursor_relative (v, 1, 0); break; case 'D': /* CURSOR LEFT */ vt102_cursor_relative (v, -1, 0); break; case 'F': /* ENTER GRAPHICS MODE */ v->cs = 1; v->g[1] = VT102_CSID_VT52; break; case 'G': /* EXIT GRAPHICS MODE */ v->cs = 0; v->g[0] = VT102_CSID_US; break; case 'H': /* CURSOR HOME */ vt102_cursor_absolute (v, 0, 0); break; case 'I': /* REVERSE LINE FEED */ vt102_cursor_retreat_line (c); break; case 'J': /* ERASE TO END OF SCREEN */ crt_erase (&v->crt, v->pos, v->screen_end, 1, v->color); break; case 'K': /* ERASE TO END OF LINE */ { CRT_Pos le = { v->current_size.x - 1, v->pos.y }; crt_erase (&v->crt, v->pos, le, 1, v->color); } break; case 'Y': /* DIRECT CURSOR ADDRESS */ vt102_cursor_absolute (v, p->cmd_buf[2] - 040, p->cmd_buf[1] - 040); break; case 'V': /* PRINT CURSOR LINE */ // Print current line break; case 'W': // Printer on break; case 'X': // printer off break; case ']': /* PRINT SCREEN */ // print screen break; case 'Z': // ID vt102_send_id (c, "\033/K"); break; case '^': // Autoprint on break; case '_': // Autoprint off break; case '=': /* ENTER ALTERNATE KEYPAD MODE */ v->application_keypad_mode = 1; break; case '>': /* EXIT ALTERNATE KEYPAD MODE */ v->application_keypad_mode = 0; break; default: ate = 0; } if (ate) return err; } /* * If you edit this switch don't forget to edit the length and * termination tables */ switch (p->cmd_buf[0]) { case 'D': /* IND */ vt102_cursor_advance_line (c); break; case 'E': /* NEL */ vt102_cursor_advance_line (c); v->pos.x = v->top_margin.x; vt102_cursor_normalize (v); v->pending_wrap = 0; break; /* F SSA */ /* G ESA */ case 'H': /* HTS */ v->tabs[v->pos.x]++; break; /* I HTJ */ /* J VTS */ /* K PLD */ /* L PLU */ case 'M': /* RI */ vt102_cursor_retreat_line (c); break; case 'N': /* SS2 */ // select G2 for one char break; case 'O': /* SS3 */ // select G3 for one char break; /* P DCS */ /* Q PU1 */ /* R PU2 */ /* S STS */ /* T CCH */ /* U MW */ /* V SPA */ /* W EPA */ /* X SOS */ /* Y SGCI */ case 'Z': /* DECID */ vt102_send_id (c, terminal_id); break; case 'c': /* RIS */ vt102_reset (c); break; case '=': /* DECKPAM */ v->application_keypad_mode = 1; break; case '>': /* DECKPNM */ v->application_keypad_mode = 0; break; case '#': switch (p->cmd_buf[1]) { case '3': /* DECDHL */ // top of double height line case '4': /* DECDHL */ // bottom of double height line case '5': /* DECSWL */ // single width line case '6': /* DECDWL */ // double width line break; case '8': /* DECALN */ { int i; crt_erase (&v->crt, v->screen_start, v->screen_end, 1, CRT_COLOR_NORMAL); for (i = 0; i < CRT_ADDR_POS (&v->screen_end); ++i) v->crt.screen[i].chr = 'E'; } break; default: log_f (c->l, "<%s:%d unhandled ESC: \\033 \\043 \\%03o (ESC # %c)>", __FILE__, __LINE__, p->cmd_buf[1], safe_ch (p->cmd_buf[1])); } break; case '<': /* DECANM */ // Set ansi mode - ignored break; case '7': /* DECSC */ vt102_save_state (v); break; case '8': /* DECRC */ vt102_restore_state (v); break; case ']': /* Set various titles in xterm - ignored */ break; case '[': /* CSI */ err += vt102_parse_csi (c, p->cmd_buf, p->cmd_ptr); break; /* Charsets */ case '(': /* SCS */ case ')': /* SCS */ case '+': /* SCS */ case '*': /* SCS */ case '%': /* SCS */ vt102_scs (c, p->cmd_buf[0], p->cmd_buf[1]); break; default: log_f (c->l, "<%s:%d unhandled ESC: \\033 \\%03o (ESC %c)>", __FILE__, __LINE__, p->cmd_buf[0], safe_ch (p->cmd_buf[0])); ; } p->cmd_buf[p->cmd_ptr] = 0; #ifdef DEBUG log_f (c->l, "", v->pos.x, v->pos.y, v->pending_wrap); #endif return err; } void vt102_status_line (VT102 * v, char *str) { int i; CRT_CA *ca = &v->crt.screen[CRT_ADDR (v->current_size.y, 0)]; for (i = 0; i < v->current_size.x; ++i) { ca->attr = CRT_ATTR_REVERSE; ca->color = CRT_COLOR_NORMAL; ca->chr = *str ? *str : ' '; if (*str) str++; ca++; } for (; i < VT102_MAX_COLS; ++i) { ca->attr = CRT_ATTR_NORMAL; ca->color = CRT_COLOR_NORMAL; ca->chr = ' '; ca++; } } void vt102_parser_reset (VT102_parser * p) { p->in_cmd = 0; p->cmd_more_bytes = 0; p->cmd_termination = 0; p->in_escape = 0; } void vt102_reset_state (Context * c) { VT102 *v = c->v; vt102_parser_reset (&v->parser); v->attr = CRT_ATTR_NORMAL; v->color = CRT_COLOR_NORMAL; v->application_keypad_mode = 0; v->current_size = v->original_size; vt102_do_resize (c); memset (v->modes, 0, VT102_NMODES); memset (v->private_modes, 0, VT102_NMODES); v->private_modes[VT102_PRIVATE_MODE_AUTO_WRAP] = 1; v->private_modes[VT102_PRIVATE_MODE_AUTO_REPEAT] = 1; v->private_modes[VT102_PRIVATE_MODE_SHOW_CURSOR] = 1; v->private_modes[VT102_PRIVATE_MODE_VT52] = 1; v->modes[VT102_MODE_LOCAL_ECHO_OFF] = 1; vt102_reset_tabs (v); v->g[0] = v->g[1] = VT102_CSID_US; v->cs = 0; } static void pre_parse_cmd (int ch, VT102_parser * p) { if (ch > TABLE_LENGTH) return; if (ch < 0) return; p->cmd_more_bytes = 0; p->in_cmd = 0; p->cmd_termination = vt102_cmd_termination[ch]; if (p->cmd_termination) { p->in_cmd++; return; } p->cmd_more_bytes = vt102_cmd_length[ch]; if (p->cmd_more_bytes) { p->in_cmd++; return; } } int vt102_rx_hook (Context * c, int ch) { if (!c->r) return 0; if (!c->r->rx) return 0; return c->r->rx (c->r, ch); } int vt102_parse_char (Context * c, int ch) { int err = 0; VT102 *v = c->v; VT102_parser *p = &v->parser; #ifdef DEBUG log_f (c->l, "char %3d %c ie=%d ic=%d cmb=%d ct=%3d %2d %2d %d", ch, safe_ch (ch), p->in_escape, p->in_cmd, p->cmd_more_bytes, p->cmd_termination, v->pos.x, v->pos.y, v->pending_wrap); #endif if (ch == SYM_CHAR_RESET) { vt102_reset_state (c); } else if (p->in_cmd && !ctrl_chr (ch, p->cmd_termination)) { p->cmd_buf[p->cmd_ptr++] = ch; if (p->cmd_ptr == VT102_CMD_LEN) p->in_cmd = 0; if (p->cmd_more_bytes) { p->cmd_more_bytes--; if (!p->cmd_more_bytes == 1) p->in_cmd = 0; } switch (p->cmd_termination) { case 0: break; default: if (p->cmd_termination == ch) p->in_cmd = 0; break; case CSI_ENDER: if (csi_ender (ch)) p->in_cmd = 0; break; } if (!p->in_cmd) { err += vt102_parse_esc (c); p->cmd_more_bytes = 0; p->cmd_termination = 0; } } else if (p->in_escape && !ctrl_chr (ch, 0)) { p->cmd_ptr = 0; p->cmd_buf[p->cmd_ptr++] = ch; p->in_escape = 0; pre_parse_cmd (ch, p); if (!p->in_cmd) err += vt102_parse_esc (c); } else if ((ch >= 0x80) && (ch < 0xa0)) { /* C1 characters */ switch (ch) { case 0x80: /* @ PAD */ case 0x81: /* A HOP */ case 0x82: /* B BPH */ case 0x83: /* C NBH */ case 0x84: /* D IND */ case 0x85: /* E NEL */ case 0x86: /* F SSA */ case 0x87: /* G ESA */ case 0x88: /* H HTS */ case 0x89: /* I HTJ */ case 0x8a: /* J VTS */ case 0x8b: /* K PLD */ case 0x8c: /* L PLU */ case 0x8d: /* M RI */ case 0x8e: /* N SS2 */ case 0x8f: /* O SS3 */ case 0x90: /* P DCS */ case 0x91: /* Q PU1 */ case 0x92: /* R PU2 */ case 0x93: /* S STS */ case 0x94: /* T CCH */ case 0x95: /* U MW */ case 0x96: /* V SPA */ case 0x97: /* W EPA */ case 0x98: /* X SOS */ case 0x99: /* Y SGCI */ case 0x9a: /* Z DECID */ case 0x9b: /* [ CSI */ case 0x9c: /* \ ST */ case 0x9d: /* ] OSC */ case 0x9e: /* ^ PM */ case 0x9f: /* _ APC */ /* C1 chars are equavlent to ESC ch-0x40 */ p->cmd_ptr = 0; p->cmd_buf[p->cmd_ptr++] = ch; p->in_escape = 0; pre_parse_cmd (ch, p); if (!p->in_cmd) err += vt102_parse_esc (c); break; } } else { #ifdef DEBUG if (ch != 27) log_f (c->l, "pos.x, v->pos.y, v->pending_wrap, ch, ch, safe_ch (ch)); #endif switch (ch) { case 0: /* NUL */ break; #ifdef HIDE_NON_PRINTABLES case 1: /* SOH */ case 2: /* STX */ case 3: /* ETX */ case 4: /* EOT */ break; #endif case 5: /* ENQ */ vt102_send_id (c, terminal_id); break; #ifdef HIDE_NON_PRINTABLES case 6: /* ACK */ break; #endif case 7: /* BEL */ // FIXME beep break; case 8: /* BS */ vt102_cursor_retreat (c->v); err += vt102_rx_hook (c, ch); break; case 9: /* HT */ vt102_cursor_advance_tab (c->v); err += vt102_rx_hook (c, ch); break; case 10: /* LF */ case 11: /* VT */ case 12: /* FF */ vt102_cursor_advance_line (c); err += vt102_rx_hook (c, 10); if (!v->modes[VT102_MODE_NEWLINE_MODE]) break; case 13: /* CR */ vt102_cursor_carriage_return (v); err += vt102_rx_hook (c, 13); break; case 14: /* SO */ /* select G1 */ v->cs = 1; break; case 15: /* SI */ /* select G0 */ v->cs = 0; break; #ifdef HIDE_NON_PRINTABLES case 16: /* DLE */ case 17: /* DC1 */ case 18: /* DC2 */ case 19: /* DC3 */ case 20: /* DC4 */ case 21: /* NAK */ case 22: /* SYN */ case 23: /* ETB */ case 24: /* CAN */ case 25: /* EM */ case 26: /* SUB */ break; #endif case 27: /* ESC */ p->in_escape++; break; #ifdef HIDE_NON_PRINTABLES case 28: /* FS */ case 29: /* GS */ case 30: /* RS */ case 31: /* US */ case 127: /* DEL */ break; #endif default: /* regular character */ vt102_regular_char (c, v, ch); err += vt102_rx_hook (c, ch); } #ifdef DEBUG if (ch != 27) log_f (c->l, "", v->pos.x, v->pos.y, v->pending_wrap); #endif } vt102_crt_update (c); return err; } void vt102_send (Context * c, uint8_t key) { uint8_t ch; if (!c->t) return; if ((key > 31) && (key < 127)) { c->t->xmit (c->t, &key, 1); return; } switch (key) { case 0: /* NUL */ case 1: /* SOH */ case 2: /* STX */ case 3: /* ETX */ case 4: /* EOT */ case 5: /* ENQ */ case 6: /* ACK */ case 7: /* BEL */ case 8: /* BS */ case 9: /* HT */ case 10: /* LF */ case 11: /* VT */ case 12: /* FF */ c->t->xmit (c->t, &key, 1); break; case 13: /* CR */ c->t->xmit (c->t, &key, 1); if (c->v->modes[VT102_MODE_NEWLINE_MODE]) { ch = 10; c->t->xmit (c->t, &ch, 1); } break; case 14: /* SO */ case 15: /* SI */ case 16: /* DLE */ case 17: /* DC1 */ case 18: /* DC2 */ case 19: /* DC3 */ case 20: /* DC4 */ case 21: /* NAK */ case 22: /* SYN */ case 23: /* ETB */ case 24: /* CAN */ case 25: /* EM */ case 26: /* SUB */ c->t->xmit (c->t, &key, 1); break; case 27: /* ESC */ case 28: /* FS */ case 29: /* GS */ case 30: /* RS */ case 31: /* US */ case 127: /* DEL */ c->t->xmit (c->t, &key, 1); break; case KEY_UP: case KEY_DOWN: case KEY_RIGHT: case KEY_LEFT: case KEY_HOME: case KEY_MIDDLE: case KEY_END: if (c->v->private_modes[VT102_PRIVATE_MODE_CURSOR_MODE]) { uint8_t buf[] = { 033, 'O', 'A' + (key - KEY_UP) }; c->t->xmit (c->t, &buf, sizeof (buf)); } else { uint8_t buf[] = { 033, '[', 'A' + (key - KEY_UP) }; c->t->xmit (c->t, &buf, sizeof (buf)); } break; case KEY_STAR: case KEY_PLUS: case KEY_COMMA: case KEY_PERIOD: case KEY_DIVIDE: case KEY_0: case KEY_1: case KEY_2: case KEY_3: case KEY_4: case KEY_5: case KEY_6: case KEY_7: case KEY_8: case KEY_9: if (c->v->application_keypad_mode) { uint8_t buf[] = { 033, 'O', 'a' + (key - KEY_154) }; c->t->xmit (c->t, &buf, sizeof (buf)); } else { static char kpoff[KEY_NUM] = { [KEY_STAR] = '*', [KEY_PLUS] = '+', [KEY_COMMA] = ',', [KEY_MINUS] = '-', [KEY_PERIOD] = '.', [KEY_DIVIDE] = '/', [KEY_0] = '0', [KEY_1] = '1', [KEY_2] = '2', [KEY_3] = '3', [KEY_4] = '4', [KEY_5] = '5', [KEY_6] = '6', [KEY_7] = '7', [KEY_8] = '8', [KEY_9] = '9' }; c->t->xmit (c->t, &kpoff[key], 1); } break; case KEY_ENTER: if (c->v->application_keypad_mode) { uint8_t buf[] = { 033, 'O', 'M' }; c->t->xmit (c->t, &buf, sizeof (buf)); } else { ch = 13; c->t->xmit (c->t, &ch, 1); if (c->v->modes[VT102_MODE_NEWLINE_MODE]) { ch = 10; c->t->xmit (c->t, &ch, 1); } } break; case KEY_PF1: case KEY_PF2: case KEY_PF3: case KEY_PF4: { uint8_t buf[] = { 033, 'O', 'P' + (key - KEY_PF1) }; c->t->xmit (c->t, &buf, sizeof (buf)); } break; case KEY_VT220_HOME: case KEY_INSERT: case KEY_DELETE: case KEY_VT220_END: case KEY_PGUP: case KEY_PGDN: case KEY_F1: case KEY_F2: case KEY_F3: case KEY_F4: case KEY_F5: case KEY_F6: case KEY_F7: case KEY_F8: case KEY_F9: case KEY_F10: case KEY_F11: case KEY_F12: case KEY_F13: case KEY_F14: case KEY_F15: case KEY_F16: case KEY_F17: case KEY_F18: case KEY_F19: case KEY_F20: { uint8_t buf[16]; int i; i = sprintf (buf, "\033[%d~", (key - KEY_180)); c->t->xmit (c->t, &buf, i); } break; } } void vt102_reset (Context * c) { VT102 *v = c->v; VT102_parser *p = &v->parser; crt_cls (&v->crt); v->current_line = v->pos; v->pending_wrap = 0; v->screen_start.x = 0; v->screen_start.y = 0; v->current_size = v->original_size; v->crt.size = v->current_size; v->crt.size.y++; v->screen_end = v->current_size; v->screen_end.x--; v->screen_end.y--; vt102_cursor_home (v); vt102_status_line (v, ""); vt102_reset_tabs (v); v->current_line = v->pos; vt102_parser_reset (p); vt102_reset_state (c); vt102_save_state (v); v->last_reg_char = ' '; } VT102 * vt102_new (CRT_Pos * size) { VT102 *v; v = (VT102 *) xmalloc (sizeof (VT102)); v->xn_glitch = 1; if (size) { v->original_size = *size; if (v->original_size.x < 1) v->original_size.x = 1; if (v->original_size.y < 1) v->original_size.y = 1; if (v->original_size.x > VT102_MAX_COLS) v->original_size.x = VT102_MAX_COLS; if (v->original_size.y > VT102_MAX_ROWS) v->original_size.y = VT102_MAX_ROWS; } else { v->original_size.x = VT102_COLS_80; v->original_size.y = VT102_ROWS_24; } return v; } void vt102_set_ansi (VT102 * v, int ansi) { v->xn_glitch = ansi ? 0 : 1; } void vt102_resize (Context * c, CRT_Pos size) { log_f (c->l, "", size.x, size.y); if (!size.x) size.x = c->v->current_size.x; if (!size.y) size.y = c->v->current_size.y; if (size.x < 1) size.x = 1; if (size.y < 1) size.y = 1; if (size.x > VT102_MAX_COLS) size.x = VT102_MAX_COLS; if (size.y > VT102_MAX_ROWS) size.y = VT102_MAX_ROWS; c->v->current_size = size; vt102_do_resize (c); } void vt102_free (VT102 * v) { free (v); } work/src/vt102.h0000664000000000000000000000714313337271225010556 0ustar /* * vt102.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: vt102.h,v 1.25 2008/03/10 11:49:33 james Exp $ */ /* * $Log: vt102.h,v $ * Revision 1.25 2008/03/10 11:49:33 james * *** empty log message *** * * Revision 1.24 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.23 2008/03/03 06:04:42 james * *** empty log message *** * * Revision 1.22 2008/03/02 10:37:56 james * *** empty log message *** * * Revision 1.21 2008/02/28 16:57:52 james * *** empty log message *** * * Revision 1.20 2008/02/27 09:42:22 james * *** empty log message *** * * Revision 1.19 2008/02/26 23:23:17 james * *** empty log message *** * * Revision 1.18 2008/02/26 19:08:27 james * *** empty log message *** * * Revision 1.17 2008/02/26 16:53:24 james * *** empty log message *** * * Revision 1.16 2008/02/24 12:22:42 james * *** empty log message *** * * Revision 1.15 2008/02/24 00:42:53 james * *** empty log message *** * * Revision 1.14 2008/02/23 11:48:37 james * *** empty log message *** * * Revision 1.13 2008/02/22 17:07:00 james * *** empty log message *** * * Revision 1.12 2008/02/22 14:51:54 james * *** empty log message *** * * Revision 1.11 2008/02/08 15:06:42 james * *** empty log message *** * * Revision 1.10 2008/02/07 12:16:04 james * *** empty log message *** * * Revision 1.9 2008/02/07 01:57:46 james * *** empty log message *** * * Revision 1.8 2008/02/07 00:39:13 james * *** empty log message *** * * Revision 1.7 2008/02/06 20:26:58 james * *** empty log message *** * * Revision 1.6 2008/02/06 17:53:28 james * *** empty log message *** * * Revision 1.5 2008/02/06 15:53:22 james * *** empty log message *** * * Revision 1.4 2008/02/06 11:30:37 james * *** empty log message *** * * Revision 1.3 2008/02/04 20:23:55 james * *** empty log message *** * * Revision 1.2 2008/02/04 02:05:06 james * *** empty log message *** * * Revision 1.1 2008/02/03 23:36:41 james * *** empty log message *** * */ #ifndef __VT102_H__ #define __VT102_H__ #define VT102_CMD_LEN 128 #define VT102_MAX_ROWS ((CRT_ROWS) - 1) #define VT102_ROWS_24 24 #define VT102_COLS_132 132 #define VT102_COLS_80 80 #define VT102_MAX_COLS VT102_COLS_132 #define VT102_STATUS_ROW 24 #define VT102_NMODES 32 typedef struct { int in_escape; int in_cmd; int cmd_ptr; int cmd_more_bytes; int cmd_termination; char cmd_buf[VT102_CMD_LEN]; } VT102_parser; typedef struct { CRT_Pos pos; int attr; int color; int origin_mode; } VT102_State; typedef struct { CRT_Pos top_margin, bottom_margin; CRT_Pos screen_start, screen_end; VT102_parser parser; int attr; int color; CRT crt; int pending_wrap; CRT_Pos pos, current_line; VT102_State saved; uint8_t modes[VT102_NMODES]; uint8_t private_modes[VT102_NMODES]; uint8_t tabs[VT102_COLS_132]; int application_keypad_mode; int last_reg_char; int xn_glitch; CRT_Pos current_size; CRT_Pos original_size; int g[2]; int cs; } VT102; #define VT102_PRIVATE_MODE_CURSOR_MODE 1 #define VT102_PRIVATE_MODE_VT52 2 #define VT102_PRIVATE_MODE_132COLS 3 #define VT102_PRIVATE_MODE_SMOOTH_SCROLL 4 #define VT102_PRIVATE_MODE_REVERSE_SCREEN 5 #define VT102_PRIVATE_MODE_ORIGIN_MODE 6 #define VT102_PRIVATE_MODE_AUTO_WRAP 7 #define VT102_PRIVATE_MODE_AUTO_REPEAT 8 #define VT102_PRIVATE_MODE_SHOW_CURSOR 25 #define VT102_MODE_KEYBOARD_DISABLE 2 #define VT102_MODE_INSERT 4 #define VT102_MODE_LOCAL_ECHO_OFF 12 #define VT102_MODE_NEWLINE_MODE 20 #endif /* __VT102_H__ */ work/src/vt102_charset.c0000664000000000000000000000610613337271225012260 0ustar /* * vt102_charset.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: vt102_charset.c,v 1.5 2008/03/07 12:37:04 james Exp $"; /* * $Log: vt102_charset.c,v $ * Revision 1.5 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.4 2008/02/27 00:54:16 james * *** empty log message *** * * Revision 1.3 2008/02/27 00:27:22 james * *** empty log message *** * * Revision 1.2 2008/02/26 23:56:12 james * *** empty log message *** * * Revision 1.1 2008/02/26 23:23:17 james * *** empty log message *** * */ #include "project.h" uint32_t vt102_charset_c0[VT102_CHARSET_SIZE] = { [0x00] = 0x2400, [0x01] = 0x2401, [0x02] = 0x2402, [0x03] = 0x2403, [0x04] = 0x2404, [0x05] = 0x2405, [0x06] = 0x2406, [0x07] = 0x2407, [0x08] = 0x2408, [0x09] = 0x2409, [0x0a] = 0x240a, [0x0b] = 0x240b, [0x0c] = 0x240c, [0x0d] = 0x240d, [0x0e] = 0x240e, [0x0f] = 0x240f, [0x10] = 0x2410, [0x11] = 0x2411, [0x12] = 0x2412, [0x13] = 0x2413, [0x14] = 0x2414, [0x15] = 0x2415, [0x16] = 0x2416, [0x17] = 0x2417, [0x18] = 0x2418, [0x19] = 0x2419, [0x1a] = 0x241a, [0x1b] = 0x241b, [0x1c] = 0x241c, [0x1d] = 0x241d, [0x1e] = 0x241e, [0x1f] = 0x241f, [0x7f] = 0x2421, }; uint32_t vt102_charset_us[VT102_CHARSET_SIZE] = { 0 }; uint32_t vt102_charset_uk[VT102_CHARSET_SIZE] = { [0x23] = 0x00a3, }; uint32_t vt102_charset_vt52[VT102_CHARSET_SIZE] = { [0x5f] = 0x25ae, [0x60] = 0x25ae, [0x61] = 0x25ae, [0x62] = 0x215f, [0x63] = '3', // 3/ [0x64] = '5', // 5/ [0x65] = '7', // 7/ [0x66] = 0x00b0, [0x67] = 0x00b1, [0x68] = 0x2192, [0x69] = 0x2026, [0x6a] = 0x00f7, [0x6b] = 0x2193, [0x6c] = 0x23ba, // bar scan 0 [0x6d] = 0x23ba, [0x6e] = 0x23bb, // bar scan 2 [0x6f] = 0x23bb, [0x70] = 0x2500, // bar scan 4 [0x71] = 0x23bc, [0x72] = 0x23bd, // bar scan 6 [0x73] = 0x23bd, [0x74] = 0x2080, [0x75] = 0x2081, [0x76] = 0x2082, [0x77] = 0x2083, [0x78] = 0x2084, [0x79] = 0x2085, [0x7a] = 0x2086, [0x7b] = 0x2087, [0x7c] = 0x2088, [0x7d] = 0x2089, [0x7e] = 0x00b6 }; uint32_t vt102_charset_gl[VT102_CHARSET_SIZE] = { [0x5f] = 0x25ae, [0x60] = 0x25c6, [0x61] = 0x2592, [0x62] = 0x2409, [0x63] = 0x240c, [0x64] = 0x240d, [0x65] = 0x240a, [0x66] = 0x00b0, [0x67] = 0x00b1, [0x68] = 0x2424, [0x69] = 0x240b, [0x6a] = 0x2518, [0x6b] = 0x2510, [0x6c] = 0x250c, [0x6d] = 0x2514, [0x6e] = 0x253c, [0x6f] = 0x23ba, [0x70] = 0x23bb, [0x71] = 0x2500, [0x72] = 0x23bc, [0x73] = 0x23bd, [0x74] = 0x251c, [0x75] = 0x2524, [0x76] = 0x2534, [0x77] = 0x252c, [0x78] = 0x2502, [0x79] = 0x2264, [0x7a] = 0x2265, [0x7b] = 0x03c0, [0x7c] = 0x2260, [0x7d] = 0x00a3, [0x7e] = 0x00b7 }; uint32_t *charset_from_csid[] = { [VT102_CSID_US] = vt102_charset_us, [VT102_CSID_UK] = vt102_charset_uk, [VT102_CSID_GL] = vt102_charset_gl, [VT102_CSID_VT52] = vt102_charset_vt52 }; work/src/vt102_charset.h0000664000000000000000000000113413337271225012261 0ustar /* * vt102_charset.h: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ /* * $Id: vt102_charset.h,v 1.2 2008/03/07 12:37:04 james Exp $ */ /* * $Log: vt102_charset.h,v $ * Revision 1.2 2008/03/07 12:37:04 james * *** empty log message *** * * Revision 1.1 2008/02/27 01:32:41 james * *** empty log message *** * */ #ifndef __VT102_CHARSET_H__ #define __VT102_CHARSET_H__ #define VT102_CHARSET_SIZE 128 #define VT102_CSID_US 0 #define VT102_CSID_UK 1 #define VT102_CSID_GL 2 #define VT102_CSID_VT52 3 #endif /* __VT102_CHARSET_H__ */ work/sympathy.10000664000000000000000000006102113337271225010675 0ustar .TH sympathy 1 "%VERSIONSTAMP%" "%LONGVERSION%" "USER COMMANDS" .\" $Id: sympathy.1,v 1.28 2008/05/09 12:31:55 james Exp $ .SH NAME sympathy \- client/server terminal emulator with logging .SH SYNOPSIS .B sympathy \-\fBt\fP [ .B \fIterminal_options\fP ] [ .B \fIdisplay_options\fP ] .br .B sympathy \-\fBs\fP [ .B \fIterminal_options\fP ] [ .B \fIserver_options\fP ] .br .B sympathy [ .B \-\fBc\fP \-\fBs\fP ] [ .B \fIterminal_options\fP ] [ .B \fIserver_options\fP ] [ .B \fIclient_options\fP ] [ .B \fIdisplay_options\fP ] .br .B sympathy \-\fBc\fP [ .B \fIclient_options\fP ] [ .B \fIdisplay_options\fP ] .br .B sympathy \-\fBr\fP id [ .B \fIclient_options\fP ] [ .B \fIdisplay_options\fP ] .br .B sympathy \-\fBC\fP \-\fBd\fP serialdev .br .B sympathy \-\fBls\fP .br .B sympathy \-\fBv\fP .br .SH DESCRIPTION .I Sympathy is a replacement for screen(1), minicom(1) and consolidate(1). It is a VT52/VT100/ANSI terminal emulator with some special features. In normal use .I sympathy would sit between a terminal device (a serial port or a pseudo-tty) and the user's usual terminal emulator (eg xterm(1)). .I Sympathy renders data from the terminal device into an internal frame buffer and then expresses changes in this frame buffer to the outer terminal emulator using a small subset of ANSI escape codes. .I Sympathy always generates valid escape codes to the outer terminal, and will reset the state of its internal terminal emulator when it detects receive errors on the terminal device. .PP .I Sympathy\fP, unlike screen(1), takes care to preserve the scroll-back features of the outer terminal emulator: lines that scroll off the top of the internal frame buffer are scrolled off the top of the outer terminal emulator. When .I sympathy is used in client/server mode, some history is added to the outer terminal emulator when the client connects. .PP .I Sympathy also supports automatic baud\-rate detection, and advanced logging features. .I Sympathy logs whenever any of the modem control lines change state, receive errors, and the contents of any line on the frame buffer as the cursor moves off it. .SH OPTIONS .B \fImajor mode options\fP: .TP 5 .B \-C\fP clear lock files .I sympathy will remove inactive lockfiles for the specified serial device, and then exit. .TP 5 .B \-c\fP or \fB\-r\fP \fIid\fP act as client only: .I sympathy connects to a .I sympathy server process and injects the history into the outer terminal emulator, and connects the user with the terminal device. One server process can support multiple client processes. This mode can also be used to obtain a dump of the current screen in HTML format (see the \-\fBH\fP option), inject key\-presses (see \-\fBI\fP) or allow control via a dumb terminal (see \-\fBN\fP). The \-\fPr\fP option connects to a server process socket called \fIid\fP, or if \fIid\fP is an integer \fIhost-name\fP.\fIid\fP mimicking the behaviour of screen(1). .I Sympathy searches for the socket in the following directories: \fI~/.sympathy\fP, \fI~/sympathy\fP, \fI/etc/sympathy\fP, \fI/var/sympathy\fP. With the \-\fBc\fP option the socket must be specified with the \-\fBk\fP option. .TP 5 .B \fP[\fB \-c \-s \fP] act as both client and server: .I sympathy forks. The child process becomes a server, and the original process becomes a client which then connects to the server. This is the default major mode if no other is specified. Since the default terminal device is a pseudo-tty, running .I sympathy with no arguments will start a new shell in a daemonised process and connect to it as a client from the original process, mimicking the behaviour of screen(1) .TP 5 .B \-l\fP or \fB\-ls show active sockets: .I sympathy will show active sockets, ones to which a call to connect(2) succeeds, in ~/.sympathy. If the socket name begins with the host-name of the machine, and the call to connect(2) fails, then socket will be unlinked. .TP 5 .B \-s act as server only: .I sympathy opens the terminal device and renders into an internal frame buffer, listens for clients on the socket and logs activity. By default the server will fork into a daemon process but can be forced to remain in the foreground with the \-\fBF\fP option. .TP 5 .B \-t act as terminal emulator only: .I sympathy opens the terminal device and outputs into the outer terminal emulator. When .I sympathy exits the device is closed and no process remains. In this mode .I sympathy behaves like a traditional terminal emulator such as cu(1) or minicom(1). .TP 5 .B \-v show current version: .I sympathy will print the the version number of the code it was compiled from. .TP 5 .B \-h show help: .I sympathy will show brief usage instructions .PP .B \fIterminal_options\fP: .TP 5 .B \-d \fIserialdev\fP connect to terminal device \fIserialdev\fP, eg /dev/ttyS0. By default .I sympathy doesn't lock the terminal device, but checks periodically for lock files of other processes. If .I sympathy detects another lock file it displays \fBLocked\fP in the status line and refuses I/O on the device until the lock file is removed or becomes invalid. To lock the device use the \-\fBK\fP option. .I Sympathy will in addition check that the name of the device does not occur in /proc/cmdline as an argument to the \fIconsole\fP kernel parameter. The \-\fBd\fP option is incompatible with the \-\fBp\fP option. .TP 5 .B \-p connect to a pseudo\-tty instead of a terminal device, and fork a login shell in it. The \-\fBp\fP option is incompatible with the \-\fBd\fP option. This is the default terminal device if none is specified. The first non\-option command line arugment is considered to be the a binary to run in the pseudo\-tty, subsequent arguments are parsed to the binary. The current value of PATH is searched for the binary if it does not start with '/'. If no binary is specified then '/bin/sh' is called with \fIargv[0]\fP set to '\-'. .TP 5 .B \-K lock the terminal device specified in the \-\fBd\fP option. .I Sympathy generates lock files in a staggering variety of formats and places. For locks based on the name of the device .I sympathy generates lock files for all devices with the same major and minor in /dev, /dev/usb and /dev/tts, it uses both normal and lower case and replaces occurrences of `/' in the device name with both `.' and `_'. .I Sympathy also generates locks based on the device major and minor numbers, and for all lock file names generates them in any of the following directories that are writable: /var/lock/uucp, /var/spool/lock, /var/spool/uucp, /etc/locks, /usr/spool/uucp, /var/spool/locks, /usr/spool/lock, /usr/spool/locks, /usr/spool/uucp/LCK, /var/lock. Lock files are assumed to be in HDB format. .TP 5 .B \-b \fIbaud\-rate\fP set the baud\-rate of the terminal device specified in the \-\fBd\fP to \fIbaud\-rate\fP, if omitted the current baud\-rate of the serial port will be used. .TP 5 .B \-f turn on flow control on the terminal device. This option adds \fICRTSCTS\fP to \fIsympathy\fP's default \fIc_cflag\fPs of \fICS8|CREAD|CLOCAL\fP. .TP 5 .B \-L \fIlogfile\fP log activity to the file \fIlogfile\fP. If \fIlogfile\fP is `-' then log to \fIstdout\fP. Note that logging to \fIstdout\fP only makes sense with the \-\fBF\fP \fIserver_option\fP. .I Sympathy will also close and reopen its log file when it receives a \fBSIGHUP\fP, which with the \fB\-P\fP allows the use of logrotate(8). .TP 5 .B \-P \fIpidfile\fP write the pid of the server/terminal process to \fIpidfile\fP, which is removed on clean exit. .TP 5 .B \-R rotate log files. When the log\-file specified with the \fB\-L\fP option grows large .I sympathy will rotate it and compress old log\-files. .TP 5 .B \-w \fIwidth\fP[x\fIheight\fP] set the initial size of the terminal emulator's frame buffer to be \fIwidth\fP columns by \fIheight\fP rows. If \fIheight\fP is omitted it defaults to 24, the default width is 80. These values may be overridden later by terminal escape sequences. If \-\fBp\fP is also specified the pseudo-tty will have its window size set to match. .PP .B \fIdisplay_options\fP: .TP 5 .B \-u attempt to render Unicode characters in the internal frame buffer to the outer terminal emulator by using ISO-2202 sequences. .I Sympathy currently only checks to see if an appropriate character appears in the VT102 US character set, or in the VT102 `special characters and line drawing' character set. If the character appears in neither of these then it will be rendered on the outer terminal emulator as a `?'. .TP 5 .B \-H render the current state of the internal frame buffer to \fIstdout\fP as HTML, then quit. .TP 5 .B \-N don't render the internal frame buffer using ANSI characters, but instead write characters that would be written to the screen to stdout. Take characters from stdin and send them to the device. This feature is useful when you wish to use sympathy in conjunction with programs like expect(1). .TP 5 .B \-B Write the actual bytes read from the device to the logfile, rather than the rendered version. .PP .B \fIclient_options\fP: .TP 5 .B \-k \fIsocket\fP set the name in the file-system of the socket to which .I sympathy should connect. This option is \fBmandatory\fP unless the \-\fBs\fP or \-\fBr\fP options have also been given. If \-\fBs\fP is given then it will default to the socket which the forked server process opens. See the discussion of the \-\fPr\fP option above, for information on how .I sympathy chooses a socket name if \-\fBr\fP is specified. .TP 5 .B \-I string Inject \fIstring\fP to the device as if it had been typed at the keyboard. Each character in the string is treated as a key\-press. .I Sympathy recognizes various common escapes for control characters. Other keys, for example the arrow keys, are mapped to character codes between 128 and 255, see src/keys.h for details. .PP .B \fIserver_options\fP: .TP 5 .B \-F tells the .I sympathy server process not to become a daemon but to remain the the foreground. This option is incompatible with the \-\fBc\fP \-\fBs\fP major mode. .TP 5 .B \-k \fIsocket\fP set the name in the file-system of the socket on which .I sympathy should listen for clients. If this option is omitted .I sympathy will create a socket in ~/.sympathy, creating that directory if necessary, and named \fIhost-name\fP.\fIpid\fP where \fIpid\fP is the process id of the .I sympathy process that created the socket. .TP 5 .B \-n \fInlines\fP sets the number of lines of history that the server process stores to \fInlines\fP. When a client connects \fInlines\fP of history are injected into the outer terminal emulator so that they can be seen when scrolling back. By default the server stores 200 lines of history. .TP 5 .B \-S tells the .I sympathy server process to log errors to syslog. .SH OPERATION When .I sympathy is relaying data to the outer terminal emulator a reverse video status line will be visible at the bottom of the screen. The status line shows pertinent information. The first item on the line reminds you what the current escape character is, the second indicates the terminal device to which .I sympathy is connected, and the third shows the current baud\-rate. Other messages are: .TP 5 .B Flow indicates that that RTS/CTS flow control is in operation on the terminal device. .TP 5 .B RTS indicates that the terminal device is asserting the RTS line which indicates that the local system is ready to accept data from the remote system. If RTS/CTS flow control is in operation then the operating system or hardware may de-assert RTS even if RTS is shown. See the section on SERIAL PORT THEORY for more information. .TP 5 .B CTS indicates that the terminal device has detected that the local system's CTS line is being asserted, indicating that the remote system is ready to receive data from the local system. See the section on SERIAL PORT THEORY for more information. .TP 5 .B DTR indicates that the terminal device is asserting the DTR line indicating that the local system would like the local DCE to establish a connection to the remote DCE. See the section on SERIAL PORT THEORY for more information. .TP 5 .B DSR indicates that the terminal device has detected that the local system's DSR line is being asserted, indicating that the local DCE is ready. See the section on SERIAL PORT THEORY for more information. .TP 5 .B CD indicates that the terminal device has detected that the local system's CD line is being asserted, indicating that the local DCE has a connection to the remote DCE. See the section on SERIAL PORT THEORY for more information. .TP 5 .B RI indicates that the terminal device has detected that the local system's RI line is being asserted, indicating that the DCE has detected a ringing signal or incoming connexion. .TP 5 .B n clients shows the number of connected client processes. In the \-\fBt\fP major mode, this will always be zero. .TP 5 .B Locked the terminal device was opened without the \-\fbK\fP flag and another process is currently using it. I/O to the device is currently suspended until the process dies or removes its lock file. .TP 5 .B n errs indicates the number of frames received by the terminal device with errors (indicating the wrong parity, baud\-rate or framing). The count resets if no errors are detected by the device for 10 seconds. .TP 5 .B try higher .I Sympathy thinks that you have set the wrong baud\-rate and is unable to determine the correct one as the current baud\-rate is lower than the correct baud\-rate. Use the \fBbaud\fP command to set a higher baud\-rate (eg 115200) and .I sympathy will try again. .TP 5 .B try \fIrate\fBb .I Sympathy thinks that you have set the wrong baud\-rate and thinks that the correct baud\-rate is \fIrate\fP. Use the \fBbaud\fP command to change the current baud\-rate. .SH COMMANDS Commands are entered by sending the escape character, ascii(7) STX, from the outer terminal emulator (usually by pressing CTRL\-B), typing the command and pressing return. Whilst the command is entered the status line changes to `:' and rudimentary line editing is available. Whilst the command is entered the cursor \fBdoes not move\fP but remains where the terminal emulator has placed it. Pressing the escape character whilst in command mode will send the escape character to the terminal and cancel command mode. Valid commands are: .TP 7 .B ansi switch from VT102 behaviour to ANSI behaviour. The most noticeable difference is the so\-called `xn' glitch. .TP 7 .B noansi switch from ANSI behaviour to VT102 behaviour. .TP 7 .B baud \fInnnn\fB set the current baud\-rate to nnnn .TP 7 .B break send the break signal by asserting the TX line for longer than a frame period. .TP 7 .B flow enable RTS/CTS flow control .TP 7 .B noflow disable RTS/CTS flow control .TP 7 .B hangup de-assert DTR for one second. .TP 7 .B width \fInn\fB set the current width of the screen to \fInn\fP, and reset the terminal emulator. .TP 7 .B height \fInn\fB set the current height of the screen to \fInn\fP, and reset the terminal emulator. .TP 7 .B reset reset the terminal emulator .TP 7 .B expand expand the size of the screen to fit the size of the current outer terminal emulator window .TP 7 .B quit exit this instance of .I sympathy (disconnect from the server if present) .SH CHARACTER ENCODINGS For characters between 32 and 126 .I sympathy interprets them as would a VT102 terminal by following the subset of ISO-2202 that the VT102 supports. Characters 128 thru 255 are assumed to be in UTF\-8(7), if however the UTF\-8 is invalid they will instead be interpreted as characters from ISO_8859-1(7). Character 155 (0x9b) when not part of a valid UTF\-8 sequence will be interpreted as the one byte CSI character. .PP For the outer terminal emulator .I sympathy by default issues the ESC % G sequence to select UTF\-8 mode and emits valid UTF-8. If the outer terminal does not, however, support UTF\-8 use the \-\fBu\fP switch to force .I sympathy to use the VT102 subset of ISO-2202. .SH LOG FILES Log files are made exclusively in the UTF\-8 encoding. Each line in the log file starts with the date and time at which the entry was made \- for example: .IP Feb 27 23:24:42.509440 .PP .I Sympathy logs a line to the file whenever the cursor leaves the line. Additionally .I sympathy .IP \(bu 3 logs certain other events to the file: .IP \(bu 3 serial port parameter changes: baud\-rate and flow control. .IP \(bu 3 serial port control line state changes. .IP \(bu 3 serial port line discipline errors. .IP \(bu 3 serial port errors. .IP \(bu 3 suggested baud rates and bit frequency analyses. .IP \(bu 3 transmission of breaks. .IP \(bu 3 sending of the hangup signal (dropping the DTR line). .IP \(bu 3 unknown or un\-handled messages sent on the socket. .IP \(bu 3 connexion and disconnexion of clients. .IP \(bu 3 reception of SIGHUP. .IP \(bu 3 invalid UTF-8 sequences. .IP \(bu 3 terminal size changes .IP \(bu 3 un\-handled terminal command sequences .PP The log file is rotated when it gets too large if the \fI\-R\fP option is specified, and the log file is re-opened on receipt of a \fBSIGHUP\fP which together with the \fB\-P\fP allows the use of of a program such as logrotate(8) .SH AUTOMATIC BAUD RATE ALGORITHM If .I sympathy detects a framing error on the serial port it displays the count of errors on the status line, and logs the error. .IP .PP The count is reset to zero after ten seconds have elapsed during which no errors have occurred. .I Sympathy looks at bit patterns of the characters received, and measures the length (in units of the receiving UART's bit period) of any runs of '1's delimited by '0's and vice\-versa. It then calculates the statistics on the length of these runs, and logs these. .IP .PP For a typical stream of ASCII data, the most common run length will be the correct bit period. .I Sympathy uses this together with the current bit period to calculate the most probable correct baud\-rate, which is displayed in the status line, and logged. If the correct baud\irate is higher than the current baud\-rate then the most common bit frequency will be '0' or '1' and the correct baud\-rate cannot be determined. In this case sympathy will display and log the message 'try higher'. .IP .PP The algorithm only works well if the data stream is normal. If the data stream is generated by the reception, at the wrong baud\-rate, of characters emitted by .I sympathy then the algorithm will be biased towards suggesting that the baud\-rate is too low. Noise on the line will also result in sympathy concluding that the baud\-rate is too low. .SH SIGNALS .I Sympathy reacts to a set of signals. You can use the \fB-P\fP option to easily determine the PID of the .I sympathy process to which you would like to send a signal. .TP 8 .B SIGINT .I Sympathy will immediately try to restore the outer terminal emulator to its original state and then exit. .TP 8 .B SIGHUP .I Sympathy will close and reopen the log-file specified with the -L option, which allows the use of programs like logrotate(8) .TP 8 .B SIGWINCH .I Sympathy will redraw the display in the outer terminal emulator so that it will fit within the new display size. .TP 8 .B SIGCHLD .I Sympathy will wait for children if some were born (for example from compressing rotated logs) .SH ENVIRONMENT .I sympathy uses the \fBHOME\fP environment variable to determine the default location for sockets. .br .I sympathy sets the value of \fBTERM\fP in pseudo-ttys spawned using the \-\fBp\fP argument to `xterm'. .br .I Sympathy will use \fBCSI ] 0 ;\fP to set the window title to the name of the socket or device if \fBTERM\fP starts with \fIxterm\fP or \fIrxvt\fP. .br The \fBPATH\fP enviroment variable is searched for the binary to be run in the pseudo\-tty. .SH EMULATION .I Sympathy completely emulates a VT102 terminal (including the VT52 emulation). .I Sympathy also emulates a few extra sequences: the xterm(1) ESC ] ... sequences, and the ANSI CSI @ and CSI b sequences. The numeric keypad follows exactly the sequences produced by an xterm rather than the exact VT102/VT220 sequences. .I Sympathy also recognises the ESC % G and the ESC % @ sequences to switch between ISO-2202 and UTF\-8 but ignores them (see CHARACTER ENCODING below) .SH SERIAL PORT THEORY A serial connexion was originally envisaged to connect a DTE (Data Terminal Equipment) to a DCE (Data Circuit-terminating Equipment). The DCE (some sort of modem) would assert the DTE's (the computer or terminal) DSR line to indicate it was ready. The DTE would assert DTR to indicate to the DCE that it should attempt a connexion to the remote DCE. Once a connexion was established the DCE would assert the DTE's CD pin. Data could then flow between the DTR and the remote DTE via the two DCEs. Flow control was provided via the RTS and CTS lines. The DTE asserts RTS when it is capable of receiving new data, and pauses its transmission of data when the CTS line is de-asserted. The local DCE asserts CTS when the remote DCE detects RTS, and vice versa. .PP In modern usage the signals are slightly different, for a typical connexion using modems DSR indicates that the modem is ready, a drop DTR is used to indicate to the modem that it should break the connexion to the remote modem. CD indicates that the local modem is connected to the remote modem, and CTS and RTS behave as before. Connexion is established by in-band signalling before CD is asserted. .PP For a \fBnull modem\fP cable local DSR and DTR are wired to remote CD, local CTS to remote RTS, and local RTS to remote CTS. Thus asserting local DTR asserts local DSR and remote CD, and asserting local RTS asserts remote CTS. .PP When RTS/CTS flow control is in operation and the receive buffer becomes full, the operating system, or the hardware, de-asserts RTS, causing (via the DCEs or the null modem cable) a de-assertion of remote CTS which in turn causes the remote DTE to cease transmission. .SH EXAMPLES .PP using .I sympathy to mimic screen(1): .IP [foo@barhost ~]$ sympathy .IP .I Sympathy forks. The child becomes a daemon server and launches a new shell in a pseudo-tty, the original process becomes a client and connects to the server and shows the output. The user then uses the new shell and after some time either hangs up on the client or issues CTRL\-B quit, and the client detaches from the server. .IP Later the user wishes to retrieve her session and to determine which sympathy sessions are active and issues: .IP [foo@barhost ~]$ sympathy \-ls .br /home/foo/.sympathy/barhost.8843 (Active) .br [foo@barhost ~]$ .IP The user then issues: .IP [foo@barhost ~]$ sympathy \-r 8843 .IP and is reconnected to her session. .PP using sympathy to mimic minicom(1): .IP .IP [foo@barhost ~]$ sympathy \-t \-d /dev/modem \-b 9600 \-K .IP .I Sympathy opens the device /dev/modem and locks it, sets the baud\-rate to 9600 baud and disables flow control. A VT102 terminal emulator then displays the data from the modem. The user quits the emulator by issuing CTRL\-B quit, which unlocks the modem and exits .I sympathy. .PP using .I sympathy to mimic consolidate(1): .IP .IP [foo@barhost ~]$ sympathy \-s \-d /dev/ttyS13 \-b 19200 \-K \-k /var/sympathy/13 \-L /var/sympathy/13.log -R .IP .I Sympathy becomes a daemon and detaches from the current tty. It then opens the device /dev/ttyS13 and locks it, sets the baud\-rate to 19200 baud and disables flow control. .I Sympathy then listens for clients connecting on the socket \fI/var/sympathy/13\fP, whilst logging completed lines and changes in status to the file \fI/var/sympathy/13.log\fP, rotating the log file when it gets too large. .IP A user wishing to see the current status of /dev/ttyS13 issues: .IP [foo@barhost ~]$ sympathy \-c \-k /var/sympathy/13 .br or .br [foo@barhost ~]$ sympathy \-r 13 .IP and the last 200 lines of history are injected into the history of her outer terminal emulator and she is connected to /dev/ttyS13. The user disconnects from the server by issuing CTRL\-B quit. .PP using .I sympathy to mimic script(1): .IP .IP [foo@barhost ~]$ sympathy \-t \-L typescript .IP .I Sympathy starts a shell in a ptty and logs completed lines to the file typescript. When the shell exits .I sympathy will terminate, or the user can press CTRL-B which will close the ptty and send a hangup to its controlling process. .SH SEE ALSO screen(1) minicom(1) consolidate(1) .SH STANDARDS ANSI X3.64, ISO-6429, ECMA-48, ISO-2202, ISO-8859, ISO-10646, Digital Equipment Corp. VT102. .SH BUGS .PD .IP \(bu 3 The command editor and parser should support better line editing. .IP \(bu 3 It should be possible to change the escape character. .IP \(bu 3 The HTML generated with the \-\fBH\fP option is ugly. .IP \(bu 3 No useful error message is generated if opening the terminal device fails in the \-\fBc\fP \-\fBs\fP major mode. .SH AUTHOR James McKenzie, sympathy@madingley.org work/test/0000775000000000000000000000000013337271225007714 5ustar work/test/Makefile.am0000664000000000000000000000107213337271225011750 0ustar # # Makefile.am: # # Copyright (c) 2008 James McKenzie , # All rights reserved. # # $Id: Makefile.am,v 1.3 2008/02/06 15:53:22 james Exp $ # # $Log: Makefile.am,v $ # Revision 1.3 2008/02/06 15:53:22 james # *** empty log message *** # # Revision 1.2 2008/02/04 11:30:57 james # *** empty log message *** # # Revision 1.1 2008/02/03 16:20:24 james # *** empty log message *** # # # INCLUDES = -I$(srcdir)/../src noinst_PROGRAMS = test xn xn_SOURCES=xn.c test_SOURCES = test.c test_LDADD = ../src/libsympathy.a -lutil AM_CFLAGS=-g work/test/test.c0000664000000000000000000000214613337271225011042 0ustar /* * test.c: * * Copyright (c) 2008 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id: test.c,v 1.8 2008/02/27 09:42:22 james Exp $"; /* * $Log: test.c,v $ * Revision 1.8 2008/02/27 09:42:22 james * *** empty log message *** * * Revision 1.7 2008/02/20 20:16:07 james * *** empty log message *** * * Revision 1.6 2008/02/15 23:52:12 james * *** empty log message *** * * Revision 1.5 2008/02/14 10:34:30 james * *** empty log message *** * * Revision 1.7 2008/02/14 02:46:44 james * *** empty log message *** * * Revision 1.6 2008/02/14 00:57:58 james * *** empty log message *** * * Revision 1.5 2008/02/13 18:05:06 james * *** empty log message *** * * Revision 1.4 2008/02/13 17:21:55 james * *** empty log message *** * * Revision 1.3 2008/02/08 15:06:52 james * *** empty log message *** * * Revision 1.2 2008/02/07 15:42:49 james * *** empty log message *** * * Revision 1.1 2008/02/05 14:25:49 james * *** empty log message *** * */ #include int main (int argc, char *argv[]) { return 0; } work/test/vttest-20071216.tar.gz0000664000000000000000000045721113337271225013306 0ustar veG[msƖWty1 e*{xl_㙝RI}n!<Ɠl~=/yβ(*nsu7§IOI㿽#67^:XtoDXO ?M.NX_Y>|Gxfy7=\VbBCK,(MDhqǩ)f(λOW]y.B˩Gp\] CND0TbbR3ilGY!__|ܽď+bz.!M2jIeq8 8zy~myX~YAL (+l7WP`ǖ h%he 8wu`1}6DJܖޗeQ;΢I b+Rx^^D>i+ ڞ헗Bi?8 2݉Gt3ℒ+>?>?<Ŝ0WЈ'juL8}?]d)gJ7=\v$Y_[{?*e~Q:~[9'ٜ(DZv3Z"2ηTzyk쿶I@SvL,O@E\0m{-KkڢP10o`I ]2{Ua4Y2@BbIߘXϧIAm%rrn~h=: fmBˁ6ID1N$J"+6.<*0DϋH<&Ԇ7`oy{" ZYCr-ntMwAr":=~aRxc5xw눮wH_˧L8wuKQF2R8nbN;At(?쌜qQ:ESUŤu!~ '㐙L laZλl_`SKfQ0rț]'sCjq[O^+<0P Td֕$6g`O)dHb8sq?@2 #Ձo5jAs#}44.nfnPMy>޵X}Ji9b6Jc>,8 AZNg4_@-i:W itVVVKo&*E$3,r'%&) oO9{b9>EHkZ,Ȇ phX\ dy9<#ЪV|a'AeY`~r S¤03! M:nOǝ03{Gzk{0#8klsM@eoFVJ4!\[ΫҌ`2F`H`EEBQ*VKl*ONWusuw|MiBH|^}~j k†;Bpqڅ:J±̧sBH)0a(GlW*/ލ.\UcB@&؃: & CJ jpnW n *h"H#(aY2 UhE,*,Ur{wy8t?D@ZiXTRit.QXʬy4 |CZ%I=R#rBZ]2~a4)6eLz["ĭT@ +Dq Vy2ŹXG%Zȯuf3Dh^H(/L \yU:A$DnvmۥQ\4r,P1L͘fë{l7x74ꦨ6Ln&N\,54YLI++^%m&hwj*H )4=z:mpB "{ea1?>T6̙ʤQ4<]Xe{niBz{$Χ߀Dc]\rrIy%LqU*8 ),$N Na^YYڕKOR0\ |M{7.u{2vA8A82 c'X*!e%B8# ָvfSjB9Nc~aHq67'*PԠ~yMSZg)=l*[gEiPI7t8?rFZ]f4lɲtkZb/8dda؜PٙrVm$"lw.+Z8j$`(?O˄(j<&'uA5 +`D}EiI@-qDVEєwB)ٵ Zإr{C)Wۇw7%5%^t};I/fr9u Si ~Qɑ) L,0G#D04p ί He+`lhJ88Ǥ,JT6V)5w>f3Xv\~ùiLlUZʷy lzP7{2{W乼ƷxXKE9LIwSxsdM |Uc9<7MȾO:.hoUySyEIeCn KHݩ{vp6.Ѧ -7O: _Zr8< VT6z0~|1JI\K5:ºv.V-P`X8&V\ ߱5>+t1JcŊ"[xv94Ǿ<>uB*e4؉ ŷmilXEc8xj3 Ar՚Bk&L5& '7D 8=zhiC&j35{=Q'=R *%]#;4o;yCzzXa;,CLFadY[v+r:$+glDQUp-VORM;񚪚tdQZ%W&T-w}btu/:ǔ%mF|&,\u0G1h!nm)_is՜)re HgGtUV.c+|G|9on[O̞˵i*Mԧnέرb鮔k]},s#)SG*1ٕۋA\oX/곡aE3LVo.?CM2Re+ uA//LPK8({3.aۃ?H.+"]J-q9#eğFI4vkMs1:\"G!Yw>̍4wtw VЎ;-2M–!ò&Z5nGzWwJ8b/ZELb9/x = ߊp\ia$;^pYi7}|P:T~-@7ϝy<9dަa?6Qoۺ`[*}.§p`=݌ʮ \Dwi$75X1Gsi$-1 @xZZ,k.orˬ Q8,]gRx{ڷuX,py x"J_!"8;9dez$H‹zwq B*3sD!u=!&J۞9bC fVvm5\d8[vRD9{4v]M3ꊝIg%fv$17iHy}zT D LX>RǮ% e!hmZ3Q~ꕺ3;sD0pEGE =DgmVaKqHKX/[0UPtʞԩY+H5O yantp`$퐶cǾ}qM_h7:Q̈́1 Ne;'!xp_{lN ̽FO唎-\AaدBs΍n@#(7P/ݑ|z= $#",xłWJZx×@}$qm!/ŏ[6]%(QXd,ri#w))iB%<יT枒NU36Pݖ3zKoj8mh9ffڃzT[µ [˅Km j<ҋ*rE#IJ]XTMG*T& Rs41(4jCؕbx.x( #rWaIX%gURHj/8S 6)n&0Y&+4foRz:m8ݜSC#˴eG#|<A}`x(.2<7بHSټM[+WV9x^swH5K ]kDh6K7_u/J\\.~H:KW)+yV-oeY0998x<,C o`SBVW!ՈHzr6f3M ,bZ Nڭ`DOn4{~V5Zz:Uv[zΠw5k5Iݣ5itө(nӳvƏufڛV5xo: ut>PjmvAWоiZ/=bPIi[6FlzV(zQvipz*OIm=Zg=rzSy}Xk=IZǪd5M:џ4ۭfD.t{𼯤jV3v #M!(xf|ZQ:*v_w/g62T_yWxV',wK :Z2q[& H  %)ݲrzXW/Uitaw<^!-&ʂFmuHMq&uPjI(wF qck,3V]CbI_Nw@|y (i>>7{5U!]Ώb1xYx^d#9Z=-%o1c31F>4Im^%MTZ))*<Tu]T &l5PAdB2˦ "0rQYRi܄'2f[BU`%pDު_5 ÙQڤNX,m|?V 곧$kf{_nt)Bc︳_.{SE/>O 3GM:5")UC[k TbcRmXyx50+I9,Fǰ(3-ZsՉ(}H3%"@\ITffB%4P<nHfZ`;ʀC8-.&k3DR$<0jumPUAft DNs5)70f(fⲼ5J32Ip "W22"=}ovvOH\GFd 6,0rZ;.5Nbl,GRjWkOhTDŽT[fvt JWGb kU h ILٲ[P$5t!x:"}͛*ipg]rW z9>ڵ vhe} 8oA+yt# VL R +J7'U!qꫜr%UWF3AB &&O䝶 Ґ@b(>ڿ4̀OAF pXM!氯ۻ%w9b+dK vF>Fnc?lŎ6{sYp8,{R*OI1_ >ݤ;34{tht<}3!v_DgqL2y͟T}#ez+GL֚Bյk| )1_QdZ'꟧=>&IB? N`pЫe\ܬBAMyRSeGJ80"?9baK+-QIXfȍp$me#=QyP  Eʉ{G KWGpg=fw[/;2 I~ iTXI>Qd{D2L^貱tJvnvd /\zGbzhf)shBU0BTm ) 6oXm_@^03f6}ߦ4(b郐Lw mz}K[ofaF#wUX.W-}%c=<A^r _ =x5/7\4HgɶF oV 1]F뵲Zp6mUo3IJ4BB_Ir `e IL0ɹ$l:N^kOI+c[U尸! Sd:n؈)'#%VR jYq4Q]8J'֗4OIPvK[&j'XE!qZ'էF}GSF]8t6Nġ˘$;7~A+|s[[dUUa},Wi̧ahE_H5Ra.F&Shш:y2 ;Ӧ$xΌ&a}09dұulԫ9G1d6;4!'o\ 8QHu/Yd@^Ioy~sJ qS"ea~};U*ˀ%4h=BACҜs TkU}!}7\ƂZ8W/,KglD[R2l}o)"P $WLslzhQb/֫u$O*=' 7nƫ.^ Hϑij>Gy?O>3 "7}'{Iz%oZ^0=nu3ڊ|xN}\XN ~:Y+)gPuζR$ U L)t8ZnEp,*C<:r7qxsGs&襴LhC_k@6h6ބ$Y+I" ƓF$D O)Y+M9Z:mrzKbbtvWBGC$Ld4_R.4UHO\$,lZ43sle`8u-J0ֻg-" !nxj2nXJaBho^ Oӂ>R:s^XL1Qovd_]MIyܿnA͖Y[ސG$y9qzs|U trꔾxlȖTdpI627jk a(YM=щ׋K4Nvl9Pmёњ3 1,?=и+>%/*^ A$Uw1YKzXN/#8*ukuHAx>d{N:桢c裫~!l$:ˣ]Ƿ7=$,~ -膭Th;Ȃp7L[/V#Mk4# tg..=d2R$%'iEV4Z>"_f`[Q.rg䮞O%ltz$5}|Xo3e{twq=ad>z2*~3@/\-w\'E49yKW*K4 azXK'TI+tώ$`hY;kkU.`Xpբ`X #vQlP*hg܉ѯ)!4!=!)s64"Yk+[fB. n W" AID꒧Mp^J'zQŭ-&a\wŶ'xcl|| \Z-5w1w|= ֥Ȕq*jeM&>lzڴ W*eu:fKX*Wz&޽Ӆ8&ʏҁ"f/CjܟUcHž$YlE2/wQ )VHYǤM bB8L0|,ڌ+6P-l"goKl@mƒTPSL1%7li^xigYm#'ξsPU"}>觜}u:tèc}=/U#_z{6dq|EŬLpHcl8GAL4F߿[GsH& 骾uesQq(P0UضL"d.j-<:ϣ|*,$~qж{@5W` 㱟#:e$| CY$'qCxe!6TcR7IK2y&&\C>gIQD>0n;&9}:q]HUmnT{#F6Րܝ`ܥdYPe$&)F3)Bld_ģ3`8Ck3.{NwTzm J X Aﺸ#,#Xӏu)`SS~R]ig٬SXe7x-;'AO|6c_5JADmyle6e0ahK[P^mp2>\`'MiOg`&t7&Zh䚓k܉ga"bERn?p>*Z[uTɉ%)|w5+zqHAW3:חjK_/[{rG`mYP5-lY PĦNd)_~1RV2:xbt'–6#;EezgbcQqi̱|C)IɎ*+`yǚX>2f j,ӈ^1ze502X8'./ pfϣ曕 S ?qzsЈ2RuTiϴ1FLqm0(302ڤBR&brRi ;mH kg:Ix3 : H}j.ndwC>5R%6FEۍ8<6q!˧8bO]K9g{ǭr`}w9mL vr~:{{(3*'9m>fR˿ ڬc/($N*9JeDE>}>_ovV#+^^E"t+͒SZHOэ7ln-INΝ?zAJҸa(U[ͭZg+vU9xʎD塱bЌˑQȑ:8-tJAaB4 yAdTB!KVK E/ ]  X(]ۛ1'h=VƔ50>EI>ΣSkg-i'G8S2v9/\j΍l\X1*b_:*1 '1?]\Jj6/޴̩>m,/-E[ܪnlU6aD8tnMWXrKUU:{ `H286={-7aadKC st:"; &Y|nq-L* Dϔ3uT=yB}= YIbUnDOga:!&f,&: ėU(JN[h$ĕ5D I'kr5\Q`U{%!ÇŪ.r?%@^:2M` %n:V U z9ۚ<$s,}9DbUjGU=ڷ8q/;0Xkכ`~ÿ7;/v7o>iŜ-Ĥ@]%rag%r--W`3F݂a5:dө._[ofk$w8QJ;,(Љo V{/Մҽ$Ṉ15q+i 2UzA. wCk&E;6d~sbs2/=̋jPIŌeb58?"҈ͭZ|ihlcW ,,ٍhSD# B.{A!aEe=g~kTPa&Hqף~sr8N&^zofn8dxVHLx?uHF߹[0A "E &-i7p*CQפ0[\GGLH@<ōeW-+kT`/6;Ȟa'X=Z=D-ka@1#Hꀢ^i\y>ߞ{n;a=qߤ0V|"/ъ͹o;=4EYvfɹDe6@ fL@CuhdԈf5]jWj@,vjukZYAz^TWs=U7rTQF T:˔'naR' 7ݖt;!Nw1ːC9EyұJ&@),5cL1#z͍pn/,)2PEހ73ZWYckx뫾7+6Eavreⵉ)S餃6e6m_[w~ OY'*$JeUGζSŨ9R[#|'Ӟj_׍~ic;Ԭ= 0 cwtmMG#9LQ'\sWBrȻY "dzjLma\t,>?zwtV8~*$DO҄3"h>=Ggy|}yv,)D6+ <4{!jEf9`ʓbt7s%>uXg P!ۅB` ݡ#!<@QN.\}}I۷jࡆ؃ !J׽paľx. m尌V@X!eWߠF?0 ;a?:9ghמ[9'CZIqtE!C9/ĻQ7ⶹT@$& uϹt;7Bx]KZLԶ-^jO8Y5z%g 1To[Q?"J !*JuPm4H>vDtȵ ;GL̤9vfђĢgpmZF֜ή;UI֠jvZ{Vh 0einOj?@#:ѕHm1/mGo^FvUh"ZʽO[5@'KYbOE9hpUkTo кğof˥:ԨP%_=y"C>`'CL<):!oDF1JY+.\k2G)C`ER+yuD.c9i{1;ryM HaaXr@Zk;\vg|h!Y=}Kt ſjLuK#D19^w"vXZ&Cy*ujLT0 S5yO%KoPA[>>I#:;8.yhTeRK$+br7[my}4DMrP&@$pA{ 6FtegNI\!oӇ2~JP q>y_;!*ӧ3?b3] TC:6R yτ$\ϚӁuT3<_QtN3y]vVNEC7Ҡ*XB5 dny4H9`f, !3u܅!-B=`Ċ`_ aodśwͭ~@橂Ef|2і%Zj[#A9]7A G!FQH@j&#0'+)|sy4F@((!!9:݅Yj?%dEĥ,*oӀ,;rXWR(遪<0MQ936Җ||b 5ȅa nCڒHvâ2hі<POE͵[$iqHRKRÎ\<_s 'b ^/o;LL!Rt 7\'\^Zts&Fhd*R4"P/)W3J2QKE&ˌ2s{m+Qyd`JZUO7@X9aLHͣԺ[jE<1Q6ǖyV o̴ZU:Q\S.5݊Rǹ]*&w&UQ??e Z.pƽ?u 68v4CY~!'f1 GY4OaX!@l/8 8 :wL2` 2jif``WؕWP_,$H]an*Xh1PDd/ܽÝB}ù=V.0teuFnvHbTFD5Ȩ?aU݂UC $\]!aTW"F+NXJF Pyi"*?l8*ai:+_g_.ga+ _LVag`PE~U5.5g#I1Ha{obiaet4ڒLm
x|9=D| 8MtF JX-ܣ 0Mbp6T9-UŁJǖ& Eyr*ɘ>;X~Ȧ6q=ž6Kij5`NvޟdmRZ" MlDA5u@&"EX&6٬GHt?,N$|J2&}5r{{V)]SΘ8JZ.ǰyKXKBU&OLXPal;@KE܋xJG80rHD9>P=vu2o3C>v2btNvZ-o4I2B0r諁osD˿w*hZGI{+OJ&:Igơ[wA amr[,Mݜjcn)}L%L$%,&Mf4~mW$ݭcĵTV*"\Jj(@r3'Q'sl`6zR[^TrrV+Oq7.*RT[u=rw]45H+gw޵wO\rCq$Y>;j$罃xÝװI8H;iFz#ԟ{JfV (s<ӷ <^oj\Ъcp:ΦO 0:+Dp6al  &o2fE/J2S.` c㗠::is%FX-T뀟65X\#ZyF\=Um& Il|*&+Od0 |Mݞ ;J Fd}wf5n͞UӢ@ -(LvE~mTZG^2LcMtҥC<^s + RV0 >Q퉧]Ne tHXd)0GmAHש)9&YXo!/ׂCW,H wp M n&ЍO,zÀ3"1s7V>o$n,( VJj)CXKBZCRZM( 4 02 (Vzt=$h]Dk~f "kܓHF*LHdD S"6IS"[՞$BN7 *bAzQSWCYxMDή ;ɹsn8ՕJo IK/ھt7FM?k{d6N(e7E W>5n,r=rh*/9Ʋ&5ehYŕ#3I{J~x1Fz\"cS*SX^ 8kd$g^A`ه-mG:h)(f'+ќLpgfbSJē*ɾ0r8`R8WUЅ;^NZ$إP3HsܚDN< '?DaD2O l9[j8A Ӆnl!~^0>ޘd:,9559bB$S93M^W /Ơ1YT*oЪ0>tXvTzZ)ɭADqZz,hmG+ u}(bGTIye,wdkT.vP / /\٠h=QZ_VU_J\XN &? uw*[TgK](6u m3׍Z" ' I4eE.3.{꬐./;QHC腫/9yw_\!BrI0 !=tJNU$Q͈&Hr'xUJ+0ie0Õo vQK]AKN`s+&*acoTҚ_=aϊm$[3s=$RIJ1)J"m2s_K=ϕP(Co豲G, "$01o3/ިa%Lذ:K\zw*tP\ ޽kށ2ik}fxqh0R0 E{npnYv ZxfKy }Ld"l1l.%.to;,5EWX,c $2}xE!S(ORI -)rFZ]}l!k͊U3Wz+9 >q(/#M ̍^U)4>}rY7(+ovIvL=/ QPʫV*+4L}UNO|,G(Gk Ω &q+P}|̎L0ssr{1kkٖ/dM-V|EZ ]~Ǻ))s|$+nZ\Ѕa|%(Wy:*u_Y+O\z)[5..ϜZַt}!р5mɯQ1;[C(}9:'>CΞubvobH;mX112Sf' W } (+D iD E" q=)\Q<߮ PYJtqWߡ4JK6Ȥ6ԻC c7y$m=:$䄷F_:ԽO(Jb@tW);VJSb]o>վ ц]4Զ]_x$wS:O㾈~Ctŭ/W1|5pX0_;H*z7aQS]g"6*N=!\R_^zuSe \w'W(Ҹz^'7()*t4jK7-'C2&-0U`5 {W)Ur"ۄ"G Y[+Ukj4k ^cRu#q!aƮ#j'0A5ժm[eMv5Pp5PeeMa<²[j<ֲj k/VW1–5Ie }}VZTRskY#=ne~Xвf_Բffe_!T}lziՆ5_ #]5f=!wȾ(-6aJxM.35t;|o ƀcE6q#N4$lh9vXz 3_Oi|si[DY8 6{obxdjhr^:;Ωsr~zr+:Nd!ِ[ *|B?/ #:+aC<2XI `'u\'H@]@%I,vÞw(܃ELeùd9vO_j jN;A'̓ā5Z]*`'-c$9w>M"k9  dA5{^O24&NYh3.)ȟ-0o׹r9|r{sVµb1n^daY.;O>d2N{젋o[6c)f-)5P#YS_sO`[maq;*~w﹡8ɆgJa"dp:8(smLF`ľ|M"fe_歷bxL* 83qA.Ňb;c@wa SXƞr%t3ΑllSNLC& yg7>4]HZ~z.B==e B5><>MuH,25Y@y\ ncpc zM%^ if`N<-2 k" AvC=vrKP:ˢsc5nʒ+ؐ?*7V"h ^v2hWj$XI^9D)hXr+۱;rV8a*Qu* 'Wy|%":i26ܴ)Wym0 O^TBv`Q'\Z0va#kͲӁPHWק(dոܮ۹س;솴ѥ^ora~>"㾉VXQ.ўhu]):?\~zw-e\'>*De @-SpMd!xOm۴nfq|Q}sgu

C*dA:S^_ nV J;͙|Xsj C$NHTJW`O,LJ*Y^.,R/l-"͙H-l@nZ?c44g SDW3ַQA`ië^TzzՓ$erpaVGy1eJ*vȇпP,$F4PG ijڻvstE;%P(T t唊 BK7wK<$6i:?9k?C@m( "k'9ht`oeeNslPp /roN[ [h۴eN ݏ;: \il-q <0[PV}ޒ \g.@'Z}J0uM`l N/. УޱO m =t4#ݺ@<<^46TYpVf'7F H,x7w\h.R{ǯ^1t%=qj+*d|"أ)A m΁^4$!`V"ౡonS^z>yI1Bjړ0Y,k

\MpkJlQnCoh%πnv9CW#Zvݒ]t IK |XZ]1=9o|W89:{v~wZqhp|wsZ[%8yfwQ믁HƏ\L?2 (BW w1 ˿E?6(-!C'rB =#K3V?&B0wsz$(1([A.3sBFC;U2u?^q<[][ǭW2 M^,zz?4,¸w7P^}V!(ѨcKko!#8Bf0 p+K4qo]O$$"H"؍g'D>p^ tBc#h vN[.wdB 5Ҩ;EN*@q1\F+jY(a;r<( ew'PČ"(erfICfptxrJ[eh,Q^FnX)\BNWh~+:6`;YwmEe|9(!L,gWkDLQrPw,6 ʀ8YwDs&;YuVjh~GX+6𑂳gǭY87zD H^#II8p{)4=z t9O*$[R3lUI6-FUL.lNc% eevrK᎒1pRP2{qJK/XU>{yT\zQ<.1U %ћV Mݪף{=}[ )pUSpFL67I\; ߗ_ȣ&ZO*?8֬xsh|ɊmOIX{ބQ~PkN3]]*b'I !tҟ4|c 9j-:+Ge4Zr؈d J`#V%TSk`5YXUj<ʙYܱΑ,g-R.V[b'}f4cŢ0>/Fk*Ä%d@EjHN(@tw/KrL>d"^΢5}ȗcȔkm((#;8CXtr+,6G#sA rϣm|Yh--di/-:jĽh+̖2UǬ3-J3Hf 3 >' M5+41 8?sZ|NZkK)WwwOZ器I Affl=ÔVh$CꧩJ!q!KB!t=門 SS1 4*eG=A!B\R%x4fY ț#e n 4۲}5qEoX?T*j-O}r;{&F O#ŅfnMս f'͛{4xҖܬgѐfz?'(g9f=uʍrm/`EGxKI1ec-pM|ܕQy$Ə7C/Kx~փ!Ҕ y{!D(")p@۰T}[[49{+l^JA1GbFP[b&PmpF'4{Q f2X٤ BJN}ܸb.:KREkCC4:A&B^ɗ2 F^Ts=ۀh2-Qi «( MB1RXwBi2NTf揫-Gho2ItцۭvwGNУzթEwT b$|UՇ!什w0](zJ|?ZRjU|!C)U)UB@Zv&'뷳ڞ\4K|U Xǭ`dYUїV~_|Ej]1>@-^Hdu_}cO,6f}(-.YWt@X)p5՟ӂN|os64ʱ^-d'v//֩qEeLR?va\zxXTbtvss+7oHVc>$"^{`W|$fPW#8APQV# 46f'W8S ǯ{E9лcJ^4r{wj;[*dI>t#WVQRdZy'*:AZ +:{L9j5NpG]+Dؽf NL)JU KHLF{|eݓ87aϭ47'|Cws+Te}-rvq/{w1X_pr#rW+u(3Q̕;JXC{iK{īq z}tnJ <ЏQ/ .3|Up:Jk%PR^))]l*ñy{]R9Z/_0*$O-GytB㻭WޮߚzwK:nV?A OXXPqP)~F֋׷.tݶ.d;1!M$emUky\΋r^yaJmS7f?Ζ) &/pHW>f {!,zGݳ0Sz|Mm19Y@'Lj*Σ d01DQmDEЄg!K!93*G8sJh[\E6>v%x< :iL';+!ye3r͵Z)#zZ:F>8pf \ su N:C[Y]O30(Vqf4+#`v YA?klB,`;tn'(9y?l/ȲVY)p)\U,:Y 4&V{9v6̬x5ir\mS05IДpF]7dlMxbS"wSi2#"KAOa&w5 b/'4x%C) Cvԃw!@*pr3vXt:]c#h^` +r#|_E>_/+ZjS}X­ȝ\7qv;ۻXt ;wj!t^0$7a0Lw"zm `(W?Ȁ%BF*Kׂhj;K|)b>(idqP~ HSy<jPPuwtsvo;f[8rUNUif#@Y[UE@#(HI]=fb&*A(2j"ŮG_x3*FXw6KF=^ JO6xGw_m%#q@ǖHx;0'U N5D:gN&sNˠ8wON#HJlaꚮM"T&@̋RPiOZ쉢5.^vw~. xq2 yuUa Ph s}# M8V-2@h) 9E]OkÕ ^p2{n׸kWx7"]S9ؘ\c8y.JX,Yw@Dh &Hj(\;4-xbY ")VwPBN81hqKECayV+fW*/\#&lDs?w=`f0{$oSftf“_&*N:E*5l.€D:$ g>:0Fd cRV-O48*bZJ78ʑ6y"'TQΏ CqE:06QEd<ibp_|xWw!]oؼ͆_YmeYQ<Hm2ė$!a0(V(lkeuo4}vWn3#v>rn/ږFLg}abmr(wtECU[@ X.(oCX]h[ya$k 4Cbd5!3g&"k_S0cۘE!mmF[gp7D7&X6n+eed#:֑x1anmT[/ QE t}Ѝ6'ca8+u;,q~TRƎvI%;.qIy٪ o^GQE[ʊc]v"S|;Wǣ?GhLX".;ksan=#j˿s>#(2_}>a wԿnU lLYuWnb:sݛ CUdENQ )FOvI6%'[8.P{ZJuhzTrzD; B>'&]dshʣ>ɬOQ`O1LHL <dn2 iR@Rt+`&ƺ4=p|wonN]{t;_L4m}ڎ=KM }SeTy BpH"w[ ol~TӨ)cl4FAEݑӚB-CQ YZ{$Cx 20 wau:xa\$EmD+ !D^ѽ C!pa R"z¼b.R%q6LoҩhJ CNX7B7ot$Y.?mw<@ư&bYhx#?ȄFlx>^'ߍ ݳӽvK/g!:8VF_a ODfbGډ)(C\YwN)j7o8OkV&B"g-fv/3MaY5a>+:6mXvqf244{uY,Oa#'ʍt݇a꒲`31c Jl$<9xڙ86#&Pũ X[kNm&_5lo;e'<{ŽݻwH3`jbSa } Kw96q9LvwV)3z WՓ|ҋ #3S,qaOӝddvS|F"ḃ3ۧ{C DQ.Zb`vySޙNHf~?a$cJ8t?)f2|-T.AG˿NP u2K63&sO$u' OC$kgqaSN%c}=yKiRı^$F<;.PQkS!"LFEޟwG`~vijBt@NG2Kgvk,1q]O&R)toн.b0:=vw׹ Kε׹)/$?]2x:2`nj ,Þ}|`4|a&BWwˮhw$ZDqę MJ[S4{ ~K |aAic(c&m̞LFYm;J0xq G 36aƋ&Ḽ s;&HбԈ*6MeF 2J!\sγ!OQ0YwF? t\[b~1G$<F1gvNgW'5lp~Buc+Rm;]>ȾxZ*)fahްCu|5m8llY(6<MArFXE*mzVyR^/ +Ph ),b !c)ńRePg}dz;΁@Y]T'_ژ6*HuWU!g NXW}sAA}R J6:c>.=c^is 7a1@'i'Pu@pw v^/r3Za?;kWǧΎssz{Lsr~ mˣMgHa8Qc=3Rh02n]Mnki(k4Xe֜F2Û>tzk'Ny_Wo ?jR.Tj[;ܮ5;Hjg7gM&˜z u^rЄ= }:hS3ߏ$\k:+G~B$Ē2Nx`4 P!5R⬚^paS˼ uՕ^GkwUdr2¦ *@ҿ=.ԀC ek:BEK8L@qoʇOħsHŮi 91 XzC[`h!*F3Vvtйl.!Z߇9ĂNz\ހ>yv'h)Lڵ^86\z f0H@:8JSN|P.ʭiKdQ^EK (`T44HW.y[9J Q baxy^k(~w_idt %[BIt(qNѲ%xv>9#=G?{de %,Kj .]iV$3)E 8c Pi]ff9ie2 $=.פ?OWh+ WEf O0LDơeG[-K(O&')(sJ؇/Et6FcЯbTӰp pϙTYDd *#f@[>48#Bv ᾄqfe<%L`#uKe!½wSMȻn7k労&'V腉ZR#5LJ1 '>ơh `Tu Vi6 搟[r-ݍ`d#M Uޣ#Ge.-6M'ʍ;hذe˕el [ʹx/ILG._ѻf$f[aU*@WҨ=Ct g4ْO=nZOdtK]%GX$Mi4xa r{M<29!Eo(#.?@Ev!<\ 9]1Ҡ@@ͲkU޾~a?> "\M H\YvQ%:ô9*S7*|"ROƃB BLq<+(IA5R.|TUd4y~Y}đ, DCK\:y $a"=zD"@~%)QX&2rկ7/FK]ů 05 ՁlVu7vGF_W}:-OIR]fQ uᓅ`dRQ7@vo[k}j HG*Cwcbm^YCns)#b br7($N_z.S!\hϲTYoqWll9[ݼOx$ck_M|?a8fQODQᛅYjm[oc {߿4 >ˏc[2+=zX@ԭo![>f膣J3\]ܽƵ2rX6w4rO\jd:tko&ϣ &:NԪ? O#&8gcC . KF"'\z}ũܕ~ È4 Y+bEanRYe+ ƲlY6,~Œ2cq4z}4-!8kr/+J?5t2fϣΥ~;`ߚwTGdk&Zx4ks.^j^_! J1ӥ~{&O[5 vS?][yi#ĉ{`'SZn8`ny Q~}BPz&jM*b17n⻯A#ڿh|TUJ9C!:͍7JR?D(rL ^k?kD ^D G5^cbH|uV`E$wJ%+:pQCv9 v):0]:@ bz>F#%t\QW9t0+cE\=)ݩeFPLSI++[J V+}B"W\z&_%d&418p+N2Q(.B"%36(%A_=y6`nǜLDR'4Z:@fyPᅒcWAR)ㇾBC_\jQ26~ZbxbCM1. njzЂ32sƚ96XSL30vQ2uꁆWKUtKԚ|Ti'olp=r sbգCǾWiobH$ff9Ł5UY.ߒ{vaG\z$aG ZA=Uuc_!'"2) [+77] ) $!{ؠWHَVHQhum>SV>G9}HG#=&&Ō`p/S7H*L$8UB(vF@H,ciZS6RK;^%ȋl&LeHRYvpUIXs$P5:U(t1֎\`M0~M_gu# R E`Vv+@~:L];Ce1zD7Waіȅ S@mI 뺤ǟTjeve@@?2|Qd Ä(B1 " L+<ġ]0Q8j ۚеpNww!02?!JHi,|#bnؙ%ͬI@ y hDd} f`/}3]yʓHܬw9\(BH%7Fnؾ3OMX3D V6hЏ[{|z&{c\~A(q^W7 tt&aҮJУx6bc|Ip(cVnIYؐ20t$Yǐ&z@NYG&ܽDxϻC6RKl*R!L5^l /A #ͦF;=mf=7oQ 7J ],jz^ټiFJk>yDa&̘ |CA>s^;rLHE).vj)}p6HZPOBA޸'̢L'M?>D6(IXG=f*栳 3wK؋|0Cī@K|JEFJu+5]'ˑЖ_8TIv ʗu$щ+BO%rqP Ĕh֠h%% owI)H?$ӆzLj ĠrmOy H";5ܮ' L-NgŎAx%SlɄlEΓo+8}g%ub&ٔ8:zb a47e$t9Uŀ8,LJo%qx1S"3`aI&2FOHQI E n$xD)Pc4 P 'PFD$Cm,Ui7e ˤ} xRtEOr'_eLi[ui }V j7V7F1wUcw$v˻ ܛ;-旗\]ŷ%7+N<Ƥx4„E=Z$HZ.iyi4$fE*ѵşLuP/iuRk_Pf=+xIEoFF>$:( ѓքiB1G%FgiYu 3r KSƃh &2.OZr&M2Vm&*)}/ߧ7f5i*KeٹigO!2 0$倲lϙ9j%dDK)`K_DJ؀&hbH/K#nLA[ ̚fdz V4Ah='tb؝$<G*f{8&rG#[&pFVNBF5 ,aLJJQV-QR=$fӋ'e) alNRI=jN$Nqv0IXC&P-L3n o2N85ҤW7R$Lf߰թXXۢe%RMnm&Sk2I xg 4gL&ȹ@s跐etND%+1-s ͒eFSEF|JPA3ݺ gK"|Ae#|; oG{%+$Jުu[ixK5p>w'ḱ Su9E:=SnK.ZY%]2X] ]fqG+aI%XZۂT{0($ \ 9W8M^1YAE٬ j:/83=i^oLЋzWFW.K!Dģ;OpYԄ燁]#q(;Eir* ? t`MyoODsєE n#(>Ѯè? exCt`u//ңtʃ82ǃezrx77B, ma'g64U{Qu#RY}m ,`!@jy$Bib 7Vԟx=!:hfQ<;QH8a>bPA#g-DlVCG=Yȓ˷{cg&w@L -w4^DR#7D#0eza# mW|ru!Fn {3śF;-mZdFO])b.veMY'Ͻ.,\"}p *q7<X(#p;{9;o giT\[FFp,0 t]3fĐᓀ29wg,J{DN:^cӅkD1qi_N{b'6U%ȚFnG-;|x oh 7 bv_@OToةVE2=]7tGrv(ts覄Ђ+Ge&0q±hƐjGgb6'ލJ׶6Ov|nS_.*'{}4XZNGHq$bc7XR95:i{(>óbO0X) NAA?͙VZf쿚/.:[Uܣ? (jZ2CwD:䔔ljJSR z _]>ӛByAښl[Ays'k|1o'?Ћt$U35Hcp>VA;Yo0;ɳwb}5ׁW9j۸{ =m eD3@lRc3FF Os7B2 Gtݹk1{WaQqGDp+c sAY+RE4Y9GAF3ṕW)b0b@En\Rt8e2Š{CgPQ00ԷS6f z]&3HM $ U\.D}M.aC CEI%vǃ<[L5ޏ?Y N\C3F.+vc9yT`ˀxKµ"Yp6v}8!uAs#/|v,,\fR:&a aeb 2!HE3I\<mp`މq(K N cal\1#GfYDcyFU4HU4G7,MQfk+ =_)VTjԬOl^'r:Kns47| 1z+;O1ad>C"5S\Ti. T SO]%ʛ>ձ>.q7TgXu`j<v;a( eGM]U݁1yFհM^ꠗF*g3tmJs*Uhj+Y':y!KS*QΦIL`^F)LSkR΃$TJa@#S!8z@hM ;b 8erwnl܄Ԥoe%>4dMt> q)ʑ1v;?8t;uu@w1 bw;7lwvnz706'ۻ{gg{핝/^~_?iO~*.[,[xDV2r-y)t QX(ßbS=D1K0i8<7+lEj2nY$f4y_F>|}la''V9Hdw7'v̬ yL2ló &. ji 3`0Ћz^gJ$q]+_\>pq tr^VR wS]5eSzG=o@=C$ "WR*]{#|_ON@6z7GMC24BhBF2J:!1acN8Nvl?Tz##2p>ֺ ."/#z۰;#0ZpXu~ vj8 M9ڰZEOջ0C&*Tx6\5%QmkԛSLqrS?D@e&`,J|۴m{}Sij980QJ.`býBLJƈ_lù{I)%cO6ZJ8yGLKKOL`,VcNM3ԚcNw#Ej2~/cZ-hW+RLN.A~Xy{z@ÑXsD a`E=r^ɬdvYZZ/Ovޘ˄SVpJB;'juV藢3`ثYm=<ӈ dp!GqCiFj ydѶzCRO!)uF=;E_W}>}^p|I"h/3 ,cm#)W.cfg@pzKaڇ6Mp *6bik;qpO0Fr "a| ^g K߻½6cҊC1gx?gt+ @e(<:D;U!%I{w Ly~N\jv(VcT%{1 sxBa&"i+A1sF>z\Ʉ)C Iħ ȠAC U#T>a.{G>r$}ΦZh%#ILd~A$N}WA *X a$RVhΡZŸ;9>=&P Nvǿϛ [ JjHk=@C4 ,'J,>!eUpvY):>8Y#j E܆RYހG /y,`3U(}@j=*cI>ߜ^EGvgQ=m 3 閌$R#Q=jiD uj9L0zL4UWC4'=!򾝏`Q=ٍƖj(r&h/֏I>_%BI&v|1ї]W.CQAJ^+>FQQzi%K٫F LtIt,*[̿`k䲦t"]m N*q˱JAcy,Š]*1~̗&I=Ih0N{. 4~''ױ6P@A3·6 Q$G7bzY?q>)o=ch`Q<]IAOT旀k`J ~TOr4h˜ia^7E~׏I>1 RO>RhB~5&3g((0H0gC *\Dk/Ƴ~ԕgxYGdWRd: Y6o 0_gY)&BX0֛zC"H w՘cb~6$J`Й)]fZoKR?' ~#kUSǛO2WFEՓ4qc EՓ|cz|1z>^wL'G_Wr!LoF^Ekv v>+̟y7K$|1zRf`fDT5uj/ƳD=?l+˓VIJH'+RFEW-Փ|Kî~|BQ=?voZ_gl@*.1jN5#kyjY ծy0񬱔h94(hBKU#krGV%%& dzR e:H+1,)ZCsY`) iҒRlb& 22?쮍 b̞<4pX P:H"@ZѬMiq|5M} I>_#gJ>'?gGg'`h)9Rқb<^Lks&T$钌hB~a0_gLPP_|B;^5Yc)фLv|1m$d= cq1"_D]֣*SJ+DQ=P0|1zR5h CZoz׏I>HKuy|"Q4!n3RƳ~TOt~gAsI>_ϰDm/Ƴ~TOAğЊ[-0fJ g᭭Ж`[)iY{Nft&'J398S,x&DɉGr2j| 'Fz&#'Mg9yl8Ss{Cwo{y$z3_-?M^ dA)"ܛG?|ȆQgK{_pb]aWx1:C^lreۚTy[ 'JWOKXEBYrBP_Jhox,ȡ4ý-^X̓)E[+EOZ=-o%00%$5Iv5 JJEб?:0g. !g?IdLqֻ4$3ۼVAo yԆ9Hׁ=ef M|vϷp[#wr KH-Sv-g3d[Pda.aH~آk6$$,`MB+gD Q-Y."A|l='Ґ"J 1?XH'!pF?r']A26n< F}\Ehv5jW^m I/d"C@˚PtK#2QY>ە2mVߴ頉zrM0盾S:^x"_e.>k+Fch!EnMfzH.UHs 0eчbsv|_3@p`{Z⚳ 0TnMp(a AFa-:NCGx|u$V0ɻ>/ye/_u=-"vM[պ^Q}Τh+J8\@w"@&*kͣbrɥx…C7Ȼ Q C&v8#B~1mf{ !8=9ʒb2Gc 4.WU[ۑqWK+ ^ܲ~wT"cBG|dp1Z+3ыH!p*]εT(uTo F$|{$g#fҞ*?r9K^(kM/TbVRkOnQ'N A ܂dܡ,GBة&b\bHY# BWý, %9_#iH5):̋>?'SW)#mYۄ,tދ!!E ;ZPa0.FHiU2axyU׮F, NW~K4I85BWU-40O۴E "_Z` zɺ eU+T_' spIA#Іa6 W,SdfHZG q a8MtdWYI;@"ݱ+u|@lq,Ua턬Fա gÃfX)ߋ2|I#3 q)DX)!QJ~$n| R"R,QZLT\:Bhh9J ڱnnLOxV buߒT] bM!0l]RDŃ)2p UTi.*JAcNM3OOB-cO;NX,e(G+Ey &a#*ɞ/p/k(|i ]y$ 8R1`p%ż `*n+JpRglڅyU < 5},9tLfW9u} HT-n@3Q8y!w[e:z 4e74.r[ ~MEtd׹0B3ϵJ=4mDBRrIKK Hbfu~_S>XFr jɣ|9Nϟ92Ϟ\g0N` vrB<#> @W`&x1Є 5andHB`Dб9h̼_",f%TP Y; ?jf/) m2>u_B! _ӜnÙG핟f47eS B bGJ%O~J`|Smg3E>#D(EإO BP ځ9?zFIcSC3z>myQOS99"n BT{Jߍ|:B;i0al(:&.a`W6o)vUr m#52g.g\"zŧ]|Eb6.br,mjE ]QJqҢGa5d/LMlDB_pr<ᖎ20++50C S5a=DJyج7h0q-sL`(3>9;} 55X#gkf?PS[<`.gA-B1Cf}tdHfڥc&}$eFPP[lB剣0`8_Nc8An )"(@|\)`{% ss3H E(,(iDP+rq޶{4"}A7.rʶ@\e#ò'dXdNI~ǧAd r'W )`ٰg{$ f>e g7 8)3?)R#o1ӑd(5*~5)Tu"\Or(RY/cjElFEpX1JB@&onwR I6t"4Qdtl?p}4gi-)"`!"䤗w2j}$JUru\oea̺CC뛾E.Yͫ‰N/Ommhڥ[:;77{#Ub6QGCa(*:0OŒ 32uc2 d8a[N_m{#btQ)V>E+.}T@;+#"Ż8dlΟY_*-*iɒ[Γ2"g AITQ9*x:LLO*ˀ%5imUaP}Ek Y(?mle=-1F{@QѪo- "ҝPC?hBo9xEY^;٣o4o+ N0L"Zf#[u/kXE8xА>aV'$aSB+c֠x ?M+IaDU 3 ZP;DB YGrrc2J\.2TFfТ:t/|ƊBl<׳00S9VPeU"3[ ^>8L@f%931hˢn;:NۮS8vΥeƇ"P4př<G%o}q.h)(Nab. `|TJqc]tcp*kյ5 `}u CX9{oGl{eiE(\!oqT^@,rˬJ1K(/:+fFZbBwaU5?5u| [;׃|{TgU( Exd@dJf`;q)C)c6ErO]/] ݱ; +W+[8㱦)9;_ֈ+FyIeܲ?;od݅铴⑶3ŢJLK0.e$d{/lXL/A$OSlqbkUE2 e-خGg +4o]+ } X`s슡O Z1)Cրu8#3"ϴ;h@"VzDQ]$5kYh`j6u36ԈF8a rs;M¬;&F%y3qg% a;"Bl]*q$ݜNSu5پl;;cuq#hjb@<'kƥ\5VqǛ1m ohU\$*R(s8jk,V~gs4CS:/19 Xݩa+?jCj : \FEGvWj\Axj'c'Sg[IK{uސ{EM4|jOClLVÚ$B&vFI[>m9V朵dD՘kRTbQZ{S8 ҩ_"Pː$`*L5,xvg'QdF8?f3KO U+4MڟPy6 o3NTsl"9G٢X+5#׮H yxe6` YG2/@׀D$ Kc1ѭEY/&A%RJ^6L]-1;U{tw{hN7r %7(YJVgOV3zl2~\XR?mIQÿyNwvq~ w0>:,%#:7M3H^XTw:<8Ix%m/W]i:DEޙ|q>n ?_ANݵR難duf>̽ZCO1U4q 5_[`ǭA=a >^GD4F~MYV(^V%N5[b2;Bi ۙR+g_ۄ^oimQݶhջ-k^x->HXxmOnV6fKZg$1E@aO/XζdbsYt+b}'j}q -9^ds0DnyЃq&Y>]a0G{PĘUƗaBCΧ0U687:"q=c-yjrv!Ja\I?]t5 ^nq|G0"~$VVɀJU斸u#Ҥw¸u V"EKl926|]'T A-dxmZ{x{nאh[*'iAˆ}\ mcǀ]U.JYEg>;LzjK,HI\wxӅm@|T-(< #&ņ[ĵg3":X(YwGsF{ bȧ\B>!;!J|$Ǯ(fz!"(B|=%)]AL)F8oDx&W "\"2el2"}=1]G*a\x!_B;7qY(aoTD7KHf'3/e!#4_Ptua! "Y$أ? ŕ5!x2̣Yuñe '`"/Z,HRuFDxYdA0|X"I7 JȤT*u$M* u˯<gejF֢k}]\Q9e"կl>8d'kޤ /)'4l|&X,x=,4FbkODx̞y&Igƨg>܄ Q[qva[3DGX2kbrG'~rq_#aL/~JJ$#(%Cur>0/ԫu>hV:PNfCk]orW*8^'=SC(fDR晌9р0t^~ӕ3O4 Wq,]Gzn%iHr &2'†.'#HK}3qȚ]$K Hl'LL m<`W/ q)B4.H`_zhe0!id*iaHo|ϡ#@w҉ F݇ޝSU] JWu||䍁7[^Äk=X6;'W|`J=^5C玑` 1_`>c7 {J^.rnG Z䆄ua&gE9 pSc^=V%QBVG.o֞Rx56Q,EbQ~V,zL&=MZ I#)uEMT9QݴT%PũP:Oq8z"1,s43\m R1=Zlq$Pd1d O+bjOWCv[ ܍?NojjfPF)0i⍳2Ƅzj*c~4f# ,aejA$I lʐўݢ蝘WmC =Pp\D (dtJ(aJ=G^kY-:Nq֏f ZG(2@]w)Űc MG`.Yx(4j~ 84#8 u2'\gjGPPv= x ETs !sX_N#Ó:>#^ 3/Bܬ׾ 'ݾY~E6zeaQȰE%¶Bl|υ?_IϫeE8f'ЏWsϟmhl_6lf mL=4lAWbgĻVF20K4K?H*tw=>]C}4izswy ѢVN1-RRdEgS$Z7DㄧkhKj?D;P;tЎFV-bNp w^_C`/_ћڎx\ϟgH IluL%"Klk0a7X7I7 /Ywzztnީ@bbT>p;U/!@k%BȤ 5fLP܈t xU`m΀*OdNN_*+ijÕsQbuzA+A;b(zW. 802 Pe7ddh= P x^ xt[-AHcW@ !o @["#j9t]?" M-bEwN47,E~E S@~&\2tB2J42Y+S&^W]hb(>tpB) ޞ +ds'y1Dӑ+QB `v˦] aш75ۨFm7\EckƑz0AZg;ZuIk-q-Sk~=L)\ޡOi C6J;Ǎ]P}78LbCye )1DcHo[ʋtxb\Iԛd'l34oZTszU!=v_ҫBwCIR+dF. UpDZ\#W{F%B5nrͺK\%7mxݐm+RlrHByw %`%B%B])0ݥ "o}꒪EGQ0wݴLC;&#4Fڿ|3Qyxf%8i}&AJwH85) V=mJ9Y%ib":eZIt!!SG:S3d"LJ})Q?-uF)4tJlǡOR G(c3̢f?'P Ja|5R$MH6QJa3Rؙ(mJQlhXl2OA}Mk6d^F8. G_DZ.GU{pe3\sFޥЮS.i"c_TQTO(%i}9zwvﴵ|=4Õaeڍt 6qRُ˿~^ٍXsVkz KsJ%raHDH)ñlfIlH"+fÛapoB JZMoT߽ BD}Nt u۟v ưf ^l.xNҒ23;Yc|.l\cf%>RGNDaUBGGTKKiFJɍV @e&D bٔW&Bk%6_5ZdmExm1jbqcRa3YW+)omg^> H@Oh^V*OeExj5x:cVMc?L*`B僳s# p?C/Np})H1hLF+'18* Rt\=H,4u1azJ:zl'L3yy(N8N.Ó}xG#W}o a.L;G#xs_^&8`3CdC@qyҁѤ=(|r 8lw5i@$zVٺJ9,(̾?l>,f}΢[0'Qe0P?߲Q' YuFx]Mhdž.|N&*Tm55wCtwU8G L\^6baӕhZTLMCttG~Bt%Tx/-uqGXqS&V%PC˧ OI*)ƨSZ,>|#o?Wm>Z5463liz)>:}3,}n$i_ vvVj6'pb?ݍ ^ZaV-7'O &Cy-dh< ދ!4x{ib(\sRxv; mLbh Ld\y%Y+Y d%bWc.(W ~ZgG_?#Th2Ppy+EjstA_!$t:㎊L;ƛBס,V"8ZjcqnTȦ'y1!/#GZDtR1tn|dFN{WZkjУ:p~~>>9Q kls BچZKBDɳ6JǠނm Ǩq?vc)5̓}vxKRxJg{)%S}_Ƿ{)`9V&fZw=7',  h~(΃l޷ <X W"Xw3@Rڣd|9[Y[bUiSCX"vbְ'ʟr3מ^뜧@O/r?SQB %qɨqRՕϫҒ5 Qbq2?uilWRG$VJLܔNX<1'UFF('cЎLQY,8j3m)z14xoo~>= By<@yD,E'}H&clf/4k,?ŏ?i6XUwE$ܻwQғB0VU>"5f1 AFҗ.9-Uk!%4Kc)l1JP̀W((;ǡC;/]# zsM/dxw&y[_XlEu;[cQw|LR6p 3PV\xX[$Y;>,DnZNg/tՁ8 WЄ 4gRNXJ$Ϟg]؅1S3dˢ=zDЉM_{Ɇ H3sHd'pʝ;Z0Rg#hW^tES86\Ӡ8/h3?]";._w7o :|}A@U5U/^ HeSJ>) %1?]b*2F7a dC3,ĹʱfAșPL.i(C}H?o/#1 $s׋xF+; OͭՐB ZV(6;Cgj Njic@Iɚ9L3H$FpfkGTbE(6-MܖK< p7bvt1hNB *.E]2VvPE zn1e*%KwhA4(Tid ٌȈgt[ˑR`iEݜf:Ͷgx+ceoQ=nVdꃗ@9tȆfTBdeC+I*4?kz;VŦ,L>v+P-_gL\BmoOr)m W|#*ky @85Wė\qMALhC%fg[ tY {KRn金ejCb Cf 8aeuʲh3T :h0jć,c?HE}Fy7Wng X% Wh,.z&]BT }+j)@B8 ck%CSin+`#['jޡ`/ rE( 7@!Xvнm?pa;w^8%gZZ2x|>ZFT}9d88$ 6xG[Ь7t,t)EB[N6q$#O+Äzs O7x{;!}p_nabKxu!uN4AuUO;omi^|DEN=>kPS?~qVW+/ϪbY$Z2i^lErOђ~['uu `>n8UGUV9Ԥ{L|+Arvu_2IJv *h) ϧݦFV/W7Qn<gǛ`XO:/03SS[w՞/9Vܱ{44{#SJ[bDܶ5OE-D/"A>vOq[C{~YwWV}&|TrA68(on_dKy](/ ʸ-LIPwFd>bD#DdiKI, e+Ǡ8s:m5\ ~=bzy Le9ٛi}N2q l%ћ].m"/V)!ڤBV~/w"Xė;ĤZ;MQn3nX*PbwܿLK73 } oWǤe|M5@dӟ9s{P[ Wu)^wMvq 5pz F,C.hp'ƨ l<#OP/]b!uq5ygyhY(L!$ݓ,PChZ˪ t|fr7x7fEm$` 7= ʵ*d ]`)^ݑ8wFP;oJZOؼ OHDNv]]pZ^GW)޲Qѽy"NĽ@ޔR;'_ۏy|>_WbG BM(,+vAS &K#_d&!YdNΈ5wAg[be]L,+c)(16st=eGȝ^O]^5 +wJVG<%6z+Jhd*Jd2+[[,|wrHѴ6d-YyU2+7 3O_.;VVz! g^g>XyJDXY?t`/ ֟}6F-(lˣxplEW~ hP-FXgO+!P<#F"|1CK@kY[[MCqĭdo u:u, wdaтMG)h˒ xTHƏ'b6D Et`:$`0Kctעi%[ۙSz--{|LoohL k%$ȵڸ']9}K'Xd0\<]L2zn iyr6N:l MJO\y8P~EWg8NVAS"sW. PcNxLq1Oz@O+3͕-d%*T$5ö߳lpVV8`Qm쵶 9:k] D[]oY9O$\-&$9R81Gʟ&A,HWVkh:4MHɜd'k#Xjm%qFΤC7] `춨%N##"8FM`Naq,HKvAi ?DT[*NUHmul^;K7_8·~g뭊S-W/rHC$^rOIrL㪋ި0H(p*g"CX+qkyGQ(mrj`n)_1G'f~͖tAgB6q!. Q UZghAQx;-1A)Z:IwP}hے9q(6ͩan` t"%Iߐ]NƯe{||C 7A$XF 1xA#!0HL!ya >RR.`#%~=߯c-m揑Vsb A㤹/Sˏa21jAZ Trr k u~h"އmqsCb_]P@Zo&8MGL*Hi,EϞ&bS:7u9A,{$`Iw. /;=TL"#d:Koc@n(tmGJ͐USv%踍/?{Ƈb3(Xj12)"_B0&XfjɞAggi%p;KX0_<>l * qHB̌&d\~ǿU[wny)rjo8C38/n1E'a,Np߈e}Y8.t{S|_tysQArqz=' z"<)$(Q&h$]1lF.4>eTNҡx}g#->WfY7ά[ R.67W'vʬ.. `[R9۴[- Jj t8coie%na9Gb">W$<@#G\_ΎneJ C$T+ x18X"~QLwAgԃYtDntXTZę$ # u3 PĚXK2c69?y ?K!.rJ 5W9Q>ԁ\qƽwȧ3zSup }9Ն5D?Q0=B_tw~I"R ,R`DOe٦Fw~?2rqI+t=gA]=YUkRujiJ+֢/0IjMtp$/|8ЈȎ l#!D5lOcϭX ˌ*}7dOՉ? ~=,$) _M +tNBaIj1a*LH+"D(9dɳ<.Lnʡ KUEe6vxJQVIAz|@|Í8 XDBIkchMkC'L> iec9UM$乌S^T7(3a,G &oeu^2 )Dx0?قwz΄o7;]j+B:fD:ϗpQ΅R<:$&)J xa"k ` W6ܸB$\sJ(&z".0@ ԢDV0Ա6:D^^iҎ3P,HZKdL:cA0[t~ c>FSD+S}U62,*\ԧP>JrNN lXHayt$>8ml@'npsv:ע-^u' J~@> Es`Jȁ ̥ pΣ44ͱxM@tV|Db\ߙz>,B.OD0@`ŌȆGNRΈ:| 96F>,ČmO]ߊ%&6>nq2Cdd]+W+^l U^=-! ggZwA&>>K(=Bm%#^!`X9,~g>WyTYo:K's#9Ք/.wТ!:ȗ{ EuOO Vd<PVлNF;]7{^(K݂z_PLAwi~iO"dJ,F*'vxk! 5$vK7R&q";ҷk)Ir 2\y!Pr/δN@,!ElgBNdJcN?wJM)/m8l{9h(\|X~Jr|m z5-²Kbݠ 7GVv~Mɡlֆ3Fmt2|mk6\8"pSJz2r7nt5Cc&U]ٱL6*>*#-A3-_LͦdCB@S'|Op\l:C򂖕GGβ_Mjz)^P*j닌Bx’51peQe"Mi2ppiZS'x.?8M"NdSޠPlblhZ7O FgI= QHlF֛D*H{fc7 0Mװ Ew./(ԊX.oʿ(RXAU_+dXh&@/lVC5@^{F84/ql1dˆP!Y+3LX oВŏamaH }K^Y1J[X8NǝJ.XC*|8H0+lL+[%[ QBل^XorYK 6EW2tR98xnK#}̮J&Y}e4U,b,Σ3M*eKOPz/mӳhd\JrI{O_!fBnpFFeړZ"t%Wd K{I>KYC'U`ft8̳e"3 9E k7Q]^EGE/)Vu?&Oxk%t (mP,$ݟs;}QtK}1٬;?ا( rz,t ߪp,ie̖7t@uQ!q. $aL*kcwpHC̤twkX f @^/EȒ[,Rh[|i{#wˊJA;̔ZB;EGjmAGEP=mC}XFZVT;KiZh`P" :=<ky㖐Kʌd@,WKJEUCfC5419cMkV^~">z;YYSw=ngF2WH?Ё VŠITj;g9ov;]h'帡 ʟu]hY4y:HkB;͝*I땿tGEw"ًddI}QR/qrq\KO'ZqRШi-zc `5a1eq$,{^jY1PFyH3-X~&ơ,LO<.¨ ߆Bo֛Q~Kiky+=Eɘ,h W/m֢~렑ɰ(ȷUOcmnI\] A0zWN$)BF}oiWFعaOv* CWת8ERI`fa ";t= P)ТXsP#qO܈>KxpU*}R!@^gܕ)׍ȏLp\f^~˔rFIŋq `9 ܋O{Og~zO;Ϊ)9Nϰ{jڨJ1rBE".w*C QQ|t&y !FܥYz4tHTJWG$F0kd׼Lه$zD 0`Ց_e4Xncyؠ3yG\y#o#WIfKIn?ӕL|jH)7TVRtמBhFrw!9O7îE[G'; kƀCk<$dD%/(V-ǣFFFj8OB!zoܓeL,՚k4]9ƣV_:a#d Wx0QQ_b%'"K}AAmZbb&@CI8 r>1U_sm&|,n/b2u0Mt=Uȸ,R@plZf6V>zKh4۸ЦtD`"#K@4&Nb5{kإMÕSx1T$4M ӯIjT4|Y idJӶH{2Y,*bT(o<igWdE>4'g͊Xj"?S*Mlٻ/ c6߿xV"y6ӷɬlϟʪd)@͛2KA:eR"FeM\Ț^N}t:KKQFXJ $-}E_V}V}5j#ϣ-baaާL+qI)Kjۈj\*#ҡ(<˽r޸GqUh (z7#65^ *L74>Ԙ"߂kg 2wI^a7Τǎȩ;>!eXV 31\Z]J,GG'yR0={7gx Nț=i(fSY \kCWLP^XdsgؠE~BTZG78+FsGUG ~Z -Z\Z Z|gQzM1p|3z`54u2ʽe>눌ᓢBYj6M>\JRYjuq;KI]gNO~R.ߛvn_Cf,>Pjg|mc:KP~j^鸹8u9l_p1O+K7~Q7?]'/N_ڔ&+]|~{}y@GǍCf|gBK7NVWbt}j9S;ڻ;7St ^8 =ApOAo^G<`GP(zYG`j30tWX{L?p1/7k(%ߵΛG;Ϗ!>:m{G~QshJcvZ \j*z/g0߶vy v v*JfubOĻ+Z" ew/n$ߵۍp&zc ){@@v:k0N+oixFA-0PCwc'Ƭ2&XAr]{\苍/Q<$feU FUNa"TTnHr)r=#J qez>#Ɗ \^1\̻[̻L,6P :]6X|a64+”Cx_)1ǭuz\Y-UAii@N+ k(W,OSOE|/4_R+)j\Hi;uun$ՃrEE8na 2ȇ+sۂ/:pFf9A_9N?ngUಥ `à+Ɔ%@?aUUoTs+tOdcPW-cyC%5lRd.0(%aFA05޷U-*G`[L+2Ѹl+: ;:H))1 0Volɇ`ЅzU|#J9 2`4gf$@2%@%$ef+hlI&'wl)/2Lr eCa6- ?W<۝S"Aq 99'tN͉uNV'OE*Ńk(0ѡ J}CqsZaDnSDAr=.,3 D4C63I37wy3W1  VXr-n*\C=7ΙNƳbpݽʩ[qLP +Z!K"ZFmp~MzYI,!~e/` 9ϟDm3>{6],TYd i 8EZ]3%DMrP|g2~[y( reEK.ow3ѕa[,wq1Z"DzʴpCrk%rr)I$~!ӻ&QV"/<^S1z6Khmv Ur9ɲ@շeCrs"} aĮ0dXfwg nUNٜyIcc-MjgjNW[=j?jeQ_ߟ Ȟ~J+T6W˛~x7c+WT,WeƋk꓀d Ed$?Ty2ZDڟQb2+67:z:ZR.jRUQSYOwRS*bT,xh{^&I-oЙ>]^Lkg@Ƚ[Uz0sLaQ [Xɣ҉pw۩EӖ5a\+op A ?E9 R VH?Pk  qX?uF\avRu= }8-F&<uq`,<FDan^sa#pYj9Lx(X~5ys00G࠳sPŁ ˆ;;"nqCpOւ#-QZz<'tigx}wztAw B[kr kEure$MN7 zË3o:"pQ79sث[Ǎ.lawNܲuP/VKmK-ƒYM}k-85k}}=D]>.H ցLh̨pA,ca¹b %\tٶ(FEF%<׵H5KJEuU0i Z}ρa QcxVN1"k Ie)1V0pN0h \`0ntm=E٨P'f6mՓ llE]ŗ('K@z/=} ͯj:i*Ś>? Ud@IMɔ#dhԬd#/L5 wrRAs3/"Qr9F"~V >3مĺu>Z YcL T;+F;>y(zD.xc"8.I;-mm/BL2#܋{'%#/!ko_=Bv?-#dK>foLZpJRDV>V,c؊|LӞPA@AͿt QHH"[ڵrTE+s2Qs HQu68T.A?^۽d[$:k{7۝ +vD3"1OۮsAx;0I͡0& yіyΤJr3y4X!82 8^zS?^#E3Zɬ~ _37 ыVx}D|%>|7Bo:Vs[\\ƗJiS@^9|U.1tc=߇^u@.YyjAn:v@`&[]:w .."'ɐbA8c(pJBl[ͥ٭$oE-esn&vڥ2G[mh3P]V*m2gn݆sw&F\;wszR\o'ud= Iy:'ϛSr~Ļɫ)i38HT<=J@;ZʆЅsW/GQĔ-z ;(bVFJZ;GVamɸQٍva P 0VAOU޼q4_k WJA.P o 3* /1T0;ۅd2;De$:oܹtV<!'ѕwv)bE"M*k;gR,Lrfd/tYŕPӟ,rjP;@}'uF'.MO9 "73{soHE9Ԥ}f?pW+X2 zYc֘VBw i_ #wq&Iʛ"::dJo3=>ܸ*g.DdbE-jD 0!ߣ'n[fhkhc%n^<`D͐;(-*W7tsZaOT0{Ooo_F?y!0MwbGB9I0} vt}1ʱN^>9҆:AGŐd 1IgFB8;,p@AhU-cBsto$UO*t2(]*被XGtp:t&n7񗑎RW:޾~_",z'[;vZ(MƑƛ7]r::G yÉ #[5c4{SH'M$BAʻ~YxrBg'R"nmpk꣱}3Ij[PN&{X2zm|Cצ[(0 5jw&+ Q[?Dc툮X):Oh/1u= ifHsQL~ )y/HrC Qm-Z"_]!XpU5-Rhqx%S~CZd| {VтFǛWC+&25D[QԟR?R\ʥOIZ} Q8J^`l&Wvar񆟥3h -eW+L<.`$Ρs#܂)e[KmS#}\#=8+ueU7NT$QݎSsKQ*uz :RC[:XgO{Oigy -Uwɕ㱸d"P 0q{{O̢lN7Sf$pK#PK\moL^5šYP (M$?4fGy=ʆKjQmX 9K}Q6/om\s rg{O\&N?~~ri{jAI}g}hIΈm7p6DQNv.`7hvcgv3v`D` 6}Iua69* v$ؚ F!B8ZW,>[0eHtjS3^,NFE/m #g*-\o8IȺ̄3WXst冱*aԨp([7Ņ8n>Uf+>UWރ$&O[Nd^hzJҢ^$+F zl,$:fKS۲^}հc72*`H"Q /߈jw3z!7% ҺuE<[9[;fNC`Yhb7ݒ7,Ԗh%[mw1pc0`5] p9錯ܮҚ)!I]*C8QK_&L=+ee;d!/e.M1{rA{/9:&6m R$d}o0I$ 6l>:Ab*ʌ9Tk&}'tTo`=ym>ASj9\\3]ӌ -cV1⪅b1-s}J.C7Z(f~,0+^Wb ~—-$mDBll"}$XݿUE )E,3-"ØfʹאVV\@E9-$rmF{(@M)2c<I[O2EPsuk,`.8Gۊ6ʊ$IZSD›z݌`EQVF΍?Sl.:"[sɱtt"C#o;ig@oPq 9\`SRj -Đ2@av)4YRJvxPC^D١Ķv(ېAO(նj9NAy`n6ٹxnX]A+_c(H@DۚqM04s&:^s*&KbitYjdn`Ϯn;ؐv$9|i& Ku:^AoCx*еRQ3.[x*u.&0ay8]@hoX^ t)8:JkBsEJ,Vdm- ;nGM<FOYrvB!%%D`yi)Y07G7LX|a(B BxkI[how@U9Q::Qh}Gjr an;X3NcGKkrFX{2*;Gy<\rrOyeбrF~\VEÉεSGe4gL.&QPorYOp3b*e_c9e/pEg\ y.t6vR5V /|Ǽe%~GUz q 'cI8)NNKk''fsI$6I0O:ɍ$Ewr,~=w7;;'~F*Q"|Yml R)N1vT8b^,KFROjTJpdJN~-,3BX _ҕIz}؂W`c9ׯMiu7ڤ [6#(վjRGhҽ L+پh?\Ҝ%tNo2;ݏ2랖bn\٩ɓ-|Jةϣ+ٺjbZWBKI ?)oXPQsz߂s.@{ # V 'J2Ncq  jcҺRzOXh[)~gpX'|L4~~ǾF!zKr.K57d?2B;t`ӡ@"v%,a5O ~U xVHXn7Fbvt&= 橵tun<UIG y~8c_V @`bT )3FUT , ޸H d:T_R=xߔH'\F^FbɿBZp$XՄ~D)ۆh4D%O5w"]o{:/o8G{~yO8:`̓fR;75<D{G'.'~DЄ]|<܃ěA]P1$;x} 9:lA _o1@t" e&6(yꇢnbr^й.}ȋIx;9 P`N!!0-m^ ؙy4]g5 @j3“:f"j)RVZ{Y5 {"5ɅAtaUb;lL0B1{=<H?c8 ǹ]$\v+xp-YdYX#|+0 =wnp {#GH 0=Dhmd8jוVBS)b=j!q^,c]o 6  8^XŮOg2p U0y^΂bvz7UWS@nϝ70D8Č{7#CĀ}DBdá?'MLy2TNd;ny}dD[zy!ZA!NM"W0;-J #^'%L ϓ!FBZ1\?bΞ?D5&!ދR9NoŇ-XE!cB7'TӗxR_a&ɏ:=l*rBL=9J:Vr&(-iyKP a@|R(hIS=; VV2?"Ic,D%@JiAdau|T$WO?, ( zkXY#kȜ-MTF.𯑓J%4GN/6qu sitݾ 仅%lr SҲ$ ,(>6YRhJbL/iR_A+;l6Z(='`sSЖbI.4{Аn32(x.Hۼ頇! ;qA0O!"WurQrh>$#NH}%qaƌjyl`/`4^jM[vIllQ e+6pnàywpipm-Ou_.t`i&9O;wbFN $ЁwvMDϑQdE D"Y\ED$Cu3S)`V>,/[~~i)_x&`? B*5Ou&$&Nء׹{@=hQk)H[8j]c@Z@{9q@⤯dܩQ^q+Z#Is h32)|i),o( xi `8b4FF=ṟBә왋34Bٯ ,SK,,ZyeFT/֞J v&c'Rj f!_\K /3\I`;`f`3:j[a=J.RMݳgWM YR}E8&" {( @kxFn ̸KmhG,䵄-Ok ^|p̖w-DbJB3mۜf8Ϭb)&!WH:T%bjq$9٢ڕnx%ԇwP/:l%zg8fXdOnIqqCfūod˳p;AϞQ!V̜%U:(GFE˫oTΑyNc)Ije߱MRi'P ܘ4sx ` nw&)Ar ;fH@!EW+oS8gMP޹dg2&REa̋_Ђ^pp1(o 3{VL0C7C,aO^}8C9$ofӱݑtI?Eٹ+աh]ɀ~㑧f}.g8:fd\9WMR>(J04 6wFL\F?h0YlQY#HƟBdb~͓&xb ]&!-I4% @{Y. 5\^-$d NmŸ[^|.^ßd_ŸoMΣQ[x]?~^UEח2 eZUo !2/\Z..a;2"]'  hޫ=&ކ{!^!P[g0}e\ܕvŗL+1N>œ:] ߼$Ԥ`0“Ie`fž 2w|ܒ> )>5st<ۢsRwp΅xAlKxmg^0C" /i)/?eA-!k@?t*JW ]*?` U5< CkYd:ְdXUS5< t^ $ӱְnx&ӱgv P62kX VLvXJVLrv52k8 l5a*\c ?XVXYyӇu׭З0nb0qak?BV=P6 (WÍU{^58VLv ` LN5VLv;P?tGT~VS5\P\@Sc M'?` UHc Gv1XVc5X{o2k.?a d:*PF֑Abau )# v,XuEv_~XU%q^T г tj]/?` }L5\Zt]J~oe:. a X.ӱ*L *0 t!4p[ְeؔXæ)95!cHr>}r5N)m`qu,sf]#nCM. S#).p+? ; q`Z8V5*Nc  k5 ad8Xá]`hZd:p`XC*L -EK5 XÊU[5|}XC\*ZD~Z~\.'HkK b4XcCCgH$ I:KR\!)n̒+3$,Iq}1KR̐$,I2CRΒgH$ I:KR\!)n̒+3$jDRUWIU7$^$ ~R' ~,EG+uW!^$ ~R' ~,EG+uW!^$ ~R' ~,EG+uW!F?I5'I+ϐ*d,ٯK+ϐ*d,ٯ~"8=NX/D!z 嵁@yS=$(gp"Pv ]eWC )(;ʎBnc !? )}>0r:&|м"ɗ *qTdx^HG?hYNlBG؄|Rә"ⓙ\Z9mB`h:Y.aO 8{e=+hBK r%4^E+]M(MWU+]&`&K^M( ު,).PIooM_Kt#^׽uYj=ԋR Yj#TPBzT*h+W.%${,VN*05"U%){,VM*PƬ\jID6 Ri%K2q{qq43y#-qM}JFڨDl 63ZKh{3lbfs^,/FheVTZ )k/vSPcHq)5^ɺRܾw?mē->ȡF:%õ_CNNe,<ҩ2EWF:+p%Kh%e,ggG+EVjGr ct_ߐ`N=Gx_\نmx6zt4yˇ" _LmYs5 lo*gRuZ0A47$ء"q+!]$=\Oä&(T4O'oZ_<58h Q}; .*wޤg]sX&=ߍRœ߸AJd1O| ʿv[¨raBݫ6A _\ϟ#%·`pp'j9 J5̤p5e,F&nm}arf29K)9Kk]gϢg`fSD>%gP-Õm+Cs6e:gS(xN,Õ)7c=U+?ig@G,Cv2R2d_e]ѫ$4Zf?kFU'kF׌Q,-^y7:eV^S?w 'W ,QzB<5yq-c g]s9ٲx.*bYdD KH 1\ek?g' ].G *҇u1ȵDO|E1W\{]rzrHYcgfFϋNuIlBSL@L[%,$9l)o&ha4+J D3"ћ!Feb_V9.1[7S MX@ (8A[9 3P+Ze z_ԟė;/ !:y˫0ꡏ)f FAg y(WlA7Jt2|Q_?6ǝGmq7?F#*q/uCuMǖDdr6!gл=ey{FBgiX?i(;'T iTM(qw!?'|)ˏ(TdUL5xXW#}гwIZ~>uU򇄒 a?&y3dkG~|qei<;S[t/Fx?a~9^T87Җ4"؛@W|#{tU&>k? U鸦&lAR]\YKY^7(~bd]|Ea KgUwvDYt'0҆^# k#yR_X;(+Tg/R_l'9 ZلYC(iO{:Za9|JR {9^r\okMz^ZZD^ >{L{6{֩W̩}FE7X4%O=tӕ=nQbDVֿ:ȅ>wY*Z5IVTzdJdNtH.ȵ?jJ6 MyP{omNry0UG>:i(R4;#Qo42Hv= n۾ ݺUA@g KL6~׸\#qNGo|qL,uE6hez!. v<B#h8Y{szÆ4t gK~c|}3؁C k TRBL~EW~-%dFTުlU ٔ)qLY)mՠT.U J"KUdVfՒ# ',QKdB){ҡLV0j}#6@~\cLQ1Ȟ?K0@5*k2}o$,r-VJՊ|_ X`MҡwKgY2vUoYۏ/J!l_ zdO9])PcPo^\x Wn?pzd\5ɷ6 WK/sAQۿx DewcIN]is]m\ѵoEϸFVtQ-FXsQn>ouCHp$ o2Dz#JXcm=T93ys oC;K^p(NG.^yv; SĎ3g./P䌊Io⠾+Oޜ@IFKԛ_co|7H'Y-]P K p XuYĽG87tJpG E,xd:b*=9=7x7FwB!}ba>^R-»,bWڹ!O#//닁wZ~$; ]F%!Pfou@ 3 :jV`4` *3 i`wX.:.FZf|e7; Ag𚿇q!^`b@n'ISe؀'#QSR8G-:k_?ix ix|-Pjh9܅CIOG'}l>O8:̓&'vʋnM^qx̓f2Tq8 d-_7ƽfk;:*'~D;lכ]tpՊƻa[Ý8GÀ}PQ_w'6v<ZǍ&<RХɏy )db~P=ދӓ6:}j7ۧxstK(o5N5w-"ؔzN@dק&^ONͣhg=D40"/ۀ,a@~ӶAH8loi4 wf 34jb֌-Á SqU4D}]/%nu;o%)\H? W/4Q:~R{M e&Ǐx`n`)xc٥cV5RfһW5>lȺcƅ"R0 [j`nc~>ZnEg+OH/ 3;WI_iugѸbW 9ҐΎBHS0 ކ GP/ >1?}h(JvT}8nml՛0r|A] LS3*S dc4&㈼:&\\q3&B8'ݖ#4?aJ{6Nց#".=v-2v,ś?2[",m@'**z$R]g \a==g,:X^.AP3& wN˙ Q~3Fh̢Ө=).ϱN3̦}"egUd{F\̛-;O3Y컟Ū $mN Yਮ B]qFB{ PiǡMZbr> kf>}7 `Bi3p'.H_6nBN;˳̀3LS $莦ou: Dc?[j#*X_?vS Otr4n 9c)fcl|x8/Q/+l%T;F!nj'МXyHL֑iWPUS+ [ bPQ^D9 R5#!~ot3ri0nm'nqNR@J1p>o`$\O /eyG)>n?ClSyQ#Y")x+>Ea失ߨ6흷dq)vv D$E8Cj`:6c5nC p| w(t Z6# iO{O{&,E6ۄ AZ2#h}(.sp]h8{U}$#wLwNЗ){K_Ψ)edN ݲO^pWm0 xK"O5|q7 ;=Ӈ,M ?8l06Z]=G+F|9#p 1k8b*gdkrSPuEL`D@ ~J|2|qTqၬBI5CpY: P6'VDeVkh -79xv UV#'QQx-FHn~5 vӬ"t Ht/9tݮ9;~+oJe3Ll0o }ST׊ X\/T"0xp}ѣ-a4EFľGtm=_}QK/{W@M7Wǖ#A6z5X6Æ`SɇZhDXfB1(.,^6VmxD}, V+^ns E7^q%PzF3i[4\Fd/F0Q/ *4NIDU U#DTia% ?t{= v -r)즽ksNM  S'2j=|րIy`/g=")43|;lhԈ G5]LIhu%TTJWROO{oȃ 7%uP=O¤ >H%I3Pp@aG^W, "t/vɣ%Wjӓc٠1G\8|TpJz6|}Η#. FVmy9>ق^c|1B-0sI8Tpʱrx%3k|iU%Eܡ^KF*>۪ i2p[+UR'到;#Wg`BO}%+>/:Q@Qɷ"݂ӰJ}:'e$,@F2N(F`F39fwO 6L"YOmÊκxxAWwm9h{cȽp۳~COvb:`d:vsXPVfCgm +'dD>]6IRVH$'NgLcs{i,Ryh =/ZHdb*GoN-g'Lo ǕۅVIy}GhҡcĽ1嬏'񄙾=tZ ."N`sI;aB_o&J{'&x7* 2UBK䒎37 MQgMѡnD+~d9\NuX"|b%{{\ 6*e5.+/ǒ8(\0"+&,ce KP61,ſ5X*?j- )M(J ǽ}l7zIT?tF'[Q,Z)5uU>{4od=Yw).M𖍭( ċF"n cyLt-SEFNЋ%J3tXgonܔ?iQdܪq6L4VC}&lvӚC) ,V*M&cLRlM^)yI4{WDz|)*_9y1x"-[rEA\{+EN%.ZqY]c  v6.S<>X39Z/"pPPJkzBVFd~o0^TfnQ:OVUQy2܏'*՝^"fQ=KԏcQBbFQ ./lX/%քvݢ"6gJgޒϮ9ubRF%iJzx,ҩlXwk!|ufkmV/Yz*쫡mP5$[Fa^O]`Fk'fyNE&j.|E/T=.*.m=ɼm9 .]FPGA[{4Yʇ0`U˄O262dU \9DUgWa)'!s&*'lhdk oɁnM^8AKxl14wުouJ8&dفH@1Fp1aE_zݓOcl 7D(-ImYw'<^*w7ƚ+zb\EsNk7mOazP~nmia-ntc2iegBm+9;l SMQ[Nd?] kLE̻ =6Uϫ#NyŤ@pQBƇBB<.<]Bl$*6\ IIPK-kZH@ )RX>ԗ{./W$q{Wk塋xм%6DŽc^ˀ|,,Ŧ}Lrx.2H!N'5[^ ~й$p95hQX⻝9U죥xf/{.c,v_-yÉ<2b aXE  =Fn:ľ8Hmq*މGCߌ%vb4|(7f.t%l7J' jWžSjN!@ndwyl]AP7t}틏%`Zm$4@+C˛%&(gQi_xRԕ"NMe{ZP."Pv6Qe,O:`lP)4Ax@E46tOH] 'e%)}e#EoA!Jy6&r+0ZòrcAa8הn+-\>e`AٛFw!v ^c>ӛ)n |ԄIpi)㙀Y]Uw4EHjv{}} {9#IrtYH0ăNܷ:C+Oɼ6QؠS > Z^u nZAQ{S{v;~AV3 (|.*CsIs"mX3<"_NQr <_z^QV@[\9Y@\!Y]28QNӳ%[ցҡD%h[d0{DruLkknëP*i'!/LR2/$ l , z5aR˰ C$j"xxއLLsz W\vhBqc#pA%7v_}G Aq9]K8@TJm.z:wRT]$M}%g֩/BK2Nț^^ z+4c MMn3󰛄$$:|OQiGF@d猄FowU+T73AEzV" V" $P3^k9±mkN@V֔m궼E8QU9 %,Fe{.κ1>ٌ}Yts[`H6$aV/J|~Vv,>m?BwS^DXV}c>r"P5yDn]4M!H3z$ ttmn7Їdnl*+EvFҟrOUsyeDVc%LG:CLm2TY`~LCغL}DH$L4i +Cefck}|O#*AsG< 3!f !^ Odׇ1Nk ux'F0/#TĪ⦰=+'tج\zq'uDC @ix(aֶo6xDOW"?:RkISS8^ڿwuYf8"rt `PHGa=@mgD3"=L0#O1,?dwdp Qr\n1Ɖptw+H[ kixކD2 BLG~R{ hwLxN4ۅrlmh{,71j^H^"Z¼VRwӞ?^ziQ@dkEr  l(Fn2u,9o=^+EXh~Ǎ;(<#'+z{YvB3 HQnăB\{̤5zRPQb3 ;NO2h`s*ֻc`Yy = HƪTžd|FhQC=.ĻfflfSHS948tnHo@wi`й(0s]L㕍K "˫S"IodedicעFqBZ?:*(BԠt @`4we:t =G3'm'z!FpLTºFwB} ;wqHP Q za`2Boh&)/bJ6D^̝HŌ޽mq1cCl'Y("+}âvKݗ3&j$'Jחɇp~08߮jp'#E@ҎvYU-9-& ' PŦu8Ri(G]:7,` Ii!Bw@Q +Fpt(F jD4 O6"ܴ[Е QEE^yQN;"D]J7_%˲Jq&WEm߷/p0O)8H9&ò)M]VL/+~" z1c4mQT ׉_d |!~qZH9Ԕʗjenf9e9T)ftߠW_oGEV v%ɉ"Jv# lV'n./Ieʓ}˩ 2١8㑢70!U'ձP9{zu2]\FOEDp!- VD(tn*˄Ty2eC.7asz:rEƵs"N(*Ik9(VNٌEQQ$% A@#'&Z[ 9'q!k VAadsh]ySh*4^vOl b(Sƨޤ̚9ӱDZ6轲}Mj;Ρ$G + /$vPXTUzɳQHJJ;''r2ڑKy4XF"b]Zě3Ny);WJ 4ڲw~t8~ؼ!(J[AGCFƲHcуkC /{~0ɓh<|~ n\IE'%;V!RNKnLዏeUBT#b g2d&A>ue2f"Y)q|)YN{Sc|d‹` _$e87&r*8,Ρ$dviXYQS[.K"[fF(#Zޘc5ȃV?{&bʗK让5lm6AyA)xc;`% M7zBFKӽVhE 557_q?AN1ژ/iHjb]}Bj@6cs4%,g`d2L>vIݑB"]rEv<e[Q֖vUOL*gh< p۔Ue _S9oOͭP FЕE`EW2a tAd{?.LlLjv"~cGC#U7V *1|3vkAUÔE,:1=PaQ\rP$erK̈b(;zp?7 s.7]Ng.Kّ|IENiذDc_H(&d' jaz /Em{e \l_wzrm%Ѥ A YlыOa3Z! 4u9L#jDa[Msoo Ug[a|GаD*hW^Qdm:h C'Si#Bp~!@A(4xE. #(zea]K\F؜Et9o4?|I\n1{%ay{˛"<>uC$d"%0kɍY9le6!@y8d(r%HӇ5ח7UBxh`bfI Ji;-iRRR$,VYBiM %黷tk4E>jR41TcK9ٿv\H6@A7/IRB9~8] *S.?6cq%ƕgT-`US.䊢 u6dwe/% 7j1_}`cZꃱ$6d.v؏ޑ83hK(ed(Nh+^V{p*DO,$ PўXX/Y;i䕭v f(W^V@$hd6h` ,C7MPӋZq2fN9P]˩ 8{IyxSRa wcsbHt'!<YwXEC 5`Ąhif Eh\k^G"-1RbP@mKM1cL q\+Va-k;"V*H9.޵3>ޟb oboG4~<qآUSA꫉̠up3tFm%ZC-ږ-C*]`Jȑ[JbyB_ӗ<]SΆN!]^Qծd˖/\)\I $5aKk6kln3RW? 0` rp ]^;rPOo7s^iq̓HJȦĦ9`RQ:E&"~c|h$E #$$J"TJeL8{1qQf eŰ?H(ͧi n>LP#I漾}n Grg&a׬xk JhLf.^@qfD2x e#đG+&I4_-E$2CH*h) ;rF=(KO4K|%[1pvc0Bx}GQm 7V\J5@{@7FX4@Xڋ{hLc1j6P= G RNU{% 4 9ɛ8H5Mpm=ZDh> <iw<X瓁_?1 U)˕ SStGVjյʥjeuV[|,Ms~SHB-s&Ѡ?D,5{GQ.VJR~!*f*tv,RO5)h &L*~l禎~j``T `ןХΝ {9pxe!KEyAt{.z|ORNI~6~h4~hJyV|u١;;R;||*"w[ëTծ L:I@o*٭Vaz7_d5[РNW؏I\w" 4?J9NW:0z nm^q԰__-es *9r0h)P6 T_R=۩o]9:k9 p)?bf[2 pd GU$GWl5h6E+X [t7SNNa;ի#| 9>ΉBCv x J.y3K@nTvG~T7>~S/P)?#O>YOnDcL߅<4_,JW6j%<\|M=^㈷*jc&[Q}r㒀Y$[1A7fxpʪ{_81O+f@tb*t&;~R+Շ9;;4{ 0X?x}]$;AJqa7ɁA 2( S; tt:O9=K_q}"zÝ8Cשԫw' ͙X?Q<=>V9LVv2gWtd%Ew o@enI=#aQ1;U_\o;=K{:pDR3~ӞbORUY_ ok[GT*r9eC0p5 75J}UL2>YGWveFfVa%#^2X`0Asis# cyL3Q@_07[?鋟 >:޶S%pʦuZ).zeU:]y% %@Be=Zńl^Df4,7&ߡG~Gtz[;lO[$x#@8n ݾ(bK;\+zoYȥ)?*V. >oAAhWn? bW}_ %KќIO uVX9S3-y$;¯Eg"_ @1 Si峊3I{߹`8ƿ˜L?zgm>}?æoE]I=7[ob̷r/GrY6AahIF•nz!K~E'tR҈wȡ` 8 Ψ~xV>jeXa_+4je,Uǝ ^˕(‚ ^f-(K+4vԾiۓl7'9g< d m3\S(`~rV:2H mot1&bDDښQ|~^^mœуh(y߄2󇌅`r~1 o$z663fh- 4zYʌ_Ξ}KeJmw!ZA[c.-}+}0w;:q O&MҹpJrޡ hZrfͺX4B)qgxZ3 @±-'o@^!)iy]NKP+#h-aP Zr i];|?+(eq4{uf8#9 fGsΟ}#6a|M}f`8w.;.l@LVZ rwyF+b[ݥgLɝޒԃ!W bQ .mݰ GB~,m@y:=,\(煝yFV ոC\95*.+–t/u+N#H?s<}xw,3vMp4bA2MјR;yq|M.7VF䟒.A\ѳΡmu(U;2IY^5)dz?ښ~Rv+3l3l3lc+j 2lgLpV&/Wh7}}?^I/r 撪*YеjKQW,Bh“˖, RJXz].SYR-h 'kye>I HW=gPἚvcf# J]:9_ěaյur8־?|wO:7JDuB{. enuqY 7ң/'Yme?o~m0=jv&ʇ0p s &,9"-;2|+*T [yWH,CbS`ւ@=WwLT37i˃:?@θFX9J2&D} UCĺY&IS.| :}4N8 9jB‰RPr=jc%K >сPǦ .r^h&*H@weCnfpkʛAMnF5m /lXifCLW9VrDSB9Y%{-4i=XxKMm t`1=dyV5HSCFwrz.b.b^$MېOw.KOo-vEpB價Qtd9[b7 7dysôg+ݒ]J*Q$WࡥyRP8ߕirYl\`I`˹t`5B74y Zm*kND` oQ;庝/M1HF.!>fKz8ǷvS'&_FwUz%?hbZcn՞?fo?k߇W\X}"y.Pwު2b:9t椿-JM_16U淉VhThFu,R2)Acf$x'E.Q[X훤R7X9_.U$~Lfiž7AL;CbbwE|2>KV:׊uB?β.pVhz#?m,o=IfQ(#Os@N8wh;jf!U%8:1IFI7!?"+V)"n-Pѓ$REcL2q}ñG+Lå;k JL*aFZ4ouv޵h'wZD*/Ki=L\v ݝ̩v_OD8_OB=?G lhAT&'vem}:h[>GJ,͗(d#v.%+ 7DSb؋vE,ka^X"C îѻ3϶Q Mί2MUg/iu;gL E$t2 K TP NGȻ6HEY@ecG Mȱ|GDDqJS^A89֕@(  qzOhXYj?`?yNB( Jk3sT=v&ǰԇS)J<9@c>>" yXRfl^!ؗ<D~:bg޹<_^| Φm#l;>ecޭ Wg]V!qвfj4L,^a/{rl.{>9Fٶϻ-ر^ x{ͼ zo#7CN$E ^Ofn$m37FC]Pl*Fj̗YT d*6lLZڰk֭C(IL/ 2.C0))zy!!nYqEtD!w= ﳖ j2Xoea h "JzO{E7 ×a񍄕=xܳ0O@d?ӱdԐP`BFD+v6[˘ԝ}-%7zO®0-jRĀBۿaaE`|(7yҫ9a2CC +@(q29Q:N$,7YZ0\H.BAH}TwQgM[fYE~eD,j\/1$ %BEL04\g# rC g" aMxIT(VF@ڹ,pLԕBSp6u 9"Wa!WI_SL;X9 Fm!&/1 N"!rtݢcpH4bΫD7MK +ܽ5Kqӫ m* ^ahfc4j:B)/=vr?q jq=x3#uGj:~<~mq?plE<9w3H<Ƅ󨿕X51,VNwy9p'ѡRa6eYT.0^n?K&m<cZXʑa%ƿ^ .[6sH8'm}yJkDtEtX!=iA^@Ȧ oWVYk# `@ng  -Q %(=Ol}ޜ}iq~-npgffv^2% ~ ߝN|@eex.>˘"a+o.sj!칿އ+^e-N??J[XĘ0f  cN'.3J=nw L}t8Ʀ4EäM]n4trlY>3]p-ڠ=70~&l(g9yvyQ/~Fzy8lOf8mpjÌ5AknQ" P61ѝEr2rf2kv{;h5ǒ H/|(EBz`tRƈ3H/Ҫ/?]=t+8P{;0%Qas4*5 va WrgܽsDU}NKRDRi9r?^ ɝ4gWV2PBxv\-"’S.=&9(;s(>s*{>YO*oc[=$Xx^ڝ yݾCpLLkvib1[*4h $K%]b&DΡsp^K}y2:]o+XaɃXUwQUb2*| p:ta/3W2A ''B"'En8mv!ڽgGֽӄ53vurs:5L3tF00D[ڪhs-!tKwv!UgB=R- &' CžFy0rBLs&t5aqx|6Cx|߹!Laogؙ?Lǫcx^?kJS~wQ Z߬7Kk*~w=Dm55_.p*:\]k?=ո_Q?+ujs"^93 ߏ'Jagr^R L0>zS ǘ'/>b)^W&4],sG[⃰ԍ2HJeQv?%l/:A؝7iĞ8;/ )`0#1ͼ`j[EVb0$.ַ"-iڦH#ir$F3uayt7\ 3{cO,]Gb*l6A{iL,xZmɹ{ T@[}Ji| yr⩨aL'D+uL"tGl1Ph.E)F\:Mx=C{γ<&;ZH%J !d {{IdY>/ EfI5Dž+L=%EςLr"m `ڑTx31Z' %zL?O \BGyg08w.F CWF(UᣴU2Igk~{EQZ%bF r0 ےRB .7A҄2X;U$XoU ,<;Ԁv%ԇPTbZ(& yoVLL'iV-,6(Ӄ4H/p6$⇙=JgۋY`N8HLKMB)&nTa&.reKD (o-dVãF8AnZUHjkZ0(w:!Ua?59@`WKV1!68u}N-aj\8Z+Mra5. Jp*WN] nS76,Ap -] V.Qm0rj{[H*ԖnkF;.34* 8T8[܅>rJ*}&ZU꤃B'M~\H+uy?l0kJCq$M%L:+{OS5{ ZFK زJ BI:)Jg4ݓV.Z $[\f 0=6~! 1HGA]9*@ QtLI/PMf|kGWݘQhy$3 ;:Ad<DQFBa<%hn@(ӈΤ{%t2H#8W*XjD7s00C(^A&O'Yh4*Z["M^$M)se-֪ùQ!`Aaf8_=\BP` N뇭*d>@&HRh ɝK @!B#j؊H q;sQB |S ;˜g[lRShp @|cok"ϼf,8$nl@h< ˍ7g3hum(˲F_L_`|LUw?Px [\v`| Wgr2Yn5yU;~h*w xZrp;B n 9xo)`v%*`׈[%Iyٜ}[whG=.lh&"בъ(-"}Mx՟9N>O]Hngt[rܶgvd`iX>T>Ef+/lL֭xT̈́U6iDzDgRFyRK>ssn7%o=]Y/ۧ5b [0dߖJ]7=I;tm!r ʲ/cS}Tg;B}U2QDd#koVgCg^KnvrD9%ʌ;ΕWhbp#;,կHjb&-:5S*lLY S-T"3PUQeFTߪTLE/ڔ,:W_2\)W`0ఠ0܋҅bsmY3wH!77tZ5eu skc¤@R RnٍRMRsW[嵭 UfΞ:ƺ ,z};*{+;oS钢:_pHˆͪy] uM(2(otlfAj 78 }Ix!!ԄB32R.g{!1Q- ?PyIBaX R K "O>_Ѫ 8,t]X߹=@i:E:>& Ogűg yh(M0ꑅƕJX nbJBR@Oc"ԇF ̈́c2MdV޲> HgtY4J73<9;$9+!2u_u5U{t0\GӫVJdtp:Bvk9h7IY A#tVAeؗךgxd4ʋN  bbH}QE<)*$Rޕoc(i-t @adQaW;葢 CES'ΟTOVi`n鎨iW6& tp,T[eq,qV}*dM%F)Kx=q*H%-͸hJ3/Z}^os22扑W.(KW)~fQ0R+DvT }þ&lofwҌ '' {t&].Zl(Qb](2PRS u*u)xXO^$3\-҇o 8n@D{ )!/μγWlC[7VlbV,Sl~}+ĥ֮<[K8'rbMՓzsZ{MZȶ}8PZQսh^pz-^;6Xp]t/˭=grƣ P*:lkg|U 0J̭?dDNU\qhtWѬ_6OgjAۻw1WY IW"/,br\]'QLKET;>k'5ENI.TXCcԙ8:rPGRq7@i4C^d~+RhL"0Dۑ Tm(b`LU͏;LOW)Wׁ>v(U"^3A\$x5RX˙5ؗ|Ec&ȑ#$D! g.V K4yQθ !N) ] & TJY я\-'iC t;X^=@">y'}zύ[JU(ʥfbߴ.OnD].m~lϾP#>Cl15D53\OH3k|-{sz4lp|Jn?r@PՓQ[Y#ѬUA _HSw0Yqlʻp ,"j=YO< TtbgL%̐LAeׁhݤ ;QNOWrBnn3 OdIyaIeY!W"Cfȭx<ü ;B8]Iiy"L7fDi5oYvPn#6-nw/]mz#/:^T  gbC܈QI`n "n)bF &/1I΅,ǖT#׎K&2fE7:5%c|س`"ar)H2+aa?-CۍJAegbKl-6 &w1 p9  &wY-)bG ID$T"Պs7?@Qm?0ptL|*J:,f$ūca>GF+yт$T Kf+m*.>mnAlKǢGۋ{o6F_#xw~Vi 8A(/iɃ!14LYՋ%-J}7-t4`)< s͑t7":yq\'( @hzqcZw'Bگ昅"r-aRDI1g niU%'|X+ RmװƧj%KzU )gܙk[ĈDlc`޴,Y+TI3(nJʍY ~L-{QO7SvcMq&]K 'nItl߆+\Nj!ฦ M.]´ qC:'%a;| FX(m(I9ZɧQ(ܛqH D<Zi&O;24aV<2N ~'-XQL&!,T\i?ImLȨ5&`cd5rQw/nyӏ #:#}ۑt ;v`Y7KE-}NOٿ%Y7PLl/>[9dD 7% }GY9J9ReӁ*Qy$Wt^70DcLf~wG׉ }GǀdTLj k?Bn#{د]J"Jn=>BUchθn(I33[,*57pEL2>v.e+*v?wPܹzv3ð 30-cAƬ=*R? g~Df9J|>:HE3 )գKV yщUa+fA/o,Zů'`;:P{s,´h P !' s3eCXB(jtu6)lgޜY[E +<‘NO᡼&ѱ$\3o$:]c]8>m VdWT?PmY5ͪሒ1 /Lr)2[f{T\3J*ҬJ-7*h)RCTRe+^I/]) l"̃` Gƺ6wzK<Ҥx) F|0d8 3[s4aK,D?؇ %{y Fm[aaTrb4C<NJ6o+?aϢ8$hGd$S,C} }1oX`9-PvZ08& V Y;AbX̼g/(팵80jx?EW69=Kv ^SI% >IB=7>_ tsT* )Ku]vy>W;]WtSQ*oW6ve0n0J7F'^;M%. } %&}g;\l繟p4P]@L;Ef®h:U˖8j3s"$ܬ_BqA`*4G;hu m Dd,Me=+|j eED8p̊1&zus #8s\9cg K@mԦc8E\+\#^A48{&, y<bX1w?tXƬARMoY=#hWmkDY&h/(By >gt-.nRX*e Y8Pqaפ Īnr u {t HMxSoI1O9ݒ~&so$];8|jԛL`ZPD D+[Ej$:R6pQfc@ƮrVтkumnV͢ѵ~Jnf.k> Vi)2f;"+x\+od"|XwEyXo G~]?}17F RP\/l|Y>M꽸SiygY{=\=;G򃏞R(0AU}5H:GT-OjRa԰;'j&uW:}D|tyyֽG :.ZR5SZ;K!O~&vNOO[ ,忨qU^z^Yu~W?'D5C:SkkB =?\~&Jj5i r^Rg|#`{C{Xszl (hպ3X)Xvٳz*pUL\5ZNx[qE>r~piOx 6DYե;WڏUuDX?~n3I5OZ!޴[;sL h8?^p 8lID%'=9!YR{*\ z/yk:ĝސᰁ_ʍ'ա1a?p_@~R d)B:gg9uMChNmw۫Ѷګ6u=ֵ=QW Wߧޟ^#הvDL,Һ]bN#9~߿p >_KS /:v?'o+ݫxFT ?H[X}u'pYZG ri_<7EY2{n{v ~τ? Zy4iXNVrSxfX(C<-lC8GMTtWAz1_(a}b.dh[W7293\8l%k 5r:`tОztf@,lY+^M&l܌>X#4ð?QS]RrQz;,]r[S]<@XfOU編ɖQCwdA ^q%3w4!)EWW. .nOUJ_4ۜb?4Zn*rx}c4YMw9pȇW dp4׻@;AIed%;g`&=wĕ/F =r<[scXNRwm2 C`nN8lI%a:Z(d5WJfXLs55j5sV 9<a1)52C[#Bgѩi6L 5;bԛ~ JFl)')EH0Icv~^云ԋtd)öW\UEƛ* RwAW%FQ prK3E1X ߞ$%}"sD$v(Y7p{o- s h(2UnKDց!\lV[.FU0#r8 G͌ͫo^عZeN3h1k*xZF4ֱ9zkZR^ء ͌5` O2(NEW`'Y{DÎU[-._X:Tvē'zkSO]j<k Z >ڱ`WAx3Ld?QSMRP:#eݢR?1~5Q0YP<E%.F6f!HϵwE~>>Q)$=*գpUF1|1!h# |)/*mR 'aқ}S,6l [0c}ϽAXp:P@$FPA@1H픨-τ.I! - н֟sn $35z%zQfqd3BL)Eɩ7aX;ewԙxS(tJ4 aDx0 $;_;BEJb*Hn[,P$_O¿^y;!o|D .UN=%eS]*>VŭzC/Q { I<4l.,;żE,_uW0OF[7uXEzXz-j!|ò~>~1^RE=oaE%ꖞrCOO nl`^R.XbWC3U-oU$\UK= wŒonH I54 r/ "ŃzxAqڢdO:| &{w"%"j`KGcQz*=xAw(+=E}kڶU3td*E6}mf-Hﰜݽdyڶ1XS!mFod e_B$15d=(cg`PtƴES kNZVcbs])4~Yt+?h;>ZW_| ,cx+i2JJó>E?gQz>+ZfkQrP>(0Kº +5I rIuR Z[Fb6>7ǡirTVe^TRwEX41a$imQ,>gR(v)?WƜ?͍2,lR,eЭRI ŭ/@YP~T({E;Kwlm(hz.6PGj6b"ۙڙ%ʗ_@Aexgc9`mKgB%~N,TmVL` i?VN֓]2W-=0"GU-&{Fnqu'W[܂WƎ QV'-srFp>Ҕi?LIӂ!ihIU^0Wx >LodkOTR n`-?h`Bv:"))"Fp"zVIS[GC; 6tpl%v8z:[ aph/'?frU˒|Z/DLȜ99ř|]2TpXЉŞsW{cG^H^s "Bbo 5Bzl "BuԉOml{Aut5],Nj&K1@'DR{zhB+P ?nizm_ExRX/l7)fs|G;JbqK%6,}@P^wM'hҟ.%AtWNڵ%I$bZi*kU՗GN^'tyBWx ((HM ϟ^^ɭ59@|j^8^BB0.) zxdbB *fDrIjɪS c^[) 0LunswDawNK3nE=ȟ@A%=)*J4BuIKH{KouIJYFal ^7p)zokR#󢥢h9.A[A#M睦= `W{52\Y+A F^VFQ ֻ+j߿-u?RUM=[ GOyYy+~Jr)=$Tӥ{'/ iI# ?*v+26E/z@Ԝg(^1gU9i~iGJ 0JՎ0r,wXJq|4;vasb"m?HQ>$@̉8 rgg2ga+ H>3 3~nVOm e  ]Bb0'}{E~oRk[ZNXR83, 927:mR!+IyKK m,&&`nϖb"<:/p> ;h&CqHQRvI/Ex5͌*1Q"%idzW]{^m@DM{SΪű+!3do72ȆS%DIRcqߚa싢PS wP٩k@ &o`HX&G‡3YzH%YlɰRz%oFhE. bo2Aq|{`͈OF$c0V5|?# )+'ww@|21qiP}Q#;I!%Kx+/-#\"TaPEFw:~Ѷ2 ~Ho3Gz6R'|@f3'wX,("+omם#oDmKp jm,Za1ΒWv&ߟSwLF;0 FFj:Bhs؆@@;'PE뫕YtM4M^㍮#wckcwBE/ ^o2M G Gv3WX^0W73Lp&G?I/0EsLxQQwW8]$Iáx:J|8t&QY^Jy7)X/%>g؄7zF <>nU (+>#bZZ uǤ̼R/YClf:jwyY~[^^F \k0nf=pH!VyC($GrxAsg"Se=Anzl[OaIYO e=L2Mgu I'Y$Gd=#V({R=Y/ݱC&րv_vGk4y 5VրZ f]pޜ6)2z:pBC:AXcbrd^<9M/ L_Ψ_&ՁN/̘ф$Ps8:`NNޖo$&q9)EM0gf3B& bGD2ѭsxJ>f3*Ŭ:sǾ7ae3 (= J&̩KVRJ+| Tld2=& Eu78<ŁvN]XF0˄Yi噉\C}$mY+z՗|"eQJ_ mauɊ>FwT_;-,b pf{^3Scv`u[sݫ )ì"$%vd K-!97*AI̠XMQP9/OLOj{u/+:cRFFs|?;^? Tx:q8Ť*R(V<~Fy}D%n;f;/K'$OU"ع @Xt(80XE²LÀo쯜rFBe}:Yuz<Ą"]iaCXiMU"_uԳj[wDMR|)%/2ӓď$_ȩ@]ltvA 1FOVFםZj9FBXI34iNʸfG`DȎa;[IxQ_˜Æ_gi90׽(Kx&i"2V)Kj@-Ϟi#c!?]ڊ|fTVgb^h60t&଴Yc %hCLrėx^,,T6%;ɣe =kw<}K1DEqW@\*P7U[F#crQg57D\cuF3\NŬJԺ^VSucu֍:]/x Ki9tðKu̾WJSNs7PN`i]A <}9]5VÚQdq [l۵s #ZV*V'k{ҜXZ#/d`gN#:h"nR~FZ=wu Np7oFC+9cy/]7q.0fJ9t52r!8|]v1Y'dXNG=@hkojZJ}>l8YDV&*5AJƒWLT:B+}LEH@~߹aԟzo=kKh\.BUY H$F]/\ 2|;}q~KC?@&`)6oԭ+7S<x&尬k*Vi?2!s@jE8c EPL`*S?2RV4dg|vW3r,OV5f/%|F&I;d;f&/wuPu"_&U;gj`&/9<]]q #K~(]W UF7ϋ?rSDCh~giElw~WDi, +*rTP~йB;?R7᫙rƇ=BT`158YdG 0,Jp45*5WZ& lu\xUgy9זӈ0O Tz"X+- uuJyxk%<.a,88DlIQ 6snN ]uM a 2'iO_X2 GP0QJ9uhÁSuhv̝0^y,/sޗ_%=G?5$ADa} /fS9ziB44uKW0`il/aE$$dD]T&Q+nU~2 aTz@L`4e3`2JIN1T8Pܠ@mkk3ݱtϝAS8fԚ5h#jqY_\;Aåk'@5W8XD}\JunZBDFv4q$9!XVTWQ)!)s3 @7(`v&xH ⺆nц'N}z} $-`j/-Š}7 ěG`t3,3$j&cJܹOtIZQ*,GHhђ*<_'|9"hK;{"Fϋ8=]Y+6 m:=ͣ NOx/&D9Xw Ɛ u+*7ġ&'3Qo'nUE8#6)}/~6|K{y?Q)gP*77 ʡO6 ŵ&?ra X^@)<7oVg+ Ymzya6IS7h`W_I5k]A-bĉF(-U1r 8/T2G.<2A@]t" !HĠK 0{ovFE2K'0qr I:|%sS. VphbVY&;t] 3 0Җ,7WnU0c 6^r2Q!sCu/L,YS&R@YNC1ܛK*5KRM]p!'r+}az*z*WHԒZ\55;FTWfC5  "E3ŰTf@j`BK4㦉D`٩趖G/rsaHu2GLyz.T-$ؠLu  Fcў9$0q_ jgjZc*҉YX9o:KL ^b2X 15$ %HLC`p>$ 8QEd1z6ˈO7䮥8,bLaa$9:3f>yp0!a‡ܙ\& &h\f-@SLe#] ph0O+N IwtaimȿQ7e,W΍1&l$:*k1PH?Q|ן&)겷.ϟ'` ]nB]v?L*=ncT<ݺPMl1QɅs5*Kߩx(0Cyvy9< }Doပ+fj';$A[LJp3993u#X8]NpoݑfX&r9_i3F p-p+Z ifI}dC!zlK٨mp26VQ3e@m⁁LƶRvB&QNMPo,P O:(B T(RpKe9q!#V~ouf Ǜ7(q5^7\MjD\xZ6 Ӆ&EǴ܄3fYpVlds)DL,0eZ-PUJwBHʼ2,!ڑ4ohFZffS˹$Srg␔sH3!X+(ECYP!8ug,u~B͐WFCf_QTiy30 "EstdaiŖZO+` DMֱ *R;[eNڬɑμ*(K_P &sQZ&K>.: S_Ìj#~U4\u]hFd2\.kězΑWNR#YldJc$` KKcdz]!` ~/kcV);Ѩ -ͽ%:IPiZ,4ԵK Ff$i"iv[6H8Xb8Y"Kc3"ܸ"%b쾣+C*y+O^ѼCjԑaTدp< Y\X6_c@R'tȋR.ta@bۧ)0Dڣqd]9#N 8uR&u孆yx͉LHH'Ro㾲Ku7`%}JT]_+AfyF$6ޯ `Bac+X9can=ۯ=o7˼|^O쉱Tyx\'2{VdY'#G4NQH̍xDyY" eBm@s ӈ4qg 4v*D'32gVSAVA5Ejbػy"IoR=K11yI05(&GaTᏢaH=r\.G$75}3!a Kw n/ uUp ^ 3PB0v 74uɁ P]W.4@qXm%/Ծv}FL Y,sy*ګv(.H1G7bQFXhVSC~' N<\y;a?l/TfQSe,9t}6܍Yaa>;~RI50ɌZptKWHzU2J)tJoNȯRv[NV'>VyڭtmvivJj1ASv::ѵBqksBRf܃&ΈCƜ8*#>ۑNT82tCL>RHI*9Voja- A"3$=a~W- iNgl(= vOfճ.>ρYF ˆ*MUhr_13uQQ- H8fTkR&uiuGdj}p;Eu ,+>>1SZ-;{P="ؒD=9zIPvzy/Ӫ2A_aċ' )HфN֝W V)X;I(W߷Gm0vXU;pe0d˹|Nj]F=ɾU [W{fÇ8ʿAq}[) R~;]䤵s G|Sg(1Qt >-[vֱ".n0!Z8f[ g3 .Uae (~}:z[W!5bffcoc_Yu>$Q_#U[La5[F31B-ci2΀vtgh:ҿҡ$Xk?m^;*@'k5}ԮNvg`j)R# YߜrߖF *feVnc`l,SٝLt n8(L`66ca@G)|J@';&Ve,) (R(o`wu vtgA4voFHE[ sFmOJg( wȼJw 21lQVZWEsO( ,/j/=%ocj) G;zYz@\ 2t@&ُdWv_ӗz%uIr +Z21t&#mVhLt}=CV)d5lɶδ"Z3oi~=)\bfUㄾp6zva2 nE6 |XT!ߙilLI[+y@sO0} ?Yyh|.MOS.C{k ʑ /@KXIpAdTIJ6SHR%p9}ON<3aˤk>3>~N Na.QPWOāDIEf;AFz mf C%W@*D}עh >PAwԣDJr4vos3NNw=q R0=)_U_JU^b6-ZxqH^\ʳn^2/48vd&of|Y+u}H>_ϝkR(WY. FU60WE_Zqnze@vRu敨 E7"p*U^yyZ(Iwӄ%g^?oӓ: S)oT*xf~KԏN_3j(T aɋNlVw63wW^[;Vt/MvYbD^9]KVtpz0:0X=:5Ɖ*c9D&1r;2@}ɻ}Px((?!r&zi d2vطإiSwQŴ5{!ꎎNÉgпM[@q 6gt(fxx0 w0P>}goFG=o.YkoIށ n٩V Lcʎx0:Na7ބ!GSJ]/ o^Dʔg*Q3ds]5;.E*/A$SK,zl]`-oty`4 ;=G̊MAvrwE@L.QË4>$L fDՎbyk.҂iH*$f 1"ļ0޼Oc )p$= 3|zF6Р0vVdwZ/w Idk w]w@.HHeJ93yrnmFj'Ic6F)}*:+W%Ϸ /3@ ;7l'N %k]SaL{VV 04Y'ZfrUhAIop<)s@O5{Aq IH PAzƙA#JkQGfVɶ⃢#;7?Wץb%o> O&*YP>+*^z\ .em^#) ,P:yv#L|wA j[%Ɂc*#<#2ʊοg'T=2+?V'!ʹw|X^H:S::BznDSq<Ve{͖30F vp E(=jSfD3{c ݻ U9&ð3:)(Lρ>C$D0V(29̊*E$T@pMt/gpX\lsɒ|Rڧq0 J pУZ'G8cƺ&XHF|:슊~"3lpB"UO҆mAB96z^6NŦ]'l? 79 Z8$}-́#lTئ40!-iǬA] ;GLIY%ĕ?軓=6>GXHjtIr?ɤoŒ.}~nh 4'킌o@nZt ƾJ*Ź!,zW/{9|{NTa7P~kXh2f^X,G31 0y*ugJCI]ttnE}#*o/2x\{a0Iy6&L>oV%L+H~ &w4 K_tH?x}F`N+}:(#(B~}TG}'5X'P̺|Σ 쪾y&V,?V4+UN ʡDLHdLu(\ C8nUGZcš+V5O'7Ա±EQ+O|l 铱}K;Dkt4v63{NusA/, ί)ƪ)SI< 3a✑pm\9g{,8[d VL{![Me[ASDT:,h&:6):hTA?MQAPA[ttU\:[=K#cX T.TGtNR&cS#3;9bR3]3ҾTڟEy XU鮓RA.F14&@" IS{%DO-iΒXt"=tss ڲo6W\1#'o1͵4~P*GX##y'e#FB'Ƃx{>MBA1IC)xFfmmF4f m5p֦\@d>zI&rP,}tT^~eeTz >lFwZ04V ˿ܲo?ղx.Fbx T# 'K`.VKᎆ8*B,[8o=I .ll^>lS>/aZn`HoSV |wߴ0D*쩎Q*sȔSY` @," GHF[UԼ@G@΂U+jG_S?:Hw:)X,dOHKz8W ס|qsV ߁ |`1xܺ;[ ;L='-NƤ m/9a)rZj\>ј.bZ"B \'D /';^W \DFA4?DxNvB~ެl=ɣ.u?#ZSJ1]N]SeD{?C݄6**ݪa<#2c3ڣXU΄3@>AB5 rl1>47ӈ9>9_lf* l /,.><6ֶX9ч>t[C7궰v1(U]Q,icę.s>we-05AA?GڴK78 8YJ3]2%ѵi5;H\;tgޝU[-ix+) mP5v ?lsq6'm<Ş ?/-oXᘥerɝ@vDwL?| g坢CÕ.ؽbw/gh]]mc+&jzH: B'bdJC#Z){gqYU }gW9Ccq]8ՐuzL5 _![Ґh Pp,&wK=2*ـD+[ho#GIu``ZSpx1;ƬvcC,`OK14y o?}HUȒVz9VjL]~e[Jh"KVv$mU H 5lM^%G'Ц_Mq:b+CNo;4YVOGУ=!4 Kzu2VhBYnL֡Q, )Vhie{Y(ybtFц]͸=J$~ 5ӯ @x{Bk/ VK"qQ K6nr3Pn~ߙUET/Fe_$[4d>$rqa||3q6:,V.ɣ7R! ' O & O2fv|F@IE&iOX3q2=6j?.]'2N)Jhw; L$Dħ ɕ!;e%U]z9l1a?[$,+*r%F%=+eI:dvy!4XAI{[d[\Q_|K4&x1♣` exd/U&Љ,ĿZ 1^//.վLISp,3-:>+AG}WlBr  LgҵX"w/ 7 YЛZ4 4uS%(י=2cMyI;?4mgEH|Vv/GadL% eT$2| 쓉@Oyw|(G"tKxBш$p0)ʁAPJih(HOgkIu#qnhtvCF(ýdR3i6ΞǏλcͰ./=tvS*  :62E-={-eu7c )\|hf7 sˀ΋{S"ְؼ,XK1՛^ {$XJb< toxct¯x5F N@a^V#3}| _v=1Z <-y.QI'wG\Jl{SR]F` E<QNhil8 G^ȁ$MF8KPׅ*[#F7D #wGWn/H 9AFb暊"Zabe.<[?xZF_ b T@M`Qc*PnW ^SI(? }cߴID}Ma&Ȝ jot|\g}^Ā<e J>$]'*Pd`2nOeY[JqhOEs/n%sK \]I i"ӎD]~ecԖk9z{ݕq }~ J4&} ؚZT -P?g01suQ :θBWLaiIܓ4l4v޹4Pv%tJ`; lڝ];+wA#uS:ɁZJ,HceLLh*H[ec ݋ N6> '"?dB"Gf~:eqt)8zgG/vRw8FdyV.+ñUt= S$S(YUpv&^=|cOɏ'Oh~"=O2MPzm$kga@G[3A̛J89iInɭ d*vjv]^q X`HZt#2K ag,7`]5@6r~o*R `{nF x`R!za,2LqWwM4 HA(Pgq"]ciav3cn7uKi,Rzt΍g+_Kk(+ pixvE9:U2KKz\_bh'f5/K~99=k5ZK{BUhS֜wkrUX-KV8k7NOVUZBjqA0?n*"ٕ\QR1g7/rK>C(c,r]2̑6F@Ζvs砧h0cGn_.ƅVHirtNٶcu*K@\ybH9^j~SMhD (!F)=P# xyU)-DK'ŭ7&[thå@E"VP (:B!,P4Skwһ{q ܧ-ypV.ДۮKz]NNxOIFC۰K:`vC\ t2K.VkO-pbгQ9%]jbe4/PB Wnhx k-@ y^hՆ.yQ -˫5ƕ1Am([J *ܳ%sS(T}~~\:^r); ~9?0PEPi0q(>Z_]Z:6¾!ȯnuEnb\&$-r]K$4֩b (D+nO_~ib>ۘcߋBT+xßog?toV(6EqV$ـsX=ťYقsBd9ؕBe4c@!!T%βalyUS;=9hb Pdy$yxrS uSs jRQcylZϛvq.𴀾:Ppk˓>B ;BU%4f 8yӱB'mLob&ɚN5T=XtZcUz.I&j4^LU7$tYԮ7ʅa]mPXЪwN[7&!w([!\Fe~PvUѪJoff^WǭPT+NF(odj8kuאָK?.g!5VE{ʓkXx’K3,\B$Dߙ1iJj9-#r>2I<%2!&~kk ߬6NdE^CE4z;`E?/zC0]zwiԋTፘP~U;ԓ2J1_&ȍr2+-K PH` uZ:&r;dڀsP;iYTM((LQ!!L4gZ΀Ȁ̊iӳX1x73]8}1[f)i<|Krtzةl{Ymf9Ԧzߨz "ArP#CQ)Ko=1s 4M$Oe?$8fiz>$rYOHM?B9^ i%^ "+BQI/-4J5Q|HGp14"oTE~&ds@r.ӹBmDV,BA\6p/5ׯsFA 8tPNeaDG8;ɮ,EX?dπsj5^ԳI LΫR8 ?pez#hO| ӲІy.ktٲGzլrdg{(j$9 ;pDrG\ d] U;ؗ/ΐX]]Tm fJ!`RH* g̈́c"]d3]X`HB<|Ar$$KtR9P'å|x>F 91cg=l'aGUF$NdU Ca]As8e&][ieVə[EyL(#Qn[ß{һqfΥ?i{2iCfb!u] !A9uJ;E@!!:Q:$c; RjRveksY/^:^^z92:()ўg8¥6"#tt4~=RR91[ߜgۖDFQÜ&r?ĿK0: t+^`:+ @]Emc'Րp'ȇ)ɰ$/{ Վ.z#[h7gѱR׋ɸjɀs8rʵgmΜYoa;l:9EgUOag(0}'Q"# ( 荻 ^c2H{|V ;r~LzԆ"{q2Mz *Sr]P݈AE3-)F#&2bjDiTB7 !'HGF0aT2 )A1S|`o#7`ױ4!eAƐ1қ!ɔ6.*T. Lo ZE~?' ofrd~QݪY2k&DfM]G!:vQ,G]+ӝkcA#łT@1:`kJp{ 㺜Rʋ2K.яRb#`(EKElY yYYxƫL9 tjL.x_;21r! [*.V\+.'' lX>Agp|0b:9 P`hC2# [b=w۶ȸ_`*4z4d4f0Ծ\%\xohk)%ˑ 9^Jr `{ 'Fa>qeF ʧ겾HnTJ~hXq~B#}OE;lv!N7rDQ 4J$ #include void putat (int i) { while (i--) putchar ('@'); } int main (int argc, char *argv[]) { struct termios raw, old; tcgetattr (0, &old); tcgetattr (0, &raw); cfmakeraw (&raw); tcsetattr (0, TCSANOW, &raw); fputs ("\033[H\033[2J", stdout); putat (80); fputs ("\r\n", stdout); fputs ("*", stdout); fputs ("\r\n\n", stdout); putat (80); fputs ("a", stdout); fputs ("\r\n", stdout); fputs ("*", stdout); fputs ("\r\n\n", stdout); putat (80); fputs ("\rb\n", stdout); fputs ("*", stdout); fputs ("\r\n\n", stdout); putat (80); fputs ("\nc\n", stdout); fputs ("*", stdout); fputs ("\r\n\n", stdout); putat (80); fputs ("\033[Cd", stdout); fputs ("\r\n", stdout); fputs ("*", stdout); fputs ("\r\n\n", stdout); putat (80); fputs ("\033[De", stdout); fputs ("\r\n", stdout); fputs ("*", stdout); fputs ("\r\n\n", stdout); tcsetattr (0, TCSANOW, &old); return 0; } work/version-files0000664000000000000000000000137213337271225011450 0ustar apps/clients.c apps/clients.h apps/mainloop.c apps/mainloop.h apps/Makefile.am apps/sympathy.c apps/usage.c src/ansi.c src/ansi.h src/cmd.c src/cmd.h src/context.h src/crt.c src/crt.h src/history.c src/history.h src/html.c src/ipc.c src/ipc.h src/keydis.c src/keydis.h src/keys.h src/libsympathy.c src/lockfile.c src/lockfile.h src/log.c src/log.h src/Makefile.am src/project.h src/prototypes.h src/ptty.c src/render.c src/ring.c src/ring.h src/rotate.c src/serial.c src/slide.c src/slide.h src/sympathy.h.head.in src/sympathy.h.tail src/symsocket.c src/symsocket.h src/terminal.c src/tty.c src/tty.h src/utf8.c src/utf8.h src/util.c src/version.c src/vt102.c src/vt102_charset.c src/vt102_charset.h src/vt102.h test/Makefile.am test/test.c test/xn.c sympathy.1 work/version-major0000664000000000000000000000000213337271225011443 0ustar 1 work/version-md5sums0000664000000000000000000000135113337271225011740 0ustar 6488eda7d5c4d46ce3f587f5dc745dfa 1.0.1 ca1ac5a7fc122af620b0cf7296c324c3 1.0.2 ac9d93b50970b366e4531b4ea5a1c983 1.0.3 ac9d93b50970b366e4531b4ea5a1c986 1.1.0 0ea0fc96142920321bfa5354dc6b9da9 1.1.1 b1b1d8caa83556877bb96487f0c6a934 1.1.2 f844259e45d571cf913580d8851ee261 1.1.3 88cd008326dcedb9dee8011ce2697e6a 1.1.4 93f010bab6441e6f679f523725507d04 1.1.5 0baf4bcc06f0271dba444738df2ef1e3 1.1.6 30b3685c955c05efa7ba0affb9fbca1a 1.1.7 b9ef98229248516850808e590721c0e5 1.1.8 a5ee6f647e6d98d5f06b75a70b7bf9a5 1.1.9 69a1973d2476e4c903c39e43db6b6838 1.1.10 7f8612564a03e6cb722e8692027252f2 1.1.11 0c169eaf189eb8f9b375254b69e63c31 1.1.12 9422541c5f11969d68f1e995925f0ef5 1.1.13 b86aca610f6f0763d7ad9ee4d8390c03 1.2.0 6d5eefa9b04abaf2343677005de951de 1.2.1 work/version-micro0000664000000000000000000000000213337271225011444 0ustar 1 work/version-minor0000664000000000000000000000000213337271225011457 0ustar 2 work/version-stamps0000664000000000000000000000115513337271225011654 0ustar 88cd008326dcedb9dee8011ce2697e6a "February 27, 2008" 93f010bab6441e6f679f523725507d04 "February 28, 2008" 0baf4bcc06f0271dba444738df2ef1e3 "February 28, 2008" 30b3685c955c05efa7ba0affb9fbca1a "February 28, 2008" b9ef98229248516850808e590721c0e5 "February 28, 2008" a5ee6f647e6d98d5f06b75a70b7bf9a5 "February 28, 2008" 69a1973d2476e4c903c39e43db6b6838 "February 28, 2008" 7f8612564a03e6cb722e8692027252f2 "March 03, 2008" 0c169eaf189eb8f9b375254b69e63c31 "March 03, 2008" 9422541c5f11969d68f1e995925f0ef5 "March 07, 2008" b86aca610f6f0763d7ad9ee4d8390c03 "March 11, 2008" 6d5eefa9b04abaf2343677005de951de "March 12, 2008" work/version.sed0000664000000000000000000000014613337271225011120 0ustar s/%VERSION%/1.2.1-E/g s/%VERSIONSTAMP%/After March 12, 2008/g s/%LONGVERSION%/Version 1.2.1 + Edits/g