changeset 2:68b230f8da5f

[gaim-migrate @ 11] A few more commits :) committer: Tailor Script <tailor@pidgin.im>
author Rob Flynn <gaim@robflynn.com>
date Thu, 23 Mar 2000 03:16:06 +0000
parents 2846a03bda67
children dd6d2c96703a
files doc/.cvsignore libfaim/.cvsignore libfaim/BUGS libfaim/CHANGES libfaim/COPYING libfaim/Makefile.am libfaim/README libfaim/aim.h libfaim/aim_auth.c libfaim/aim_buddylist.c libfaim/aim_chat.c libfaim/aim_chatnav.c libfaim/aim_conn.c libfaim/aim_global.c libfaim/aim_im.c libfaim/aim_info.c libfaim/aim_login.c libfaim/aim_logoff.c libfaim/aim_misc.c libfaim/aim_rxhandlers.c libfaim/aim_rxqueue.c libfaim/aim_search.c libfaim/aim_snac.c libfaim/aim_tlv.c libfaim/aim_txqueue.c libfaim/aim_util.c libfaim/faimconfig.h m4/.cvsignore m4/Makefile.am m4/esd.m4 m4/gnome-gnorba-check.m4 m4/gnome-orbit-check.m4 m4/gnome-pthread-check.m4 m4/gnome-x-checks.m4 m4/gnome.m4 pixmaps/.cvsignore src/.cvsignore
diffstat 37 files changed, 4716 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/.cvsignore	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,2 @@
+Makefile.in
+Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/.cvsignore	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,3 @@
+Makefile
+Makefile.in
+.deps
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/BUGS	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,29 @@
+
+aim.h
+-----
+  - Needs a bit of cleaning
+
+aim_auth.c
+----------
+  - Login doesn't take advantage of aim_conn constructs where it could
+  - Login should allow for multiple BOS connections
+
+aim_chat.c
+----------
+  - Needs to be implemented.
+
+aim_chatnav.c
+-------------
+  - Needs to be implemented.
+
+aim_conn.c
+----------
+  - Does not work with proxies.
+
+aim_search.c
+------------
+  - Still need aim_usersearch_name()
+
+aim_snac.c
+----------
+  - Should implement better SNAC handling
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/CHANGES	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,63 @@
+
+No release numbers
+------------------
+ - Sun Aug  1 03:02:17 UTC 1999
+   - Added aimutil_*()s in aim_util.c for raw byte placement
+   - Cleaned up aim_im.c, aim_auth.c, and aim_login.c using aimutil_*
+   - Added AIM_IMFLAGS, flags option to aim_send_im(), removed
+       aim_send_im_away()
+   - Added client_info parameter to aim_send_login()
+   - Tweaked aim_send_im() (AOL changed a few things, there's some more
+       changes left to do)
+   - Some Chat stuff changed, still no where near functional
+   - Finally remembered to switch the license to LGPL (from GPL)
+   - Released a snapshot
+
+ - Sat Jul 31 05:28:38 UTC 1999
+   - Changed aim_bos_setdeny() to aim_bos_changevisibility() and actually
+       did the implementation.  
+
+ - Fri Jul 23 17:45:22 UTC 1999
+   - Work around for the AOL change in IP syntax (thanks to Eric Peyton)
+   - Released snapshot
+
+ - Sun Apr 25 23:31:44 UTC 1999
+   - Fixed stupid off-by-one bug in aim_logoff()
+
+ - Sun Apr 25 22:43:31 UTC 1999
+   - Renamed/reclassified missed IM errors (now all callbacks -- no backend handling)
+   - Killed aim_login() -- all connections now opened in frontend
+   - aim_conn_close() will not close fd's < 3
+   - Released snapshot.
+
+ - Sat Apr 10 22:44:07 UTC 1999
+   - Changed how rx_command->handled works; now uses return value from callback
+   - Changed the if's in the dispatcher (aim_rxhandlers.c) to switch()es
+
+ - Sat Apr 10 03:51:21 UTC 1999
+   - Started CHANGES
+   - Put in n's aim_snac.c.
+   - Updated aim_{add,remove}_buddy() to use aim_conn
+   - Updated aim_usersearch_address() to use aim_conn
+   - Cleaned up aim.h a bit (removed old *phase* protos)
+   - Changed gethostbyname() to gethostbyname2() (for MacOS X)
+   - Changed aim_newconn() to pass connection errors in connstruct->status
+     - Updated faimtest.c to detect connection errors
+   - Fixed a small typo in aim_im::aim_parse_incoming_im_middle()
+   - Added free()s in that function and to userinfo counterpart (fewer leaks)
+   - Released snapshot
+
+ - Sat Apr  3 06:43:14 UTC 1999
+   - Released snapshot
+
+ - Wed Dec 30 01:20:59 MST 1998
+   - Released snapshot
+
+ - Mon Dec  7 16:57:57 MST 1998
+   - Released snapshot
+
+ - Sat Dec  5 00:01:53 MST 1998
+   - Released snapshot
+ 
+ - Thu Nov 26 17:50:02 MST 1998
+   -  Released snapshot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/COPYING	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,504 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  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.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/Makefile.am	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,14 @@
+noinst_LIBRARIES = $(LIBFAIM_DO)
+
+EXTRA_LIBRARIES = libfaim.a
+
+EXTRA_DIST = aim.h faimconfig.h
+
+libfaim_a_SOURCES = aim_chatnav.c aim_info.c aim_rxhandlers.c \
+                    aim_tlv.c aim_auth.c aim_conn.c aim_login.c \
+                    aim_rxqueue.c aim_txqueue.c aim_buddylist.c \
+                    aim_global.c aim_logoff.c aim_search.c aim_util.c \
+                    aim_chat.c aim_im.c aim_misc.c aim_snac.c
+
+CFLAGS += $(GAIM_CFLAGS) -I../src
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/README	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,80 @@
+
+libfaim pre-0.90 or so
+----------------------
+
+This is libfaim, the purpose of which is to implement as much as the
+AOL AIM/OSCAR protocol as possible (which should be all of it).  After
+nearly a year of development, its still nowhere close.  
+
+This is not a full client and never will be.  libfaim only implements
+the routines to implement a client (ie, there's no user interface).  
+
+Status
+------
+
+I would not recommend using this version of libfaim in any form yet.  It's
+beta-quality and I know it leaks memory quite badly.  It seems fairly
+stable, however.  YMMV, YAYOR, etc.
+
+
+Building
+--------
+
+Everything in this libfaim dist should build cleanly on any UNIX(-like)
+operating system.  Originally developed on Linux+glibc.  Past versions 
+known to work on Linux+libc5, FreeBSD, HP/UX, Solaris, Mac OS X Server,
+and others.
+
+libfaim builds as both libfaim.a and libfaim.so.  If your platform for
+some reason does not support dynamic libraries (eg, you get errors when
+building libfaim.so), you'll have to tweak the makefiles a bit to get
+the utils/ directory to build.  
+
+Otherwise, just do a 'make'.  I don't believe I use any specific features
+GNU make, but if something fails, make sure you have it.  And bash too.
+
+
+Accessories
+-----------
+
+In utils/, you'll find a few things extra:
+
+  faimtest:   very rudimentary front-end.  no user interface, but does
+              illustrate the basics of logging in and sending/recieving
+              messages and buddy list notifications.  Potential front-
+              end authors start here.
+
+  aimpasswd:  utility to change an AIM password without using a full
+              client.  Note that at the time of this writing, this
+              didn't work quite right yet.  See the top of the code for
+              latest status.
+
+License
+-------
+
+libfaim is covered under my copyright under the terms of the Lesser GNU
+Public License, as documented in the file COPYING in the top level directory.
+
+
+Documentation
+-------------
+
+Unfortunatly, there is not currently any documentation on the libfaim API.
+Use the source and utils/faimtest/faimtest.c as a reference when coding
+front-ends.  
+
+
+Contact Info
+------------
+
+The author (Adam Fritzler), can be reached at afritz@iname.com or mid@auk.cx.
+
+I did have mailing lists available for faim-related discussion, but they
+have dwindled and eventually broke and to my knowledge have yet to fix 
+themselves.
+
+Front-end information:
+  http://www.auk.cx/faim/
+Protocol information:
+  http://www.auk.cx/faim/protocol/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim.h	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,297 @@
+#ifndef __AIM_H__
+#define __AIM_H__
+
+#include <faimconfig.h>
+
+/* some global includes */
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#define CONNECT_SIG_LEN 10 /* not used anymore, hopefully */
+#define LOGIN_RESP_LEN 512 /* should only be 334b but no segfault for us! */
+
+
+/*
+ * Error codes
+ */
+#define AIM_CONNECT_ERROR	-0x1
+#define AIM_SIGNON_TOO_SOON	-0x4
+#define AIM_SERVICE_FULL	-0x6f
+
+
+struct login_phase1_struct {
+  char *screen_name;
+  char *BOSIP;
+  char *cookie;
+  char *email;
+  ushort regstatus;
+};
+
+extern struct login_phase1_struct aim_logininfo;
+
+struct client_info_s {
+  char clientstring[100]; /* arbitrary number */
+  int major;
+  int minor;
+  int build;
+  char country[3];
+  char lang[3];
+};
+
+struct connection_info_struct {
+  unsigned int local_seq_num_origin; /* our first seq num */
+  int local_command_count;
+
+  unsigned int remote_seq_num_origin; /* oscar's first seqnum */
+  int remote_command_count; /* command_count + seq_num_origin = cur_seq_num */
+
+  char *sn; /* our screen name */
+
+  int fd;                   /* socket descriptor */
+};
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#define AIM_CONN_MAX 5 
+/* these could be arbitrary, but its easier to use the actual AIM values */
+#define AIM_CONN_TYPE_AUTH 0x0007
+#define AIM_CONN_TYPE_ADS 0x0005
+#define AIM_CONN_TYPE_BOS 2
+#define AIM_CONN_TYPE_CHAT 0x000e
+#define AIM_CONN_TYPE_CHATNAV 0x000d
+
+#define AIM_CONN_STATUS_READY 0x0001
+#define AIM_CONN_STATUS_INTERNALERR 0x0002
+#define AIM_CONN_STATUS_RESOLVERR 0x80
+#define AIM_CONN_STATUS_CONNERR 0x40
+
+
+struct aim_conn_t {
+  int fd;
+  int type;
+  int seqnum;
+  int status;
+};
+struct aim_conn_t aim_conns[AIM_CONN_MAX];
+
+
+/* struct for incoming commands */
+struct command_rx_struct {
+                            /* byte 1 assumed to always be 0x2a */
+  char type;                /* type code (byte 2) */
+  unsigned int seqnum;      /* sequence number (bytes 3 and 4) */
+  unsigned int commandlen;  /* total packet len - 6 (bytes 5 and 6) */
+  char *data;               /* packet data (from 7 byte on) */
+  unsigned int lock;        /* 1 = locked, 0 = open */
+  unsigned int handled;     /* 1 = been handled, 0 = new */
+  struct aim_conn_t *conn;  /* the connection it came in on... */
+  struct command_rx_struct *next; /* ptr to next struct in list */
+};
+
+/* struct for outgoing commands */
+struct command_tx_struct {
+                            /* byte 1 assumed to be 0x2a */
+  char type;                /* type/family code */
+  unsigned int seqnum;      /* seqnum dynamically assigned on tx */
+  unsigned int commandlen;  /* SNAC length */
+  char *data;               /* packet data */
+  unsigned int lock;        /* 1 = locked, 0 = open */
+  unsigned int sent;        /* 1 = has been sent, 0 = new */
+  struct aim_conn_t *conn; 
+  struct command_tx_struct *next; /* ptr to next struct in list */
+};
+
+/* TLV-related tidbits */
+struct aim_tlv_t {
+  u_short type;
+  u_short length;
+  u_char *value;
+};
+
+struct aim_tlv_t *aim_grabtlv(u_char *src);
+struct aim_tlv_t *aim_grabtlvstr(u_char *src);
+int aim_puttlv (u_char *dest, struct aim_tlv_t *newtlv);
+struct aim_tlv_t *aim_createtlv(void);
+int aim_freetlv(struct aim_tlv_t **oldtlv);
+int aim_puttlv_16(u_char *, u_short, u_short);
+
+/* some prototypes... */
+
+/*   implicitly or explicitly called */
+int aim_get_command(void);
+int aim_rxdispatch(void);
+int aim_logoff(void);
+
+typedef int (*rxcallback_t)(struct command_rx_struct *, ...);
+int aim_register_callbacks(rxcallback_t *);
+
+u_long aim_genericreq_n(struct aim_conn_t *conn, u_short family, u_short subtype);
+u_long aim_genericreq_l(struct aim_conn_t *conn, u_short family, u_short subtype, u_long *);
+u_long aim_genericreq_s(struct aim_conn_t *conn, u_short family, u_short subtype, u_short *);
+
+/* aim_login.c */
+int aim_send_login (struct aim_conn_t *, char *, char *, struct client_info_s *);
+int aim_encode_password(const char *, char *);
+
+
+struct command_rx_struct *aim_purge_rxqueue(struct command_rx_struct *queue);
+
+
+int aim_parse_unknown(struct command_rx_struct *command, ...);
+int aim_parse_missed_im(struct command_rx_struct *, ...);
+int aim_parse_last_bad(struct command_rx_struct *, ...);
+
+int aim_tx_enqueue(struct command_tx_struct *);
+unsigned int aim_get_next_txseqnum(struct aim_conn_t *);
+int aim_tx_flushqueue(void);
+int aim_tx_printqueue(void);
+int aim_tx_purgequeue(void);
+
+/* queue (linked list) pointers */
+extern struct command_tx_struct *aim_queue_outgoing; /* incoming commands */
+extern struct command_rx_struct *aim_queue_incoming; /* outgoing commands */
+
+/* The default callback handler array */
+extern rxcallback_t aim_callbacks[];
+
+extern struct aim_snac_t *aim_outstanding_snacs;
+extern u_long aim_snac_nextid;
+
+#define AIM_CB_INCOMING_IM 0
+#define AIM_CB_ONCOMING_BUDDY 1
+#define AIM_CB_OFFGOING_BUDDY 2
+#define AIM_CB_MISSED_IM 3
+#define AIM_CB_MISSED_CALL 4
+#define AIM_CB_LOGIN_P4_C1 5
+#define AIM_CB_LOGIN_P4_C2 6
+#define AIM_CB_LOGIN_P2_1 7
+#define AIM_CB_LOGIN_P2_2 8
+#define AIM_CB_LOGIN_P3_B 9
+#define AIM_CB_LOGIN_P3D_A 10
+#define AIM_CB_LOGIN_P3D_B 11
+#define AIM_CB_LOGIN_P3D_C 12
+#define AIM_CB_LOGIN_P3D_D 13
+#define AIM_CB_LOGIN_P3D_E 14
+#define AIM_CB_LOGIN_P3D_F 15
+#define AIM_CB_RATECHANGE 16
+#define AIM_CB_USERERROR 17
+#define AIM_CB_UNKNOWN 18
+#define AIM_CB_USERINFO 19
+#define AIM_CB_SEARCH_ADDRESS 20
+#define AIM_CB_SEARCH_NAME 21
+#define AIM_CB_SEARCH_FAIL 22
+#define AIM_CB_AUTH_ERROR 23
+#define AIM_CB_AUTH_SUCCESS 24
+#define AIM_CB_AUTH_SVRREADY 25
+#define AIM_CB_AUTH_OTHER 26
+#define AIM_CB_AUTH_INFOCHNG_REPLY 27
+#define AIM_CB_CHATNAV_SVRREADY 28
+
+int Read(int, u_char *, int);
+
+struct aim_snac_t {
+  u_long id;
+  u_short family;
+  u_short type;
+  u_short flags;
+  void *data;
+  time_t issuetime;
+  struct aim_snac_t *next;
+};
+u_long aim_newsnac(struct aim_snac_t *newsnac);
+struct aim_snac_t *aim_remsnac(u_long id);
+int aim_cleansnacs(int maxage);
+int aim_putsnac(u_char *, int, int, int, u_long);
+
+void aim_connrst(void);
+struct aim_conn_t *aim_conn_getnext(void);
+void aim_conn_close(struct aim_conn_t *deadconn);
+struct aim_conn_t *aim_getconn_type(int type);
+struct aim_conn_t *aim_newconn(int type, char *dest);
+int aim_conngetmaxfd(void);
+struct aim_conn_t *aim_select(struct timeval *);
+int aim_conn_isready(struct aim_conn_t *);
+int aim_conn_setstatus(struct aim_conn_t *, int);
+
+/* aim_misc.c */
+
+#define AIM_VISIBILITYCHANGE_PERMITADD 0x05
+#define AIM_VISIBILITYCHANGE_PERMITREMOVE 0x06
+#define AIM_VISIBILITYCHANGE_DENYADD 0x07
+#define AIM_VISIBILITYCHANGE_DENYREMOVE 0x08
+
+u_long aim_bos_setidle(struct aim_conn_t *, u_long);
+u_long aim_bos_changevisibility(struct aim_conn_t *, int, char *);
+u_long aim_bos_setbuddylist(struct aim_conn_t *, char *);
+u_long aim_bos_setprofile(struct aim_conn_t *, char *);
+u_long aim_bos_setgroupperm(struct aim_conn_t *, u_long);
+u_long aim_bos_clientready(struct aim_conn_t *);
+u_long aim_bos_reqrate(struct aim_conn_t *);
+u_long aim_bos_ackrateresp(struct aim_conn_t *);
+u_long aim_bos_setprivacyflags(struct aim_conn_t *, u_long);
+u_long aim_bos_reqpersonalinfo(struct aim_conn_t *);
+u_long aim_bos_reqservice(struct aim_conn_t *, u_short);
+u_long aim_bos_reqrights(struct aim_conn_t *);
+u_long aim_bos_reqbuddyrights(struct aim_conn_t *);
+u_long aim_bos_reqlocaterights(struct aim_conn_t *);
+u_long aim_bos_reqicbmparaminfo(struct aim_conn_t *);
+
+/* aim_rxhandlers.c */
+int aim_register_callbacks(rxcallback_t *);
+int aim_rxdispatch(void);
+int aim_authparse(struct command_rx_struct *);
+int aim_handleredirect_middle(struct command_rx_struct *, ...);
+int aim_parse_unknown(struct command_rx_struct *, ...);
+int aim_parse_missed_im(struct command_rx_struct *, ...);
+int aim_parse_last_bad(struct command_rx_struct *, ...);
+int aim_parse_generalerrs(struct command_rx_struct *command, ...);
+
+/* aim_im.c */
+#define AIM_IMFLAGS_AWAY 0x01 /* mark as an autoreply */
+#define AIM_IMFLAGS_ACK 0x02 /* request a receipt notice */
+u_long aim_send_im(struct aim_conn_t *, char *, int, char *);
+int aim_parse_incoming_im_middle(struct command_rx_struct *);
+
+/* aim_info.c */
+u_long aim_getinfo(struct aim_conn_t *, const char *);
+int aim_parse_userinfo_middle(struct command_rx_struct *);
+
+/* aim_auth.c */
+int aim_auth_sendcookie(struct aim_conn_t *, char *);
+u_long aim_auth_clientready(struct aim_conn_t *);
+u_long aim_auth_changepasswd(struct aim_conn_t *, char *, char *);
+
+/* aim_buddylist.c */
+u_long aim_add_buddy(struct aim_conn_t *, char *);
+u_long aim_remove_buddy(struct aim_conn_t *, char *);
+
+/* aim_search.c */
+u_long aim_usersearch_address(struct aim_conn_t *, char *);
+/* u_long aim_usersearch_name(struct aim_conn_t *, char *); */
+
+/* aim_util.c */
+int aimutil_put8(u_char *, u_short);
+int aimutil_put16(u_char *, u_short);
+int aimutil_put32(u_char *, u_long);
+int aimutil_putstr(u_char *, u_char *, int);
+
+/* proxy support */
+#ifdef ENABLE_PROXY_SUPPORT
+#include "proxy.h"
+#endif
+
+#endif /* __AIM_H__ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_auth.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,149 @@
+/*
+  aim_auth.c
+
+  Deals with the authorizer.
+
+ */
+
+#include "aim.h"
+
+/* this just pushes the passed cookie onto the passed connection -- NO SNAC! */
+int aim_auth_sendcookie(struct aim_conn_t *conn, char *chipsahoy)
+{
+  struct command_tx_struct newpacket;
+  int curbyte=0;
+  
+  newpacket.lock = 1;
+
+  if (conn==NULL)
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_AUTH);
+  else
+    newpacket.conn = conn;
+
+  newpacket.type = 0x0001;  /* channel 1 (no SNACs, you know) */
+  
+  newpacket.commandlen = 4 + 2 + 2 + 0x100;
+  newpacket.data = (char *) calloc(1, newpacket.commandlen);
+  
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0000);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0006);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0100);
+  memcpy(&(newpacket.data[curbyte]), chipsahoy, 0x100);
+
+  aim_tx_enqueue(&newpacket);
+  
+  return 0;
+}
+
+u_long aim_auth_clientready(struct aim_conn_t *conn)
+{
+  struct command_tx_struct newpacket;
+  int curbyte = 0;
+
+  newpacket.lock = 1;
+
+  if (conn==NULL)
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_AUTH);
+  else
+    newpacket.conn = conn;
+
+  newpacket.type = 0x0002;
+  
+  newpacket.commandlen = 26;
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+  
+  curbyte += aim_putsnac(newpacket.data+curbyte, 0x0001, 0x0002, 0x0000, aim_snac_nextid);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0002);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0013);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0007);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001);
+
+  aim_tx_enqueue(&newpacket);
+
+  {
+    struct aim_snac_t snac;
+    
+    snac.id = aim_snac_nextid;
+    snac.family = 0x0001;
+    snac.type = 0x0004;
+    snac.flags = 0x0000;
+
+    snac.data = NULL;
+
+    aim_newsnac(&snac);
+  }
+
+  return (aim_snac_nextid++);
+}
+
+u_long aim_auth_changepasswd(struct aim_conn_t *conn, char *new, char *current)
+{
+  struct command_tx_struct newpacket;
+  int i;
+
+  newpacket.lock = 1;
+
+  if (conn==NULL)
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_AUTH);
+  else
+    newpacket.conn = conn;
+
+  newpacket.type = 0x0002;
+  
+  newpacket.commandlen = 10 + 4 + strlen(current) + 4 + strlen(new);
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+
+  newpacket.data[0] = 0x00;
+  newpacket.data[1] = 0x07;
+
+  newpacket.data[2] = 0x00;
+  newpacket.data[3] = 0x04;
+
+  newpacket.data[4] = 0x00;
+  newpacket.data[5] = 0x00;
+
+  /* SNAC reqid */
+  newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF;
+  newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF;
+  newpacket.data[8] = (aim_snac_nextid >>  8) & 0xFF;
+  newpacket.data[9] = (aim_snac_nextid) & 0xFF;
+
+  /* current password TLV t(0002) */
+  i = 10;
+  newpacket.data[i++] = 0x00;
+  newpacket.data[i++] = 0x02;
+  newpacket.data[i++] = 0x00;
+  newpacket.data[i++] = strlen(current) & 0xff;
+  memcpy(&(newpacket.data[i]), current, strlen(current));
+  i += strlen(current);
+
+  /* new password TLV t(0012) */
+  newpacket.data[i++] = 0x00;
+  newpacket.data[i++] = 0x12;
+  newpacket.data[i++] = 0x00;
+  newpacket.data[i++] = strlen(new) & 0xff;
+  memcpy(&(newpacket.data[i]), new, strlen(new));
+  i+=strlen(new);
+
+  aim_tx_enqueue(&newpacket);
+
+  {
+    struct aim_snac_t snac;
+    
+    snac.id = aim_snac_nextid;
+    snac.family = 0x0001;
+    snac.type = 0x0004;
+    snac.flags = 0x0000;
+
+    snac.data = NULL;
+
+    aim_newsnac(&snac);
+  }
+
+  return (aim_snac_nextid++);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_buddylist.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,117 @@
+
+#include <aim.h>
+
+/*
+ * aim_add_buddy()
+ *
+ * Adds a single buddy to your buddy list after login.
+ *
+ */
+u_long aim_add_buddy(struct aim_conn_t *conn, char *sn )
+{
+   struct command_tx_struct newpacket;
+
+   if( !sn )
+      return -1;
+
+   if (conn)
+     newpacket.conn = conn;
+   else
+     newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+
+   newpacket.lock = 1;
+   newpacket.type = 0x0002;
+   newpacket.commandlen = 11 + strlen( sn );
+   newpacket.data = (char *)malloc( newpacket.commandlen );
+
+   newpacket.data[0] = 0x00;
+   newpacket.data[1] = 0x03;
+   newpacket.data[2] = 0x00;
+   newpacket.data[3] = 0x04;
+   newpacket.data[4] = 0x00;
+   newpacket.data[5] = 0x00;
+
+   /* SNAC reqid */
+   newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF;
+   newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF;
+   newpacket.data[8] = (aim_snac_nextid >>  8) & 0xFF;
+   newpacket.data[9] = (aim_snac_nextid) & 0xFF;
+
+   /* length of screenname */ 
+   newpacket.data[10] = strlen( sn );
+
+   memcpy( &(newpacket.data[11]), sn, strlen( sn ) );
+
+   aim_tx_enqueue( &newpacket );
+
+   {
+      struct aim_snac_t snac;
+    
+      snac.id = aim_snac_nextid;
+      snac.family = 0x0003;
+      snac.type = 0x0004;
+      snac.flags = 0x0000;
+
+      snac.data = malloc( strlen( sn ) + 1 );
+      memcpy( snac.data, sn, strlen( sn ) + 1 );
+
+      aim_newsnac( &snac );
+   }
+
+   return( aim_snac_nextid++ );
+}
+
+u_long aim_remove_buddy(struct aim_conn_t *conn, char *sn )
+{
+   struct command_tx_struct newpacket;
+
+   if( !sn )
+      return -1;
+
+   if (conn)
+     newpacket.conn = conn;
+   else
+     newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+
+   newpacket.lock = 1;
+   newpacket.type = 0x0002;
+   newpacket.commandlen = 11 + strlen(sn);
+   newpacket.data = (char *)malloc( newpacket.commandlen );
+
+   newpacket.data[0] = 0x00;
+   newpacket.data[1] = 0x03;
+   newpacket.data[2] = 0x00;
+   newpacket.data[3] = 0x05;
+   newpacket.data[4] = 0x00;
+   newpacket.data[5] = 0x00;
+
+   /* SNAC reqid */
+   newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF;
+   newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF;
+   newpacket.data[8] = (aim_snac_nextid >>  8) & 0xFF;
+   newpacket.data[9] = (aim_snac_nextid) & 0xFF;
+
+   /* length of screenname */ 
+   newpacket.data[10] = strlen( sn );
+
+   memcpy( &(newpacket.data[11]), sn, strlen( sn ) );
+
+   aim_tx_enqueue( &newpacket );
+
+   {
+      struct aim_snac_t snac;
+    
+      snac.id = aim_snac_nextid;
+      snac.family = 0x0003;
+      snac.type = 0x0005;
+      snac.flags = 0x0000;
+
+      snac.data = malloc( strlen( sn ) + 1 );
+      memcpy( snac.data, sn, strlen( sn ) + 1 );
+
+      aim_newsnac( &snac );
+   }
+
+   return( aim_snac_nextid++ );
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_chat.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,80 @@
+/*
+ * aim_chat.c
+ *
+ * Routines for the Chat service.  Nothing works (yet).
+ *
+ */
+
+#include "aim.h"
+
+/*
+ * FIXME: Doesn't work.
+ *
+ */
+u_long aim_chat_join(struct aim_conn_t *conn, const char *roomname)
+{
+  struct command_tx_struct newpacket;
+  
+  newpacket.lock = 1;
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+  newpacket.type = 0x0002;
+  
+  newpacket.commandlen = 12+7+strlen(roomname)+6;
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+  memset(newpacket.data, 0x00, newpacket.commandlen);
+
+  newpacket.data[0] = 0x00;
+  newpacket.data[1] = 0x01;
+
+  newpacket.data[2] = 0x00;
+  newpacket.data[3] = 0x04;
+
+  newpacket.data[4] = 0x00;
+  newpacket.data[5] = 0x00;
+
+  /* SNAC reqid */
+  newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF;
+  newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF;
+  newpacket.data[8] = (aim_snac_nextid >>  8) & 0xFF;
+  newpacket.data[9] = (aim_snac_nextid) & 0xFF;
+
+  newpacket.data[10] = 0x00;
+  newpacket.data[11] = 0x0e;
+  newpacket.data[12] = 0x00;
+  newpacket.data[13] = 0x01;
+  newpacket.data[14] = 0x00;
+  newpacket.data[15] = 0x0c;
+  newpacket.data[16] = 0x00;
+  newpacket.data[17] = 0x04;
+  newpacket.data[18] = strlen(roomname) & 0x00ff;
+  memcpy(&(newpacket.data[19]), roomname, strlen(roomname));
+  
+  {
+    int i = 0;
+    printf("\n\n\n");
+    for (i = 0;i < newpacket.commandlen; i++)
+      printf("0x%02x ", newpacket.data[i]);
+    printf("\n\n\n");
+  }
+
+  aim_tx_enqueue(&newpacket);
+
+  {
+    struct aim_snac_t snac;
+    
+    snac.id = aim_snac_nextid;
+    snac.family = 0x0001;
+    snac.type = 0x0004;
+    snac.flags = 0x0000;
+
+    snac.data = malloc(strlen(roomname));
+    memcpy(snac.data, roomname, strlen(roomname));
+
+    aim_newsnac(&snac);
+  }
+
+  return (aim_snac_nextid++);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_chatnav.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,9 @@
+/*
+ *
+ *
+ *
+ *
+ */
+
+#include "aim.h"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_conn.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,195 @@
+
+/*
+ *  aim_conn.c
+ *
+ * Does all this gloriously nifty connection handling stuff...
+ *
+ */
+
+#include "aim.h"
+
+void aim_connrst(void)
+{
+  int i;
+  for (i = 0; i < AIM_CONN_MAX; i++)
+    {
+      aim_conns[i].fd = -1;
+      aim_conns[i].type = -1;
+      aim_conns[i].status = 0;
+    }
+
+}
+
+struct aim_conn_t *aim_conn_getnext(void)
+{
+  int i;
+  for (i=0;i<AIM_CONN_MAX;i++)
+    if (aim_conns[i].fd == -1)
+      return &(aim_conns[i]);
+  return NULL;
+}
+
+void aim_conn_close(struct aim_conn_t *deadconn)
+{
+  if (deadconn->fd >= 3)
+    close(deadconn->fd);
+  deadconn->fd = -1;
+  deadconn->type = -1;
+}
+
+struct aim_conn_t *aim_getconn_type(int type)
+{
+  int i;
+  for (i=0; i<AIM_CONN_MAX; i++)
+    if (aim_conns[i].type == type)
+      return &(aim_conns[i]);
+  return NULL;
+}
+
+/*
+ * aim_newconn(type, dest)
+ *
+ * Opens a new connection to the specified dest host of type type.
+ *
+ * TODO: fix for proxies
+ * FIXME: Return errors in a more sane way.
+ *
+ */
+struct aim_conn_t *aim_newconn(int type, char *dest)
+{
+  struct aim_conn_t *connstruct;
+  int ret;
+  struct sockaddr_in sa;
+  struct hostent *hp;
+  int port = FAIM_LOGIN_PORT;
+  int i=0;
+  
+  if (!dest || ((connstruct=aim_conn_getnext())==NULL))
+    return NULL;
+
+  connstruct->type = type;
+
+  /* 
+   * As of 23 Jul 1999, AOL now sends the port number, preceded by a 
+   * colon, in the BOS redirect.  This fatally breaks all previous 
+   * libfaims.  Bad, bad AOL.
+   *
+   * We put this here to catch every case. 
+   *
+   */
+  for(i=0;(i<strlen(dest));i++)
+    if (dest[i] == ':') break; 
+  if (i<strlen(dest))
+      {
+	port = atoi(dest+i);
+	dest[i] = '\0';
+      }
+
+  hp = gethostbyname2(dest, AF_INET);
+  if (hp == NULL)
+    {
+      connstruct->status = (h_errno | AIM_CONN_STATUS_RESOLVERR);
+      return connstruct;
+    }
+
+  memset(&sa.sin_zero, 0, 8);
+  sa.sin_port = htons(port);
+  memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
+  sa.sin_family = hp->h_addrtype;
+  
+  connstruct->fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
+  ret = connect(connstruct->fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in));
+  if( ret < 0)
+    {
+      connstruct->fd = -1;
+      connstruct->status = (errno | AIM_CONN_STATUS_CONNERR);
+      return connstruct;
+    }
+
+  return connstruct;
+}
+
+int aim_conngetmaxfd(void)
+{
+  int i,j;
+  j=0;
+  for (i=0;i<AIM_CONN_MAX;i++)
+    if(aim_conns[i].fd > j)
+      j = aim_conns[i].fd;
+  return j;
+}
+
+int aim_countconn(void)
+{
+  int i,cnt;
+  cnt = 0;
+  for (i=0;i<AIM_CONN_MAX;i++)
+    if (aim_conns[i].fd > -1)
+      cnt++;
+  return cnt;
+}
+
+/*
+ * aim_select(timeout)
+ *
+ * Waits for a socket with data or for timeout, whichever comes first.
+ * See select(2).
+ * 
+ */ 
+struct aim_conn_t *aim_select(struct timeval *timeout)
+{
+  fd_set fds;
+  fd_set errfds;
+  int i;
+
+  if (aim_countconn() <= 0)
+    return 0;
+  
+  FD_ZERO(&fds);
+  FD_ZERO(&errfds);
+  
+  for(i=0;i<AIM_CONN_MAX;i++)
+    if (aim_conns[i].fd>-1)
+      {
+	FD_SET(aim_conns[i].fd, &fds);
+	FD_SET(aim_conns[i].fd, &errfds);
+      }
+  
+  i = select(aim_conngetmaxfd()+1, &fds, NULL, &errfds, timeout);
+  if (i>=1)
+    {
+      int j;
+      for (j=0;j<AIM_CONN_MAX;j++)
+	{
+	  if ((FD_ISSET(aim_conns[j].fd, &errfds)))
+	    {
+	      /* got an exception; close whats left of it up */
+	      aim_conn_close(&(aim_conns[j]));
+	      return (struct aim_conn_t *)-1;
+	    }
+	  else if ((FD_ISSET(aim_conns[j].fd, &fds)))
+	    return &(aim_conns[j]);  /* return the first waiting struct */
+	}
+      /* should never get here */
+    }
+  else
+    return (struct aim_conn_t *)i;  /* no waiting or error, return -- FIXME: return type funnies */
+  return NULL; /* NO REACH */
+}
+
+int aim_conn_isready(struct aim_conn_t *conn)
+{
+  if (conn)
+    return (conn->status & 0x0001);
+  else
+    return -1;
+}
+
+int aim_conn_setstatus(struct aim_conn_t *conn, int status)
+{
+  if (conn)
+    return (conn->status ^= status);
+  else
+    return -1;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_global.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,17 @@
+/*
+  aim_global.c
+
+  These are things that are globally required, but don't fit the
+  naming of the rest of the functions.  Namely, the queue ptrs and fds.
+
+ */
+
+#include "aim.h" 
+
+/* the dreaded global variables... */
+
+struct login_phase1_struct aim_logininfo;
+
+/* queue (linked list) pointers */
+struct command_tx_struct *aim_queue_outgoing = NULL; /* incoming commands */
+struct command_rx_struct *aim_queue_incoming = NULL; /* outgoing commands */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_im.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,253 @@
+/*
+ *  aim_im.c
+ *
+ *  The routines for sending/receiving Instant Messages.
+ *
+ */
+
+#include "aim.h"
+
+/*
+ * Send an ICBM (instant message).  
+ *
+ *
+ * Possible flags:
+ *   AIM_IMFLAGS_AWAY  -- Marks the message as an autoresponse
+ *   AIM_IMFLAGS_ACK   -- Requests that the server send an ack
+ *                        when the message is received (of type 0x0004/0x000c)
+ *
+ *
+ * TODO: Update to new standard form 
+ *
+ *
+ */
+
+u_long aim_send_im(struct aim_conn_t *conn, char *destsn, int flags, char *msg)
+{   
+
+  int curbyte;
+  struct command_tx_struct newpacket;
+  
+  newpacket.lock = 1; /* lock struct */
+  newpacket.type = 0x02; /* IMs are always family 0x02 */
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+
+  newpacket.commandlen = 20+1+strlen(destsn)+1+1+2+7+2+4+strlen(msg)+2;
+
+  if (flags & AIM_IMFLAGS_ACK)
+    newpacket.commandlen += 4;
+  if (flags & AIM_IMFLAGS_AWAY)
+    newpacket.commandlen += 4;
+
+  newpacket.data = (char *) calloc(1, newpacket.commandlen);
+
+  curbyte  = 0;
+  curbyte += aim_putsnac(newpacket.data+curbyte, 0x0004, 0x0006, 0x0000, aim_snac_nextid);
+  curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
+  curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
+  curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
+  curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
+  curbyte += aimutil_put16(newpacket.data+curbyte,0x0001);
+  curbyte += aimutil_put8(newpacket.data+curbyte,strlen(destsn));
+  curbyte += aimutil_putstr(newpacket.data+curbyte, destsn, strlen(destsn));
+
+  if (flags & AIM_IMFLAGS_ACK)
+    {
+      curbyte += aimutil_put16(newpacket.data+curbyte,0x0003);
+      curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
+    }
+
+  if (flags & AIM_IMFLAGS_AWAY)
+    {
+      curbyte += aimutil_put16(newpacket.data+curbyte,0x0004);
+      curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
+    }
+
+  curbyte += aimutil_put16(newpacket.data+curbyte,0x0002);
+  curbyte += aimutil_put16(newpacket.data+curbyte,strlen(msg)+0xf);
+  curbyte += aimutil_put16(newpacket.data+curbyte,0x0501);
+  curbyte += aimutil_put16(newpacket.data+curbyte,0x0001);
+  curbyte += aimutil_put16(newpacket.data+curbyte,0x0101);
+  curbyte += aimutil_put16(newpacket.data+curbyte,0x0101);
+  curbyte += aimutil_put8(newpacket.data+curbyte,0x01);
+  curbyte += aimutil_put16(newpacket.data+curbyte,strlen(msg)+4);
+  curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
+  curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
+  curbyte += aimutil_putstr(newpacket.data+curbyte, msg, strlen(msg));
+
+  aim_tx_enqueue(&newpacket);
+
+#ifdef USE_SNAC_FOR_IMS
+ {
+    struct aim_snac_t snac;
+
+    snac.id = aim_snac_nextid;
+    snac.family = 0x0004;
+    snac.type = 0x0006;
+    snac.flags = 0x0000;
+
+    snac.data = malloc(strlen(destsn)+1);
+    memcpy(snac.data, destsn, strlen(destsn)+1);
+
+    aim_newsnac(&snac);
+  }
+
+ aim_cleansnacs(60); /* clean out all SNACs over 60sec old */
+#endif
+
+  return (aim_snac_nextid++);
+}
+
+int aim_parse_incoming_im_middle(struct command_rx_struct *command)
+{
+  int i = 0;
+  char *srcsn = NULL;
+  char *msg = NULL;
+  unsigned int msglen = 0;
+  int warninglevel = 0;
+  int tlvcnt = 0;
+  int class = 0;
+  ulong membersince = 0;
+  ulong onsince = 0;
+  int idletime = 0;
+  int isautoreply = 0;
+
+  i = 20;
+  
+  srcsn = malloc(command->data[i] + 1);
+  memcpy(srcsn, &(command->data[i+1]), command->data[i]);
+  srcsn[(int)command->data[i]] = '\0';
+  
+  i += (int) command->data[i] + 1; /* add SN len */
+  
+  /* warning level */
+  warninglevel = (command->data[i] << 8);
+  warninglevel += (command->data[i+1]);
+  i += 2;
+  
+  tlvcnt = ((command->data[i++]) << 8) & 0xFF00;
+  tlvcnt += (command->data[i++]) & 0x00FF;
+  
+  /* a mini TLV parser */
+  {
+    int curtlv = 0;
+    int tlv1 = 0;
+
+    while (curtlv < tlvcnt)
+      {
+	if ((command->data[i] == 0x00) &&
+	    (command->data[i+1] == 0x01) )
+	  {
+	    if (tlv1)
+	      break;
+	    /* t(0001) = class */
+	    if (command->data[i+3] != 0x02)
+	      printf("faim: userinfo: **warning: strange v(%x) for t(1)\n", command->data[i+3]);
+	    class = ((command->data[i+4]) << 8) & 0xFF00;
+	    class += (command->data[i+5]) & 0x00FF;
+	    i += (2 + 2 + command->data[i+3]);
+	    tlv1++;
+	  }
+	else if ((command->data[i] == 0x00) &&
+		 (command->data[i+1] == 0x02))
+	  {
+	    /* t(0002) = member since date  */
+	    if (command->data[i+3] != 0x04)
+	      printf("faim: userinfo: **warning: strange v(%x) for t(2)\n", command->data[i+3]);
+
+	    membersince = ((command->data[i+4]) << 24) &  0xFF000000;
+	    membersince += ((command->data[i+5]) << 16) & 0x00FF0000;
+	    membersince += ((command->data[i+6]) << 8) &  0x0000FF00;
+	    membersince += ((command->data[i+7]) ) &      0x000000FF;
+	    i += (2 + 2 + command->data[i+3]);
+	  }
+	else if ((command->data[i] == 0x00) &&
+		 (command->data[i+1] == 0x03))
+	  {
+	    /* t(0003) = on since date  */
+	    if (command->data[i+3] != 0x04)
+	      printf("faim: userinfo: **warning: strange v(%x) for t(3)\n", command->data[i+3]);
+
+	    onsince = ((command->data[i+4]) << 24) &  0xFF000000;
+	    onsince += ((command->data[i+5]) << 16) & 0x00FF0000;
+	    onsince += ((command->data[i+6]) << 8) &  0x0000FF00;
+	    onsince += ((command->data[i+7]) ) &      0x000000FF;
+	    i += (2 + 2 + command->data[i+3]);
+	  }
+	else if ((command->data[i] == 0x00) &&
+		 (command->data[i+1] == 0x04) )
+	  {
+	    /* t(0004) = idle time */
+	    if (command->data[i+3] != 0x02)
+	      printf("faim: userinfo: **warning: strange v(%x) for t(4)\n", command->data[i+3]);
+	    idletime = ((command->data[i+4]) << 8) & 0xFF00;
+	    idletime += (command->data[i+5]) & 0x00FF;
+	    i += (2 + 2 + command->data[i+3]);
+	  }  
+	else
+	  {
+	    printf("faim: userinfo: **warning: unexpected TLV t(%02x%02x) l(%02x%02x)\n", command->data[i], command->data[i+1], command->data[i+2], command->data[i+3]);
+	    i += (2 + 2 + command->data[i+3]);
+	  }
+	curtlv++;
+      }
+  }
+
+  {
+    /* detect if this is an auto-response or not */
+    /*   auto-responses can be detected by the presence of a *second* TLV with
+	 t(0004), but of zero length (and therefore no value portion) */
+    struct aim_tlv_t *tsttlv = NULL;
+    tsttlv = aim_grabtlv((u_char *) &(command->data[i]));
+    if (tsttlv->type == 0x04)
+      isautoreply = 1;
+    aim_freetlv(&tsttlv);
+  }
+  
+  i += 2;
+  
+  i += 2; /* skip first msglen */
+  i += 7; /* skip garbage */
+  i -= 4;
+
+  /* oh boy is this terrible...  this comes from a specific of the spec */
+  while(1)
+    {
+      if ( ( (command->data[i] == 0x00) &&
+	     (command->data[i+1] == 0x00) &&
+	     (command->data[i+2] == 0x00) &&
+	     (command->data[i+3] == 0x00) ) &&
+	   (i < command->commandlen) ) /* prevent infinity */
+	break;
+      else
+	i++;
+    }
+
+  i -= 2;
+  
+  if ( (command->data[i] == 0x00) &&
+       (command->data[i+1] == 0x00) )
+    i += 2;
+
+  msglen = ( (( (unsigned int) command->data[i]) & 0xFF ) << 8);
+  msglen += ( (unsigned int) command->data[i+1]) & 0xFF; /* mask off garbage */
+  i += 2;
+
+  msglen -= 4; /* skip four 0x00s */
+  i += 4;
+  
+  msg = malloc(msglen +1);
+  
+  memcpy(msg, &(command->data[i]), msglen);
+  msg[msglen] = '\0'; 
+
+  i = (aim_callbacks[AIM_CB_INCOMING_IM])(command, srcsn, msg, warninglevel, class, membersince, onsince, idletime, isautoreply);
+
+  free(srcsn);
+  free(msg);
+
+  return i;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_info.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,220 @@
+/*
+  aim_info.c
+
+  The functions here are responsible for requesting and parsing information-
+  gathering SNACs.  
+  
+ */
+
+
+#include "aim.h" /* for most everything */
+
+u_long aim_getinfo(struct aim_conn_t *conn, const char *sn)
+{
+  struct command_tx_struct newpacket;
+
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+
+  newpacket.lock = 1;
+  newpacket.type = 0x0002;
+
+  newpacket.commandlen = 12 + 1 + strlen(sn);
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+
+  newpacket.data[0] = 0x00;
+  newpacket.data[1] = 0x02;
+  newpacket.data[2] = 0x00;
+  newpacket.data[3] = 0x05;
+  newpacket.data[4] = 0x00;
+  newpacket.data[5] = 0x00;
+
+  /* SNAC reqid */
+  newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF;
+  newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF;
+  newpacket.data[8] = (aim_snac_nextid >>  8) & 0xFF;
+  newpacket.data[9] = (aim_snac_nextid) & 0xFF;
+
+  /* TLV: Screen Name */
+  /* t(0x0001) */
+  newpacket.data[10] = 0x00;
+  newpacket.data[11] = 0x01; 
+  /* l() */
+  newpacket.data[12] = strlen(sn);
+  /* v() */
+  memcpy(&(newpacket.data[13]), sn, strlen(sn));
+
+  aim_tx_enqueue(&newpacket);
+
+  {
+    struct aim_snac_t snac;
+    
+    snac.id = aim_snac_nextid;
+    snac.family = 0x0002;
+    snac.type = 0x0005;
+    snac.flags = 0x0000;
+
+    snac.data = malloc(strlen(sn)+1);
+    memcpy(snac.data, sn, strlen(sn)+1);
+
+    aim_newsnac(&snac);
+  }
+
+  return (aim_snac_nextid++);
+}
+
+/*
+ * This parses the user info stuff out all nice and pretty then calls 
+ * the higher-level callback (in the user app).
+ *
+ */
+
+int aim_parse_userinfo_middle(struct command_rx_struct *command)
+{
+  char *sn = NULL;
+  char *prof_encoding = NULL;
+  char *prof = NULL;
+  u_short warnlevel = 0x0000;
+  u_short idletime = 0x0000;
+  u_short class = 0x0000;
+  u_long membersince = 0x00000000;
+  u_long onlinesince = 0x00000000;
+  int tlvcnt = 0;
+  int i = 0;
+
+  {
+    u_long snacid = 0x000000000;
+    struct aim_snac_t *snac = NULL;
+
+    snacid = (command->data[6] << 24) & 0xFF000000;
+    snacid+= (command->data[7] << 16) & 0x00FF0000;
+    snacid+= (command->data[8] <<  8) & 0x0000FF00;
+    snacid+= (command->data[9])       & 0x000000FF;
+
+    snac = aim_remsnac(snacid);
+
+    free(snac->data);
+    free(snac);
+
+  }
+
+  sn = (char *) malloc(command->data[10]+1);
+  memcpy(sn, &(command->data[11]), command->data[10]);
+  sn[(int)command->data[10]] = '\0';
+  
+  i = 11 + command->data[10];
+  warnlevel = ((command->data[i++]) << 8) & 0xFF00;
+  warnlevel += (command->data[i++]) & 0x00FF;
+
+  tlvcnt = ((command->data[i++]) << 8) & 0xFF00;
+  tlvcnt += (command->data[i++]) & 0x00FF;
+
+  /* a mini TLV parser */
+  {
+    int curtlv = 0;
+    int tlv1 = 0;
+
+    while (curtlv < tlvcnt)
+      {
+	if ((command->data[i] == 0x00) &&
+	    (command->data[i+1] == 0x01) )
+	  {
+	    if (tlv1)
+	      break;
+	    /* t(0001) = class */
+	    class = ((command->data[i+4]) << 8) & 0xFF00;
+	    class += (command->data[i+5]) & 0x00FF;
+	    i += (2 + 2 + command->data[i+3]);
+	    tlv1++;
+	  }
+	else if ((command->data[i] == 0x00) &&
+		 (command->data[i+1] == 0x02))
+	  {
+	    /* t(0002) = member since date  */
+	    if (command->data[i+3] != 0x04)
+	      printf("faim: userinfo: **warning: strange v(%x) for t(2)\n", command->data[i+3]);
+
+	    membersince = ((command->data[i+4]) << 24) &  0xFF000000;
+	    membersince += ((command->data[i+5]) << 16) & 0x00FF0000;
+	    membersince += ((command->data[i+6]) << 8) &  0x0000FF00;
+	    membersince += ((command->data[i+7]) ) &      0x000000FF;
+	    i += (2 + 2 + command->data[i+3]);
+	  }
+	else if ((command->data[i] == 0x00) &&
+		 (command->data[i+1] == 0x03))
+	  {
+	    /* t(0003) = on since date  */
+	    if (command->data[i+3] != 0x04)
+	      printf("faim: userinfo: **warning: strange v(%x) for t(3)\n", command->data[i+3]);
+
+	    onlinesince = ((command->data[i+4]) << 24) &  0xFF000000;
+	    onlinesince += ((command->data[i+5]) << 16) & 0x00FF0000;
+	    onlinesince += ((command->data[i+6]) << 8) &  0x0000FF00;
+	    onlinesince += ((command->data[i+7]) ) &      0x000000FF;
+	    i += (2 + 2 + command->data[i+3]);
+	  }
+	else if ((command->data[i] == 0x00) &&
+		 (command->data[i+1] == 0x04) )
+	  {
+	    /* t(0004) = idle time */
+	    if (command->data[i+3] != 0x02)
+	      printf("faim: userinfo: **warning: strange v(%x) for t(4)\n", command->data[i+3]);
+	    idletime = ((command->data[i+4]) << 8) & 0xFF00;
+	    idletime += (command->data[i+5]) & 0x00FF;
+	    i += (2 + 2 + command->data[i+3]);
+	  }  
+	else
+	  {
+	    printf("faim: userinfo: **warning: unexpected TLV t(%02x%02x) l(%02x%02x)\n", command->data[i], command->data[i+1], command->data[i+2], command->data[i+3]);
+	    i += (2 + 2 + command->data[i+3]);
+	  }
+	curtlv++;
+      }
+  }
+  if (i < command->commandlen)
+    {
+      if ( (command->data[i] == 0x00) &&
+	   (command->data[i+1] == 0x01) )
+	{
+	  int len = 0;
+	  
+	  len = ((command->data[i+2] << 8) & 0xFF00);
+	  len += (command->data[i+3]) & 0x00FF;
+	  
+	  prof_encoding = (char *) malloc(len+1);
+	  memcpy(prof_encoding, &(command->data[i+4]), len);
+	  prof_encoding[len] = '\0';
+	  
+	  i += (2+2+len);
+	}
+      else
+	{
+	  printf("faim: userinfo: **warning: unexpected TLV after TLVblock t(%02x%02x) l(%02x%02x)\n", command->data[i], command->data[i+1], command->data[i+2], command->data[i+3]);
+	  i += 2 + 2 + command->data[i+3];
+	}
+    }
+
+  if (i < command->commandlen)
+    {
+      int len = 0;
+
+      len = ((command->data[i+2]) << 8) & 0xFF00;
+      len += (command->data[i+3]) & 0x00FF;
+
+      prof = (char *) malloc(len+1);
+      memcpy(prof, &(command->data[i+4]), len);
+      prof[len] = '\0';
+    }
+  else
+    printf("faim: userinfo: **early parse abort...no profile?\n");
+
+  i = (aim_callbacks[AIM_CB_USERINFO])(command, sn, prof_encoding, prof, warnlevel, idletime, class, membersince, onlinesince);
+
+  free(sn);
+  free(prof_encoding);
+  free(prof);
+
+  return i;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_login.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,142 @@
+/*
+ *  aim_login.c
+ *
+ *  This contains all the functions needed to actually login.
+ *
+ */
+
+#include "aim.h"
+
+
+/*
+ * FIXME: Reimplement the TIS stuff.
+ */
+#ifdef TIS_TELNET_PROXY
+#include "tis_telnet_proxy.h"
+#endif
+
+/*
+ *  send_login(int socket, char *sn, char *password)
+ *  
+ * This is the initial login request packet.
+ *
+ * The password is encoded before transmition, as per
+ * encode_password().  See that function for their
+ * stupid method of doing it.
+ *
+ *
+ *
+ */
+int aim_send_login (struct aim_conn_t *conn, char *sn, char *password, struct client_info_s *clientinfo)
+{
+  char *password_encoded = NULL;  /* to store encoded password */
+  int curbyte=0;
+
+  struct command_tx_struct newpacket;
+
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_AUTH);
+
+  newpacket.commandlen = 6+2+strlen(sn)+1+1+2+strlen(password)+6;
+
+  if (clientinfo)
+    {
+      if (strlen(clientinfo->clientstring))
+	newpacket.commandlen += strlen(clientinfo->clientstring)+4;
+      newpacket.commandlen += 6+6+6; 
+      if (strlen(clientinfo->country))
+	newpacket.commandlen += strlen(clientinfo->country)+4;
+      if (strlen(clientinfo->lang))
+	newpacket.commandlen += strlen(clientinfo->lang)+4;
+    }
+
+  newpacket.data = (char *) calloc (1,  newpacket.commandlen );
+  newpacket.lock = 1;
+  newpacket.type = 0x01;
+
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0000);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001);
+  curbyte += aimutil_put16(newpacket.data+curbyte, strlen(sn));
+  curbyte += aimutil_putstr(newpacket.data+curbyte, sn, strlen(sn));
+
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0002);
+  curbyte += aimutil_put16(newpacket.data+curbyte, strlen(password));
+  password_encoded = (char *) malloc(strlen(password));
+  aim_encode_password(password, password_encoded);
+  curbyte += aimutil_putstr(newpacket.data+curbyte, password_encoded, strlen(password));
+  free(password_encoded);
+  
+  curbyte += aim_puttlv_16(newpacket.data+curbyte, 0x0016, 0x0001);
+
+  if (clientinfo)
+    {
+      if (strlen(clientinfo->clientstring))
+	{
+	  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0003);
+	  curbyte += aimutil_put16(newpacket.data+curbyte, strlen(clientinfo->clientstring));
+	  curbyte += aimutil_putstr(newpacket.data+curbyte, clientinfo->clientstring, strlen(clientinfo->clientstring));
+	}
+      curbyte += aim_puttlv_16(newpacket.data+curbyte, 0x0017, 0x0001);
+      curbyte += aim_puttlv_16(newpacket.data+curbyte, 0x0018, 0x0001);
+      curbyte += aim_puttlv_16(newpacket.data+curbyte, 0x001a, 0x0013);
+      if (strlen(clientinfo->country))
+	{
+	  curbyte += aimutil_put16(newpacket.data+curbyte, 0x000e);
+	  curbyte += aimutil_put16(newpacket.data+curbyte, strlen(clientinfo->country));
+	  curbyte += aimutil_putstr(newpacket.data+curbyte, clientinfo->country, strlen(clientinfo->country));
+	}
+       if (strlen(clientinfo->lang))
+	{
+	  curbyte += aimutil_put16(newpacket.data+curbyte, 0x000f);
+	  curbyte += aimutil_put16(newpacket.data+curbyte, strlen(clientinfo->lang));
+	  curbyte += aimutil_putstr(newpacket.data+curbyte, clientinfo->lang, strlen(clientinfo->lang));
+	}
+    }
+
+  curbyte += aim_puttlv_16(newpacket.data+curbyte, 0x0009, 0x0015);
+
+  newpacket.lock = 0;
+  aim_tx_enqueue(&newpacket);
+
+  return 0;
+}
+
+/*
+ *  int encode_password(
+ *                      const char *password,
+ *	                char *encoded
+ *	                ); 
+ *
+ * This takes a const pointer to a (null terminated) string
+ * containing the unencoded password.  It also gets passed
+ * an already allocated buffer to store the encoded password.
+ * This buffer should be the exact length of the password without
+ * the null.  The encoded password buffer IS NOT NULL TERMINATED.
+ *
+ * The encoding_table seems to be a fixed set of values.  We'll
+ * hope it doesn't change over time!  
+ *
+ */
+int aim_encode_password(const char *password, char *encoded)
+{
+  char encoding_table[] = {
+    0xf3, 0xb3, 0x6c, 0x99,
+    0x95, 0x3f, 0xac, 0xb6,
+    0xc5, 0xfa, 0x6b, 0x63,
+    0x69, 0x6c, 0xc3, 0x9f
+  };
+
+  int i;
+  
+  for (i = 0; i < strlen(password); i++)
+      encoded[i] = (password[i] ^ encoding_table[i]);
+
+  return 0;
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_logoff.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,28 @@
+/*
+ * aim_logoff.c
+ *
+ *
+ */
+
+#include "aim.h"
+
+/* 
+ * aim_logoff()
+ * 
+ * Closes -ALL- open connections.
+ *
+ */
+int aim_logoff(void)
+{
+  int i = AIM_CONN_MAX-1;
+  while (i > -1)
+    {
+      if (aim_conns[i].fd>-1)
+	aim_conn_close(&(aim_conns[i]));
+      i--;
+    }
+  aim_connrst();  /* in case we want to connect again */
+
+  return 0;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_misc.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,674 @@
+
+/*
+ * aim_misc.c
+ *
+ * TODO: Seperate a lot of this into an aim_bos.c.
+ *
+ * Other things...
+ *
+ *   - Idle setting 
+ * 
+ *
+ */
+
+#include "aim.h"
+
+/*
+ * aim_bos_setidle()
+ *
+ *  Should set your current idle time in seconds.  Idealy, OSCAR should
+ *  do this for us.  But, it doesn't.  The client must call this to set idle
+ *  time.  
+ *
+ */
+u_long aim_bos_setidle(struct aim_conn_t *conn, u_long idletime)
+{
+  return aim_genericreq_l(conn, 0x0001, 0x0011, &idletime);
+}
+
+
+/*
+ * aim_bos_changevisibility(conn, changtype, namelist)
+ *
+ * Changes your visibility depending on changetype:
+ *
+ *  AIM_VISIBILITYCHANGE_PERMITADD: Lets provided list of names see you
+ *  AIM_VISIBILITYCHANGE_PERMIDREMOVE: Removes listed names from permit list
+ *  AIM_VISIBILITYCHANGE_DENYADD: Hides you from provided list of names
+ *  AIM_VISIBILITYCHANGE_DENYREMOVE: Lets list see you again
+ *
+ * list should be a list of 
+ * screen names in the form "Screen Name One&ScreenNameTwo&" etc.
+ *
+ * Equivelents to options in WinAIM:
+ *   - Allow all users to contact me: Send an AIM_VISIBILITYCHANGE_DENYADD
+ *      with only your name on it.
+ *   - Allow only users on my Buddy List: Send an 
+ *      AIM_VISIBILITYCHANGE_PERMITADD with the list the same as your
+ *      buddy list
+ *   - Allow only the uesrs below: Send an AIM_VISIBILITYCHANGE_PERMITADD 
+ *      with everyone listed that you want to see you.
+ *   - Block all users: Send an AIM_VISIBILITYCHANGE_PERMITADD with only 
+ *      yourself in the list
+ *   - Block the users below: Send an AIM_VISIBILITYCHANGE_DENYADD with
+ *      the list of users to be blocked
+ *
+ *
+ */
+u_long aim_bos_changevisibility(struct aim_conn_t *conn, int changetype, char *denylist)
+{
+  struct command_tx_struct newpacket;
+
+  char *localcpy = NULL;
+  char *tmpptr = NULL;
+  char *tmpptr2 = NULL;
+  int i,j;
+
+  if (!denylist)
+    return 0;
+
+  newpacket.lock = 1;
+
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+
+  newpacket.type = 0x02;
+  newpacket.commandlen = 10;
+
+  localcpy = (char *) malloc(strlen(denylist)+1);
+  memcpy(localcpy, denylist, strlen(denylist)+1);
+  tmpptr2 = localcpy; /* save this for the free() */
+
+  i = 0;
+  tmpptr = strsep(&localcpy, "&");
+  while (strlen(tmpptr) && (i < 100))
+    {
+      newpacket.commandlen += strlen(tmpptr)+1;
+      i++;
+      tmpptr = strsep(&localcpy, "&");
+    }
+  free(tmpptr2);
+  tmpptr2 = NULL;
+
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+  memset(newpacket.data, 0x00, newpacket.commandlen);
+
+  newpacket.data[0] = 0x00;
+  newpacket.data[1] = 0x09;
+  newpacket.data[2] = 0x00;
+  switch(changetype)
+    {
+    case AIM_VISIBILITYCHANGE_PERMITADD:
+      newpacket.data[3] = 0x05; break;
+    case AIM_VISIBILITYCHANGE_PERMITREMOVE:
+      newpacket.data[3] = 0x06; break;
+    case AIM_VISIBILITYCHANGE_DENYADD:
+      newpacket.data[3] = 0x07; break;
+    case AIM_VISIBILITYCHANGE_DENYREMOVE:
+      newpacket.data[4] = 0x08; break;
+    default:
+      return 0;
+    }
+  /* SNAC reqid -- we actually DO NOT send a SNAC ID with this one! */
+  newpacket.data[6] = 0;
+  newpacket.data[7] = 0;
+  newpacket.data[8] = 0;
+  newpacket.data[9] = 0;
+ 
+  j = 10;  /* the next byte */
+
+  localcpy = (char *) malloc(strlen(denylist)+1);
+  memcpy(localcpy, denylist, strlen(denylist)+1);
+  tmpptr2 = localcpy; /* save this for the free() */
+
+  i = 0;
+  tmpptr = strsep(&localcpy, "&");
+  while (strlen(tmpptr) && (i < 100))
+    {
+      newpacket.data[j] = strlen(tmpptr);
+      memcpy(&(newpacket.data[j+1]), tmpptr, strlen(tmpptr));
+      j += strlen(tmpptr)+1;
+      i++;
+      tmpptr = strsep(&localcpy, "&");
+    }
+  free(tmpptr2);
+
+  newpacket.lock = 0;
+
+  aim_tx_enqueue(&newpacket);
+
+  return (aim_snac_nextid); /* dont increment */
+
+}
+
+
+
+/*
+ * aim_bos_setbuddylist(buddylist)
+ *
+ * This just builds the "set buddy list" command then queues it.
+ *
+ * buddy_list = "Screen Name One&ScreenNameTwo&";
+ *
+ * TODO: Clean this up.
+ *
+ */
+u_long aim_bos_setbuddylist(struct aim_conn_t *conn, char *buddy_list)
+{
+  int i, j;
+
+  struct command_tx_struct newpacket;
+
+  int packet_login_phase3c_hi_b_len = 0;
+
+  char *localcpy = NULL;
+  char *tmpptr = NULL;
+
+  packet_login_phase3c_hi_b_len = 16; /* 16b for FLAP and SNAC headers */
+
+  /* bail out if we can't make the packet */
+  if (buddy_list == NULL)
+    {
+      printf("\nNO BUDDIES!  ARE YOU THAT LONELY???\n");
+      return 0;
+    }
+#if debug > 0
+  printf("****buddy list: %s\n", buddy_list);
+  printf("****buddy list len: %d (%x)\n", strlen(buddy_list), strlen(buddy_list));
+#endif
+
+  localcpy = (char *) malloc(strlen(buddy_list)+1);
+  memcpy(localcpy, buddy_list, strlen(buddy_list)+1);
+
+  i = 0;
+  tmpptr = strtok(localcpy, "&");
+  while ((tmpptr != NULL) && (i < 100))
+    {
+#if debug > 0
+      printf("---adding %s (%d)\n", tmpptr, strlen(tmpptr));
+#endif
+      packet_login_phase3c_hi_b_len += strlen(tmpptr)+1;
+      i++;
+      tmpptr = strtok(NULL, "&");
+    }
+#if debug > 0
+  printf("*** send buddy list len: %d (%x)\n", packet_login_phase3c_hi_b_len, packet_login_phase3c_hi_b_len);
+#endif
+  free(localcpy);
+
+  newpacket.type = 0x02;
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+  newpacket.commandlen = packet_login_phase3c_hi_b_len - 6;
+  newpacket.lock = 1;
+  
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+
+  newpacket.data[0] = 0x00;
+  newpacket.data[1] = 0x03;
+  newpacket.data[2] = 0x00;
+  newpacket.data[3] = 0x04;
+  newpacket.data[4] = 0x00;
+  newpacket.data[5] = 0x00;
+  /* SNAC reqid */
+  newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF;
+  newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF;
+  newpacket.data[8] = (aim_snac_nextid >>  8) & 0xFF;
+  newpacket.data[9] = (aim_snac_nextid) & 0xFF;
+
+  j = 10;  /* the next byte */
+
+  i = 0;
+  tmpptr = strtok(buddy_list, "&");
+  while ((tmpptr != NULL) & (i < 100))
+    {
+#if debug > 0
+      printf("---adding %s (%d)\n", tmpptr, strlen(tmpptr));
+#endif
+      newpacket.data[j] = strlen(tmpptr);
+      memcpy(&(newpacket.data[j+1]), tmpptr, strlen(tmpptr));
+      j += strlen(tmpptr)+1;
+      i++;
+      tmpptr = strtok(NULL, "&");
+    }
+
+  newpacket.lock = 0;
+
+  aim_tx_enqueue(&newpacket);
+
+  return (aim_snac_nextid++);
+}
+
+/* 
+ * aim_bos_setprofile(profile)
+ *
+ * Gives BOS your profile.
+ *
+ */
+u_long aim_bos_setprofile(struct aim_conn_t *conn, char *profile)
+{
+  int packet_profile_len = 0;
+  struct command_tx_struct newpacket;
+  int i = 0;
+
+  /* len: SNAC */
+  packet_profile_len = 10;
+  /* len: T+L (where t(0001)) */
+  packet_profile_len += 2 + 2;
+  /* len: V (where t(0001)) */
+  packet_profile_len += strlen("text/x-aolrtf");
+  /* len: T+L (where t(0002)) */
+  packet_profile_len += 2 + 2;
+  /* len: V (where t(0002)) */
+  packet_profile_len += strlen(profile);
+
+  newpacket.type = 0x02;
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+  newpacket.commandlen = packet_profile_len;
+  newpacket.data = (char *) malloc(packet_profile_len);
+
+  i = 0;
+  /* SNAC: family */
+  newpacket.data[i++] = 0x00;
+  newpacket.data[i++] = 0x02;
+  /* SNAC: subtype */
+  newpacket.data[i++] = 0x00;
+  newpacket.data[i++] = 0x04;
+  /* SNAC: flags */
+  newpacket.data[i++] = 0x00;
+  newpacket.data[i++] = 0x00;
+  /* SNAC: id */
+  /* SNAC reqid */
+  newpacket.data[i++] = (aim_snac_nextid >> 24) & 0xFF;
+  newpacket.data[i++] = (aim_snac_nextid >> 16) & 0xFF;
+  newpacket.data[i++] = (aim_snac_nextid >>  8) & 0xFF;
+  newpacket.data[i++] = (aim_snac_nextid) & 0xFF;
+  /* TLV t(0001) */
+  newpacket.data[i++] = 0x00;
+  newpacket.data[i++] = 0x01;
+  /* TLV l(000d) */
+  newpacket.data[i++] = 0x00;
+  newpacket.data[i++] = 0x0d;
+  /* TLV v(text/x-aolrtf) */
+  memcpy(&(newpacket.data[i]), "text/x-aolrtf", 0x000d);
+  i += 0x000d;
+  
+  /* TLV t(0002) */
+  newpacket.data[i++] = 0x00;
+  newpacket.data[i++] = 0x02;
+  /* TLV l() */
+  newpacket.data[i++] = (strlen(profile) >> 8) & 0xFF;
+  newpacket.data[i++] = (strlen(profile) & 0xFF);
+  /* TLV v(profile) */
+  memcpy(&(newpacket.data[i]), profile, strlen(profile));
+
+  aim_tx_enqueue(&newpacket);
+  
+  return (aim_snac_nextid++);
+}
+
+/* 
+ * aim_bos_setgroupperm(mask)
+ * 
+ * Set group permisson mask.  Normally 0x1f.
+ *
+ */
+u_long aim_bos_setgroupperm(struct aim_conn_t *conn, u_long mask)
+{
+  return aim_genericreq_l(conn, 0x0009, 0x0004, &mask);
+}
+
+/*
+ * aim_bos_clientready()
+ * 
+ * Send Client Ready.  
+ *
+ * TODO: Dynamisize.
+ *
+ */
+u_long aim_bos_clientready(struct aim_conn_t *conn)
+{
+  char command_2[] = {
+     0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x7a, 0x8c,
+     0x11, 0xab, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01,
+     0x00, 0x13, 0x00, 0x09, 0x00, 0x01, 0x00, 0x01,
+     0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01,
+     0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x01,
+     0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01,
+     0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,
+     0x00, 0x01, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01,
+     0x00, 0x01, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x01,
+     0x00, 0x01, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x01,
+     0x00, 0x01
+  };
+  int command_2_len = 0x52;
+  struct command_tx_struct newpacket;
+  
+  newpacket.lock = 1;
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+  newpacket.type = 0x02;
+  newpacket.commandlen = command_2_len;
+  newpacket.data = (char *) malloc (newpacket.commandlen);
+  memcpy(newpacket.data, command_2, newpacket.commandlen);
+  
+  /* SNAC reqid */
+  newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF;
+  newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF;
+  newpacket.data[8] = (aim_snac_nextid >>  8) & 0xFF;
+  newpacket.data[9] = (aim_snac_nextid) & 0xFF;
+
+  aim_tx_enqueue(&newpacket);
+
+  return (aim_snac_nextid++);
+}
+
+/* 
+ *  send_login_phase3(int socket)   
+ *
+ *  Request Rate Information.
+ * 
+ *  TODO: Move to aim_conn.
+ *  TODO: Move to SNAC interface.
+ */
+u_long aim_bos_reqrate(struct aim_conn_t *conn)
+{
+  return aim_genericreq_n(conn, 0x0001, 0x0006);
+}
+
+/* 
+ *  send_login_phase3b(int socket)   
+ *
+ *  Rate Information Response Acknowledge.
+ *
+ */
+u_long aim_bos_ackrateresp(struct aim_conn_t *conn)
+{
+  struct command_tx_struct newpacket;
+
+  newpacket.lock = 1;
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+  newpacket.type = 0x02;
+  newpacket.commandlen = 18;
+
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+  newpacket.data[0] = 0x00;
+  newpacket.data[1] = 0x01;
+  newpacket.data[2] = 0x00;
+  newpacket.data[3] = 0x08;
+  newpacket.data[4] = 0x00;
+  newpacket.data[5] = 0x00;
+  /* SNAC reqid */
+  newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF;
+  newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF;
+  newpacket.data[8] = (aim_snac_nextid >>  8) & 0xFF;
+  newpacket.data[9] = (aim_snac_nextid) & 0xFF;
+
+  newpacket.data[10] = 0x00;
+  newpacket.data[11] = 0x01;
+  newpacket.data[12] = 0x00;
+  newpacket.data[13] = 0x02;
+  newpacket.data[14] = 0x00;
+  newpacket.data[15] = 0x03;
+  newpacket.data[16] = 0x00;
+  newpacket.data[17] = 0x04;
+
+  aim_tx_enqueue(&newpacket);
+
+  return (aim_snac_nextid++);
+}
+
+/* 
+ * aim_bos_setprivacyflags()
+ *
+ * Sets privacy flags. Normally 0x03.
+ *
+ *  Bit 1:  Allows other AIM users to see how long you've been idle.
+ *
+ *
+ */
+u_long aim_bos_setprivacyflags(struct aim_conn_t *conn, u_long flags)
+{
+  return aim_genericreq_l(conn, 0x0001, 0x0014, &flags);
+}
+
+/*
+ * aim_bos_reqpersonalinfo()
+ *
+ * Requests the current user's information. Can't go generic on this one
+ * because aparently it uses SNAC flags.
+ *
+ */
+u_long aim_bos_reqpersonalinfo(struct aim_conn_t *conn)
+{
+  struct command_tx_struct newpacket;
+  
+  newpacket.lock = 1;
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+  newpacket.type = 0x02;
+  newpacket.commandlen = 12;
+
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+  
+  newpacket.data[0] = 0x00;
+  newpacket.data[1] = 0x0a;
+  newpacket.data[2] = 0x00;
+  newpacket.data[3] = 0x01;
+  newpacket.data[4] = 0x00;
+  newpacket.data[5] = 0x0e; /* huh? */
+
+  /* SNAC reqid */
+  newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF;
+  newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF;
+  newpacket.data[8] = (aim_snac_nextid >>  8) & 0xFF;
+  newpacket.data[9] = (aim_snac_nextid) & 0xFF;
+
+  newpacket.data[10] = 0x0d;
+  newpacket.data[11] = 0xda;
+
+  aim_tx_enqueue(&newpacket);
+
+  return (aim_snac_nextid++);
+}
+
+/*
+ * aim_bos_reqservice(serviceid)
+ *
+ * Service request. 
+ *
+ */
+u_long aim_bos_reqservice(struct aim_conn_t *conn, u_short serviceid)
+{
+  return aim_genericreq_s(conn, 0x0001, 0x0004, &serviceid);
+}
+
+/*
+ * aim_bos_reqrights()
+ *
+ * Request BOS rights.
+ *
+ */
+u_long aim_bos_reqrights(struct aim_conn_t *conn)
+{
+  return aim_genericreq_n(conn, 0x0009, 0x0002);
+}
+
+/*
+ * aim_bos_reqbuddyrights()
+ *
+ * Request Buddy List rights.
+ *
+ */
+u_long aim_bos_reqbuddyrights(struct aim_conn_t *conn)
+{
+  return aim_genericreq_n(conn, 0x0003, 0x0002);
+}
+
+/*
+ * Generic routine for sending commands.
+ *
+ *
+ * I know I can do this in a smarter way...but I'm not thinking straight
+ * right now...
+ *
+ * I had one big function that handled all three cases, but then it broke
+ * and I split it up into three.  But then I fixed it.  I just never went
+ * back to the single.  I don't see any advantage to doing it either way.
+ *
+ */
+u_long aim_genericreq_n(struct aim_conn_t *conn, u_short family, u_short subtype)
+{
+  struct command_tx_struct newpacket;
+
+  newpacket.lock = 1;
+
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+  newpacket.type = 0x02;
+
+  newpacket.commandlen = 10;
+
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+  memset(newpacket.data, 0x00, newpacket.commandlen);
+  newpacket.data[0] = (family & 0xff00)>>8;
+  newpacket.data[1] = family & 0xff;
+  newpacket.data[2] = (subtype & 0xff00)>>8;
+  newpacket.data[3] = subtype & 0xff;
+  newpacket.data[4] = 0x00;
+  newpacket.data[5] = 0x00;
+  /* SNAC reqid */
+  newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF;
+  newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF;
+  newpacket.data[8] = (aim_snac_nextid >>  8) & 0xFF;
+  newpacket.data[9] = (aim_snac_nextid) & 0xFF;
+
+  aim_tx_enqueue(&newpacket);
+  return (aim_snac_nextid++);
+}
+
+/*
+ *
+ *
+ */
+u_long aim_genericreq_l(struct aim_conn_t *conn, u_short family, u_short subtype, u_long *longdata)
+{
+  struct command_tx_struct newpacket;
+  u_long newlong;
+
+  /* If we don't have data, there's no reason to use this function */
+  if (!longdata)
+    return aim_genericreq_n(conn, family, subtype);
+
+  newpacket.lock = 1;
+
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+  newpacket.type = 0x02;
+
+  newpacket.commandlen = 10+sizeof(u_long);
+
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+  memset(newpacket.data, 0x00, newpacket.commandlen);
+
+  newpacket.data[0] = (family & 0xff00)>>8;
+  newpacket.data[1] = family & 0xff;
+  newpacket.data[2] = (subtype & 0xff00)>>8;
+  newpacket.data[3] = subtype & 0xff;
+  newpacket.data[4] = 0x00;
+  newpacket.data[5] = 0x00;
+  /* SNAC reqid */
+  newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF;
+  newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF;
+  newpacket.data[8] = (aim_snac_nextid >>  8) & 0xFF;
+  newpacket.data[9] = (aim_snac_nextid) & 0xFF;
+
+  /* copy in data */
+  newlong = htonl(*longdata);
+  memcpy(&(newpacket.data[10]), &newlong, sizeof(u_long));
+
+  aim_tx_enqueue(&newpacket);
+  return (aim_snac_nextid++);
+}
+
+u_long aim_genericreq_s(struct aim_conn_t *conn, u_short family, u_short subtype, u_short *shortdata)
+{
+  struct command_tx_struct newpacket;
+  u_short newshort;
+
+  /* If we don't have data, there's no reason to use this function */
+  if (!shortdata)
+    return aim_genericreq_n(conn, family, subtype);
+
+  newpacket.lock = 1;
+
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+  newpacket.type = 0x02;
+
+  newpacket.commandlen = 10+sizeof(u_short);
+
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+  memset(newpacket.data, 0x00, newpacket.commandlen);
+
+  newpacket.data[0] = (family & 0xff00)>>8;
+  newpacket.data[1] = family & 0xff;
+  newpacket.data[2] = (subtype & 0xff00)>>8;
+  newpacket.data[3] = subtype & 0xff;
+  newpacket.data[4] = 0x00;
+  newpacket.data[5] = 0x00;
+  /* SNAC reqid */
+  newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF;
+  newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF;
+  newpacket.data[8] = (aim_snac_nextid >>  8) & 0xFF;
+  newpacket.data[9] = (aim_snac_nextid) & 0xFF;
+
+  /* copy in data */
+  newshort = htons(*shortdata);
+  memcpy(&(newpacket.data[10]), &newshort, sizeof(u_short));
+
+  aim_tx_enqueue(&newpacket);
+  return (aim_snac_nextid++);
+}
+
+/*
+ * aim_bos_reqlocaterights()
+ *
+ * Request Location services rights.
+ *
+ */
+u_long aim_bos_reqlocaterights(struct aim_conn_t *conn)
+{
+  return aim_genericreq_n(conn, 0x0002, 0x0002);
+}
+
+/*
+ * aim_bos_reqicbmparaminfo()
+ *
+ * Request ICBM parameter information.
+ *
+ */
+u_long aim_bos_reqicbmparaminfo(struct aim_conn_t *conn)
+{
+  return aim_genericreq_n(conn, 0x0004, 0x0004);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_rxhandlers.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,485 @@
+
+/*
+  aim_rxhandlers.c
+
+  This file contains most all of the incoming packet handlers, along
+  with aim_rxdispatch(), the Rx dispatcher.  Queue/list management is
+  actually done in aim_rxqueue.c.
+  
+ */
+
+
+#include "aim.h" /* for most everything */
+
+int bleck(struct command_rx_struct *param, ...)
+{
+  return 1;
+}
+
+/*
+ * The callbacks.  Used to pass data up from the wire into the client.
+ *
+ * TODO: MASSIVE OVERHAUL.  This method of doing it (array of function 
+ *       pointers) is ugly.  Overhaul may mean including chained callbacks
+ *       for having client features such as run-time loadable modules.
+ *
+ */
+rxcallback_t aim_callbacks[] = {
+  bleck, /* incoming IM */
+  bleck, /* oncoming buddy */
+  bleck, /* offgoing buddy */
+  bleck, /* messaging error */
+  bleck, /* server missed call */
+  bleck, /* login phase 4 packet C command 1*/
+  bleck, /* login phase 4 packet C command 2 */
+  bleck, /* login phase 2, first resp */
+  bleck, /* login phase 2, second resp -- **REQUIRED** */
+  bleck, /* login phase 3 packet B */
+  bleck, /* login phase 3D packet A */
+  bleck, /* login phase 3D packet B */
+  bleck, /* login phase 3D packet C */
+  bleck, /* login phase 3D packet D */
+  bleck, /* login phase 3D packet E */
+  bleck, /* redirect -- **REQUIRED** */
+  bleck, /* server rate change */
+  bleck, /* user location error */
+  aim_parse_unknown, /* completely unknown command */
+  bleck, /* User Info Response */
+  bleck, /* User Search by Address response */
+  bleck, /* User Search by Name response */
+  bleck, /* user search fail */
+  bleck, /* auth error */
+  bleck, /* auth success */
+  bleck, /* auth server ready */
+  bleck, /* auth other */
+  bleck, /* info change reply */
+  bleck, /* ChatNAV: server ready */
+  0x00
+};
+
+
+int aim_register_callbacks(rxcallback_t *newcallbacks)
+{
+  int i = 0;
+  
+  for (i = 0; aim_callbacks[i] != 0x00; i++)
+    {
+      if ( (newcallbacks[i] != NULL) &&
+	   (newcallbacks[i] != 0x00) )
+	{
+#if debug > 3
+	  printf("aim_register_callbacks: changed handler %d\n", i);
+#endif
+	  aim_callbacks[i] = newcallbacks[i];
+	}
+    }
+  
+  return 0;
+}
+
+/*
+  aim_rxdispatch()
+
+  Basically, heres what this should do:
+    1) Determine correct packet handler for this packet
+    2) Mark the packet handled (so it can be dequeued in purge_queue())
+    3) Send the packet to the packet handler
+    4) Go to next packet in the queue and start over
+    5) When done, run purge_queue() to purge handled commands
+
+  Note that any unhandlable packets should probably be left in the
+  queue.  This is the best way to prevent data loss.  This means
+  that a single packet may get looked at by this function multiple
+  times.  This is more good than bad!  This behavior may change.
+
+  Aren't queue's fun? 
+
+  TODO: Get rid of all the ugly if's.
+  TODO: Clean up.
+  TODO: More support for mid-level handlers.
+  TODO: Allow for NULL handlers.
+  
+ */
+int aim_rxdispatch(void)
+{
+  int i = 0;
+  struct command_rx_struct *workingPtr = NULL;
+  
+  if (aim_queue_incoming == NULL)
+    /* this shouldn't really happen, unless the main loop's select is broke  */
+    printf("parse_generic: incoming packet queue empty.\n");
+  else
+    {
+      workingPtr = aim_queue_incoming;
+      for (i = 0; workingPtr != NULL; i++)
+	{
+	  switch(workingPtr->conn->type)
+	    {
+	    case AIM_CONN_TYPE_AUTH:
+	      if ( (workingPtr->data[0] == 0x00) && 
+		   (workingPtr->data[1] == 0x00) &&
+		   (workingPtr->data[2] == 0x00) &&
+		   (workingPtr->data[3] == 0x01) )
+		{
+#if debug > 0
+		  fprintf(stderr, "got connection ack on auth line\n");
+#endif
+		  workingPtr->handled = 1;
+		}
+	      else
+		{
+		  /* any user callbacks will be called from here */
+		  workingPtr->handled = aim_authparse(workingPtr);
+		}
+	      break;
+	    case AIM_CONN_TYPE_BOS:
+	      {
+		u_short family;
+		u_short subtype;
+		family = (workingPtr->data[0] << 8) + workingPtr->data[1];
+		subtype = (workingPtr->data[2] << 8) + workingPtr->data[3];
+		switch (family)
+		  {
+		  case 0x0000: /* not really a family, but it works */
+		    if (subtype == 0x0001)
+		      workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P2_1])(workingPtr);
+		    else
+		      workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr);
+		    break;
+		  case 0x0001: /* Family: General */
+		    switch (subtype)
+		      {
+		      case 0x0001:
+			workingPtr->handled = aim_parse_generalerrs(workingPtr);
+			break;
+		      case 0x0003:
+			workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P2_2])(workingPtr);
+			break;
+		      case 0x0005:
+			workingPtr->handled = aim_handleredirect_middle(workingPtr);
+			break;
+		      case 0x0007:
+			workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P3_B])(workingPtr);
+			break;
+		      case 0x000a:
+			workingPtr->handled = (aim_callbacks[AIM_CB_RATECHANGE])(workingPtr);
+			break;
+		      case 0x000f:
+			workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P3D_A])(workingPtr);
+			break;
+		      case 0x0013:
+			workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P4_C2])(workingPtr);
+			break;
+		      default:
+			workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr);
+		      }
+		    break;
+		  case 0x0002: /* Family: Location */
+		    switch (subtype)
+		      {
+		      case 0x0001:
+			workingPtr->handled = (aim_callbacks[AIM_CB_MISSED_IM])(workingPtr);
+			break;
+		      case 0x0003:
+			workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P3D_D])(workingPtr);
+			break;
+		      case 0x0006:
+			workingPtr->handled = aim_parse_userinfo_middle(workingPtr);
+			break;
+		      default:
+			workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr);
+		      }
+		    break;
+		  case 0x0003: /* Family: Buddy List */
+		    switch (subtype)
+		      {
+		      case 0x0001:
+			workingPtr->handled = aim_parse_generalerrs(workingPtr);
+			break;
+		      case 0x0003:
+			workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P3D_C])(workingPtr);
+			break;
+		      case 0x000b:
+			workingPtr->handled = (aim_callbacks[AIM_CB_ONCOMING_BUDDY])(workingPtr);
+			break;
+		      case 0x000c:
+			workingPtr->handled = (aim_callbacks[AIM_CB_OFFGOING_BUDDY])(workingPtr);
+			break;
+		      default:
+			workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr);
+		      }
+		    break;
+		  case 0x0004: /* Family: Messeging */
+		    switch (subtype)
+		      {
+		      case 0x0001:
+			workingPtr->handled = (aim_callbacks[AIM_CB_USERERROR])(workingPtr);
+			break;
+		      case 0x0005:
+			workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P3D_E])(workingPtr);
+			break;
+		      case 0x0007:
+			workingPtr->handled = aim_parse_incoming_im_middle(workingPtr);
+			break;
+		      case 0x000a:
+			workingPtr->handled = (aim_callbacks[AIM_CB_MISSED_CALL])(workingPtr);
+			break;
+		      default:
+			workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr);
+		      }
+		    break;
+		  case 0x0009:
+		    if (subtype == 0x0001)
+		      workingPtr->handled = aim_parse_generalerrs(workingPtr);
+		    else if (subtype == 0x0003)
+		      workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P3D_B])(workingPtr);
+		    else
+		      workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr);
+		    break;
+		  case 0x000a:  /* Family: User lookup */
+		    switch (subtype)
+		      {
+		      case 0x0001:
+			workingPtr->handled = (aim_callbacks[AIM_CB_SEARCH_FAIL])(workingPtr);
+			break;
+		      case 0x0003:
+			workingPtr->handled = (aim_callbacks[AIM_CB_SEARCH_ADDRESS])(workingPtr);
+			break;
+		      default:
+			workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr);
+		      }
+		    break;
+		  case 0x000b:
+		    if (subtype == 0x0001)
+		      workingPtr->handled = aim_parse_generalerrs(workingPtr);
+		    else if (subtype == 0x0002)
+		      workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P4_C1])(workingPtr);
+		    else
+		      workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr);
+		    break;
+		  default:
+		    workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr);
+		    break;
+		  }
+	      }
+	      break;
+	    case AIM_CONN_TYPE_CHATNAV:
+	      if ( (workingPtr->data[0] == 0x00) &&
+		   (workingPtr->data[1] == 0x02) &&
+		   (workingPtr->data[2] == 0x00) &&
+		   (workingPtr->data[3] == 0x06) )
+		{
+		  workingPtr->handled = 1;
+		  aim_conn_setstatus(workingPtr->conn, AIM_CONN_STATUS_READY);
+		}
+	      else
+		workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr);
+	      break;
+	    case AIM_CONN_TYPE_CHAT:
+	      fprintf(stderr, "\nAHH! Dont know what to do with CHAT stuff yet!\n");
+	      workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr);
+	      break;
+	    default:
+	      fprintf(stderr, "\nAHHHHH! UNKNOWN CONNECTION TYPE!\n\n");
+	      workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr);
+	      break;
+	    }
+	      /* move to next command */
+	  workingPtr = workingPtr->next;
+	}
+    }
+
+  aim_queue_incoming = aim_purge_rxqueue(aim_queue_incoming);
+  
+  return 0;
+}
+
+/*
+ * TODO: check and cure memory leakage in this function.
+ */
+int aim_authparse(struct command_rx_struct *command)
+{
+  int iserror = 0;
+  struct aim_tlv_t *tlv = NULL;
+  char *errorurl = NULL;
+  short errorcode;
+  int z = 0;
+
+  if ( (command->data[0] == 0x00) &&
+       (command->data[1] == 0x01) &&
+       (command->data[2] == 0x00) &&
+       (command->data[3] == 0x03) )
+    {
+      /* "server ready"  -- can be ignored */
+      return (aim_callbacks[AIM_CB_AUTH_SVRREADY])(command);
+    }
+  else if ( (command->data[0] == 0x00) &&
+	    (command->data[1] == 0x07) &&
+	    (command->data[2] == 0x00) &&
+	    (command->data[3] == 0x05) )
+    {
+      /* "information change reply" */
+      return (aim_callbacks[AIM_CB_AUTH_INFOCHNG_REPLY])(command);
+    }
+  else
+    {
+      /* anything else -- usually used for login; just parse as pure TLVs */
+
+
+      /* all this block does is figure out if it's an
+	 error or a success, nothing more */
+      while (z < command->commandlen)
+	{
+	  tlv = aim_grabtlvstr(&(command->data[z]));
+	  switch(tlv->type) 
+	    {
+	    case 0x0001: /* screen name */
+	      aim_logininfo.screen_name = tlv->value;
+	      z += 2 + 2 + tlv->length;
+	      free(tlv);
+	      tlv = NULL;
+	      break;
+	    case 0x0004: /* error URL */
+	      errorurl = tlv->value;
+	      z += 2 + 2 + tlv->length;
+	      free(tlv);
+	      tlv = NULL;
+	      break;
+	    case 0x0005: /* BOS IP */
+	      aim_logininfo.BOSIP = tlv->value;
+	      z += 2 + 2 + tlv->length;
+	      free(tlv);
+	      tlv = NULL;
+	      break;
+	    case 0x0006: /* auth cookie */
+	      aim_logininfo.cookie = tlv->value;
+	      z += 2 + 2 + tlv->length;
+	      free(tlv);
+	      tlv=NULL;
+	      break;
+	    case 0x0011: /* email addy */
+	      aim_logininfo.email = tlv->value;
+	      z += 2 + 2 + tlv->length;
+	      free(tlv);
+	      tlv = NULL;
+	      break;
+	    case 0x0013: /* registration status */
+	      aim_logininfo.regstatus = *(tlv->value);
+	      z += 2 + 2 + tlv->length;
+	      aim_freetlv(&tlv);
+	      break;
+	    case 0x0008: /* error code */
+	      errorcode = *(tlv->value);
+	      z += 2 + 2 + tlv->length;
+	      aim_freetlv(&tlv);
+	      iserror = 1;
+	      break;
+	    default:
+	  z += 2 + 2 + tlv->length;
+	  aim_freetlv(&tlv);
+	  /* dunno */
+	    }
+	}
+
+      if (iserror && 
+	  errorurl && 
+	  errorcode)
+	return (aim_callbacks[AIM_CB_AUTH_ERROR])(command, &aim_logininfo, errorurl, errorcode);
+      else if (aim_logininfo.screen_name && 
+	       aim_logininfo.cookie && aim_logininfo.BOSIP)
+	return (aim_callbacks[AIM_CB_AUTH_SUCCESS])(command, &aim_logininfo);
+      else
+	return (aim_callbacks[AIM_CB_AUTH_OTHER])(command);
+    }
+}
+
+/*
+ * TODO: check for and cure any memory leaks here.
+ */
+int aim_handleredirect_middle(struct command_rx_struct *command, ...)
+{
+  struct aim_tlv_t *tlv = NULL;
+  int z = 10;
+  int serviceid;
+  char *cookie;
+  char *ip;
+
+  while (z < command->commandlen)
+    {
+      tlv = aim_grabtlvstr(&(command->data[z]));
+      switch(tlv->type)
+	{
+	case 0x000d:  /* service id */
+	  aim_freetlv(&tlv);
+	  /* regrab as an int */
+	  tlv = aim_grabtlv(&(command->data[z]));
+	  serviceid = (tlv->value[0] << 8) + tlv->value[1]; /* hehe */
+	  z += 2 + 2 + tlv->length;
+	  aim_freetlv(&tlv);
+	  break;
+	case 0x0005:  /* service server IP */
+	  ip = tlv->value;
+	  z += 2 + 2 + tlv->length;
+	  free(tlv);
+	  tlv = NULL;
+	  break;
+	case 0x0006: /* auth cookie */
+	  cookie = tlv->value;
+	  z += 2 + 2 + tlv->length;
+	  free(tlv);
+	  tlv = NULL;
+	  break;
+	default:
+	  /* dunno */
+	  z += 2 + 2 + tlv->length;
+	  aim_freetlv(&tlv);
+	}
+    }
+  return (aim_callbacks[AIM_CB_LOGIN_P3D_F])(command, serviceid, ip, cookie);
+}
+
+int aim_parse_unknown(struct command_rx_struct *command, ...)
+{
+  int i = 0;
+
+  printf("\nRecieved unknown packet:");
+
+  for (i = 0; i < command->commandlen; i++)
+    {
+      if ((i % 8) == 0)
+	printf("\n\t");
+
+      printf("0x%2x ", command->data[i]);
+    }
+  
+  printf("\n\n");
+
+  return 1;
+}
+
+
+/*
+ * aim_parse_generalerrs()
+ *
+ * Middle handler for 0x0001 snac of each family.
+ *
+ */
+int aim_parse_generalerrs(struct command_rx_struct *command, ...)
+{
+  u_short family;
+  u_short subtype;
+  family = (command->data[0] << 8) + command->data[1];
+  subtype = (command->data[2] << 8) + command->data[3];
+  
+  switch(family)
+    {
+    default:
+      /* Unknown family */
+      return (aim_callbacks[AIM_CB_UNKNOWN])(command);
+    }
+
+  return 1;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_rxqueue.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,247 @@
+/*
+  aim_rxqueue.c
+
+  This file contains the management routines for the receive
+  (incoming packet) queue.  The actual packet handlers are in
+  aim_rxhandlers.c.
+
+ */
+
+#include "aim.h"
+
+/*
+  This is a modified read() to make SURE we get the number
+  of bytes we are told to, otherwise block.
+ */
+int Read(int fd, u_char *buf, int len)
+{
+  int i = 0;
+  int j = 0;
+
+  while ((i < len) && (!(i < 0)))
+    {
+      j = read(fd, &(buf[i]), len-i);
+      if ( (j < 0) && (errno != EAGAIN))
+	return -errno; /* fail */
+      else
+	i += j; /* success, continue */
+    }
+#if 0
+  printf("\nRead Block: (%d/%04x)\n", len, len);
+  printf("\t");
+  for (j = 0; j < len; j++)
+    {
+      if (j % 8 == 0)
+	printf("\n\t");
+      if (buf[j] >= ' ' && buf[j] < 127)
+	 printf("%c=%02x ",buf[j], buf[j]);
+      else
+	 printf("0x%02x ", buf[j]);
+    }
+  printf("\n\n");
+#endif
+  return i;
+}
+
+/*
+  struct command_struct *
+                         get_generic(
+                                     struct connection_info struct *,
+				     struct command_struct * 
+				     )
+  
+  Grab as many command sequences as we can off the socket, and enqueue
+  each command in the incoming event queue in a seperate struct.
+
+*/
+int aim_get_command(void)
+{
+  int i, readgood, j, isav, err;
+  int s;
+  fd_set fds;
+  struct timeval tv;
+  char generic[6]; 
+  struct command_rx_struct *workingStruct = NULL;
+  struct command_rx_struct *workingPtr = NULL;
+  struct aim_conn_t *conn = NULL;
+#if debug > 0
+  printf("Reading generic/unknown response...");
+#endif
+  
+  
+  /* dont wait at all (ie, never call this unless something is there) */
+  tv.tv_sec = 0; 
+  tv.tv_usec = 0;
+  conn = aim_select(&tv);
+
+  if (conn==NULL)
+    return 0;  /* nothing waiting */
+
+  s = conn->fd;
+
+  FD_ZERO(&fds);
+  FD_SET(s, &fds);
+  tv.tv_sec = 0;  /* wait, but only for 10us */
+  tv.tv_usec = 10;
+  
+  generic[0] = 0x00;  
+
+  readgood = 0;
+  i = 0;
+  j = 0;
+  /* read first 6 bytes (the FLAP header only) off the socket */
+  while ( (select(s+1, &fds, NULL, NULL, &tv) == 1) && (i < 6))
+    {
+      if ((err = Read(s, &(generic[i]), 1)) < 0)
+	{
+	  /* error is probably not recoverable...(must be a pessimistic day) */
+	  aim_conn_close(conn);
+	  return err;
+   	}
+
+      if (readgood == 0)
+	{
+	  if (generic[i] == 0x2a)
+	  {
+	    readgood = 1;
+#if debug > 1
+	    printf("%x ", generic[i]);
+	    fflush(stdout);
+#endif
+	    i++;
+	  }
+	  else
+	    {
+#if debug > 1
+	      printf("skipping 0x%d ", generic[i]);
+	      fflush(stdout);
+#endif
+	      j++;
+	    }
+	}
+      else
+	{
+#if debug > 1
+	  printf("%x ", generic[i]);
+#endif
+	  i++;
+	}
+      FD_ZERO(&fds);
+      FD_SET(s, &fds);
+      tv.tv_sec= 2;
+      tv.tv_usec= 2;
+    }
+
+  if (generic[0] != 0x2a)
+    {
+      /* this really shouldn't happen, since the main loop
+	 select() should protect us from entering this function
+	 without data waiting  */
+      printf("Bad incoming data!");
+      return -1;
+    }
+
+  isav = i;
+
+  /* allocate a new struct */
+  workingStruct = (struct command_rx_struct *) malloc(sizeof(struct command_rx_struct));
+  workingStruct->lock = 1;  /* lock the struct */
+
+  /* store type -- byte 2 */
+  workingStruct->type = (char) generic[1];
+
+  /* store seqnum -- bytes 3 and 4 */
+  workingStruct->seqnum = ( (( (unsigned int) generic[2]) & 0xFF) << 8);
+  workingStruct->seqnum += ( (unsigned int) generic[3]) & 0xFF;
+
+  /* store commandlen -- bytes 5 and 6 */
+  workingStruct->commandlen = ( (( (unsigned int) generic[4]) & 0xFF ) << 8);
+  workingStruct->commandlen += ( (unsigned int) generic[5]) & 0xFF;
+  
+  printf("%d\n", workingStruct->commandlen);
+
+  /* malloc for data portion */
+  workingStruct->data = (char *) malloc(workingStruct->commandlen);
+
+  /* read the data portion of the packet */
+  i = Read(s, workingStruct->data, workingStruct->commandlen);
+  if (i < 0)
+    {
+      aim_conn_close(conn);
+      return i;
+    }
+
+#if debug > 0
+  printf(" done. (%db+%db read, %db skipped)\n", isav, i, j);
+#endif
+
+  workingStruct->conn = conn;
+
+  workingStruct->next = NULL;  /* this will always be at the bottom */
+  workingStruct->lock = 0; /* unlock */
+
+  /* enqueue this packet */
+  if (aim_queue_incoming == NULL)
+    aim_queue_incoming = workingStruct;
+  else
+    {
+      workingPtr = aim_queue_incoming;
+      while (workingPtr->next != NULL)
+	workingPtr = workingPtr->next;
+      workingPtr->next = workingStruct;
+    }
+
+  return 0;  
+}
+
+/*
+  purge_rxqueue()
+
+  This is just what it sounds.  It purges the receive (rx) queue of
+  all handled commands.  This is normally called from inside 
+  aim_rxdispatch() after it's processed all the commands in the queue.
+  
+ */
+struct command_rx_struct *aim_purge_rxqueue(struct command_rx_struct *queue)
+{
+  int i = 0;
+  struct command_rx_struct *workingPtr = NULL;
+  struct command_rx_struct *workingPtr2 = NULL;
+
+  workingPtr = queue;
+  if (queue == NULL)
+    {
+      return queue;
+    }
+  else if (queue->next == NULL)
+    {
+      if (queue->handled == 1)
+	{
+	  workingPtr2 = queue;
+	  queue = NULL;
+	  free(workingPtr2->data);
+	  free(workingPtr2);
+	}
+      return queue;
+    }
+  else
+    {
+      for (i = 0; workingPtr != NULL; i++)
+	{
+	  if (workingPtr->next->handled == 1)
+	    {
+	      /* save struct */
+	      workingPtr2 = workingPtr->next;
+	      /* dequeue */
+	      workingPtr->next = workingPtr2->next;
+	      /* free */
+	      free(workingPtr2->data);
+	      free(workingPtr2);
+	    }
+
+	  workingPtr = workingPtr->next;  
+	}
+    }
+
+  return queue;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_search.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,63 @@
+
+/*
+ * aim_search.c
+ *
+ * TODO: Add aim_usersearch_name()
+ *
+ */
+
+#include <aim.h>
+
+u_long aim_usersearch_address(struct aim_conn_t *conn, char *address)
+{
+  struct command_tx_struct newpacket;
+  
+  if (!address)
+    return -1;
+
+  newpacket.lock = 1;
+
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+
+  newpacket.type = 0x0002;
+  
+  newpacket.commandlen = 10 + strlen(address);
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+
+  newpacket.data[0] = 0x00;
+  newpacket.data[1] = 0x0a;
+  newpacket.data[2] = 0x00;
+  newpacket.data[3] = 0x02;
+  newpacket.data[4] = 0x00;
+  newpacket.data[5] = 0x00;
+
+  /* SNAC reqid */
+  newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF;
+  newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF;
+  newpacket.data[8] = (aim_snac_nextid >>  8) & 0xFF;
+  newpacket.data[9] = (aim_snac_nextid) & 0xFF;
+
+  memcpy(&(newpacket.data[10]), address, strlen(address));
+
+  aim_tx_enqueue(&newpacket);
+
+  {
+    struct aim_snac_t snac;
+    
+    snac.id = aim_snac_nextid;
+    snac.family = 0x000a;
+    snac.type = 0x0002;
+    snac.flags = 0x0000;
+
+    snac.data = malloc(strlen(address)+1);
+    memcpy(snac.data, address, strlen(address)+1);
+
+    aim_newsnac(&snac);
+  }
+
+  return (aim_snac_nextid++);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_snac.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,108 @@
+
+/*
+ *
+ * Various SNAC-related dodads... 
+ *
+ * outstanding_snacs is a list of aim_snac_t structs.  A SNAC should be added
+ * whenever a new SNAC is sent and it should remain in the list until the
+ * response for it has been receieved.
+ *
+ * First edition badly written by Adam Fritzler (afritz@delphid.ml.org)
+ * Current edition nicely rewritten (it even works) by n (n@ml.org)
+ *
+ */
+
+#include <aim.h>
+#include <assert.h>
+
+struct aim_snac_t	*aim_outstanding_snacs = NULL;
+u_long	aim_snac_nextid = 0x00000001;
+
+u_long	aim_newsnac(struct aim_snac_t *newsnac) {
+	struct aim_snac_t	*snac = NULL, *cur = aim_outstanding_snacs;
+  
+	assert(newsnac != NULL);
+	snac = calloc(1, sizeof(struct aim_snac_t));
+	assert(snac != NULL);
+	memcpy(snac, newsnac, sizeof(struct aim_snac_t));
+	snac->issuetime = time(&snac->issuetime);
+	snac->next = NULL;
+
+	if (cur == NULL) {
+		aim_outstanding_snacs = snac;
+		return(snac->id);
+	}
+	while (cur->next != NULL)
+		cur = cur->next;
+	cur->next = snac;
+	return(snac->id);
+}
+
+struct aim_snac_t	*aim_remsnac(u_long id) {
+	struct aim_snac_t	*cur = aim_outstanding_snacs;
+
+	if (cur == NULL)
+		return(NULL);
+	if (cur->id == id) {
+		aim_outstanding_snacs = cur->next;
+		return(cur);
+	}
+	while (cur->next != NULL) {
+		if (cur->next->id == id) {
+			struct aim_snac_t	*tmp = NULL;
+
+			tmp = cur->next;
+			cur->next = cur->next->next;
+			return(tmp);
+		}
+		cur = cur->next;
+	}
+	return(NULL);
+}
+
+/*
+ * This is for cleaning up old SNACs that either don't get replies or
+ * a reply was never received for.  Garabage collection. Plain and simple.
+ *
+ * maxage is the _minimum_ age in seconds to keep SNACs (though I don't know
+ * why its called _max_age).
+ *
+ */
+int aim_cleansnacs(int maxage)
+{
+  struct aim_snac_t *cur = aim_outstanding_snacs;
+  struct aim_snac_t *remed = NULL;
+  time_t curtime;
+  
+  curtime = time(&curtime);
+
+  while (cur)
+    {
+      if ( (cur) && (((cur->issuetime) + maxage) < curtime))
+	{
+#if DEBUG > 1
+	  printf("aimsnac: WARNING purged obsolete snac %ul\n", cur->id);
+#endif
+	  remed = aim_remsnac(cur->id);
+	  if (remed)
+	    {
+	      if (remed->data)
+		free(remed->data);
+	      free(remed);
+	    }
+	}
+      cur = cur->next;
+    }
+
+  return 0;
+}
+
+int aim_putsnac(u_char *buf, int family, int subtype, int flags, u_long snacid)
+{
+  int curbyte = 0;
+  curbyte += aimutil_put16(buf+curbyte,family&0xffff);
+  curbyte += aimutil_put16(buf+curbyte,subtype&0xffff);
+  curbyte += aimutil_put16(buf+curbyte,flags&0xffff);
+  curbyte += aimutil_put32(buf+curbyte,snacid);
+  return curbyte;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_tlv.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,86 @@
+#include <aim.h>
+
+struct aim_tlv_t *aim_grabtlv(u_char *src)
+{
+  struct aim_tlv_t *dest = NULL;
+
+  dest = aim_createtlv();
+
+  dest->type = src[0] << 8;
+  dest->type += src[1];
+
+  dest->length = src[2] << 8;
+  dest->length += src[3];
+
+  dest->value = (u_char *) malloc(dest->length*sizeof(u_char));
+  memset(dest->value, 0, dest->length*sizeof(u_char));
+
+  memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char));
+  
+  return dest;
+}
+
+struct aim_tlv_t *aim_grabtlvstr(u_char *src)
+{
+  struct aim_tlv_t *dest = NULL;
+
+  dest = aim_createtlv();
+
+  dest->type = src[0] << 8;
+  dest->type += src[1];
+
+  dest->length = src[2] << 8;
+  dest->length += src[3];
+
+  dest->value = (u_char *) malloc((dest->length+1)*sizeof(u_char));
+  memset(dest->value, 0, (dest->length+1)*sizeof(u_char));
+
+  memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char));
+  dest->value[dest->length] = '\0';
+
+  return dest;
+}
+
+int aim_puttlv (u_char *dest, struct aim_tlv_t *newtlv)
+{
+  int i=0;
+
+  dest[i++] = newtlv->type >> 8;
+  dest[i++] = newtlv->type & 0x00FF;
+  dest[i++] = newtlv->length >> 8;
+  dest[i++] = newtlv->length & 0x00FF;
+  memcpy(&(dest[i]), newtlv->value, newtlv->length);
+  i+=newtlv->length;
+  return i;
+}
+
+struct aim_tlv_t *aim_createtlv(void)
+{
+  struct aim_tlv_t *newtlv = NULL;
+  newtlv = (struct aim_tlv_t *)malloc(sizeof(struct aim_tlv_t));
+  memset(newtlv, 0, sizeof(struct aim_tlv_t));
+  return newtlv;
+}
+
+int aim_freetlv(struct aim_tlv_t **oldtlv)
+{
+  if (!oldtlv)
+    return -1;
+  if (!*oldtlv)
+    return -1;
+  if ((*oldtlv)->value)
+    free((*oldtlv)->value);
+  free(*(oldtlv));
+  (*oldtlv) = NULL;
+
+  return 0;
+}
+
+int aim_puttlv_16(u_char *buf, u_short t, u_short v)
+{
+  int curbyte=0;
+  curbyte += aimutil_put16(buf+curbyte, t&0xffff);
+  curbyte += aimutil_put16(buf+curbyte, 0x0002);
+  curbyte += aimutil_put16(buf+curbyte, v&0xffff);
+  return curbyte;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_txqueue.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,307 @@
+/*
+  aim_txqueue.c
+
+  Herein lies all the mangement routines for the transmit (Tx) queue.
+
+ */
+
+#include "aim.h"
+
+/*
+  aim_tx_enqeue()
+
+  The overall purpose here is to enqueue the passed in command struct
+  into the outgoing (tx) queue.  Basically...
+    1) Make a scope-irrelevent copy of the struct
+    2) Lock the struct
+    3) Mark as not-sent-yet
+    4) Enqueue the struct into the list
+    5) Unlock the struct once it's linked in
+    6) Return
+
+ */
+
+int aim_tx_enqueue(struct command_tx_struct *newpacket)
+{
+  struct command_tx_struct *workingPtr = NULL;
+  struct command_tx_struct *newpacket_copy = NULL;
+
+  if (newpacket->conn == NULL)
+    {
+      printf("aim_tx_enqueue: WARNING: enqueueing packet with no connecetion,  defaulting to BOS\n");
+      newpacket->conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
+    }
+ 
+  newpacket_copy = (struct command_tx_struct *) malloc (sizeof(struct command_tx_struct));
+  memcpy(newpacket_copy, newpacket, sizeof(struct command_tx_struct));
+
+  /* assign seqnum */
+  newpacket_copy->seqnum = aim_get_next_txseqnum(newpacket_copy->conn);
+  /* set some more fields */
+  newpacket_copy->lock = 1; /* lock */
+  newpacket_copy->sent = 0; /* not sent yet */
+  newpacket_copy->next = NULL; /* always last */
+
+  if (aim_queue_outgoing == NULL)
+    {
+      aim_queue_outgoing = newpacket_copy;
+    }
+  else
+    {
+      workingPtr = aim_queue_outgoing;
+      while (workingPtr->next != NULL)
+	workingPtr = workingPtr->next;
+      workingPtr->next = newpacket_copy;
+    }
+
+  newpacket_copy->lock = 0; /* unlock so it can be sent */
+
+#if debug > 2
+  printf("calling aim_tx_printqueue()\n");
+  aim_tx_printqueue();
+  printf("back from aim_tx_printqueue()\n");
+#endif
+
+  /* we'll force a flush for now -- this behavior probably will change */
+#if debug > 1
+  printf("calling aim_tx_flushqueue()\n");
+#endif
+  aim_tx_flushqueue();
+#if debug > 1
+  printf("back from aim_tx_flushqueue()\n");
+#endif
+
+  return 0;
+}
+
+/* 
+   aim_get_next_txseqnum()
+
+   This increments the tx command count, and returns the seqnum
+   that should be stamped on the next FLAP packet sent.  This is
+   normally called during the final step of packet preparation
+   before enqueuement (in aim_tx_enqueue()).
+
+ */
+unsigned int aim_get_next_txseqnum(struct aim_conn_t *conn)
+{
+  return ( ++conn->seqnum );
+}
+
+/*
+  aim_tx_printqueue()
+
+  This is basically for debuging purposes only.  It dumps all the
+  records in the tx queue and their current status.  Very helpful
+  if the queue isn't working quite right.
+
+ */
+#if debug > 2
+int aim_tx_printqueue(void)
+{
+  struct command_tx_struct *workingPtr = NULL;
+
+  workingPtr = aim_queue_outgoing;
+#if debug > 2
+  printf("\ncurrent aim_queue_outgoing...\n");
+  printf("\ttype seqnum  len  lock sent\n");  
+#endif
+  if (workingPtr == NULL)
+    printf("aim_tx_flushqueue(): queue empty");
+  else
+    {
+      while (workingPtr != NULL)
+	{
+	  printf("\t  %2x   %4x %4x   %1d    %1d\n", workingPtr->type, workingPtr->seqnum, workingPtr->commandlen, workingPtr->lock, workingPtr->sent);
+	  
+	  workingPtr = workingPtr->next;
+	}
+    }
+
+  printf("\n(done printing queue)\n");
+  
+  return 0;
+}
+#endif
+
+/*
+  aim_tx_flushqueue()
+
+  This the function is responsable for putting the queued commands
+  onto the wire.  This function is critical to the operation of 
+  the queue and therefore is the most prone to brokenness.  It
+  seems to be working quite well at this point.
+
+  Procedure:
+    1) Traverse the list, only operate on commands that are unlocked
+       and haven't been sent yet.
+    2) Lock the struct
+    3) Allocate a temporary buffer to store the finished, fully
+       processed packet in.
+    4) Build the packet from the command_tx_struct data.
+    5) Write the packet to the socket.
+    6) If success, mark the packet sent, if fail report failure, do NOT
+       mark the packet sent (so it will not get purged and therefore
+       be attempted again on next call).
+    7) Unlock the struct.
+    8) Free the temp buffer
+    9) Step to next struct in list and go back to 1.
+
+ */
+int aim_tx_flushqueue(void)
+{
+  struct command_tx_struct *workingPtr = NULL;
+  unsigned char *curPacket = NULL;
+#if debug > 1
+  int i = 0;
+#endif
+
+  workingPtr = aim_queue_outgoing;
+#if debug > 1
+  printf("beginning txflush...\n");
+#endif
+  while (workingPtr != NULL)
+    {
+      /* only process if its unlocked and unsent */
+      if ( (workingPtr->lock == 0) &&
+	   (workingPtr->sent == 0) )
+	{
+	  workingPtr->lock = 1; /* lock the struct */
+	  
+	  /* allocate full-packet buffer */
+	  curPacket = (char *) malloc(workingPtr->commandlen + 6);
+	  
+	  /* command byte */
+	  curPacket[0] = 0x2a;
+	  /* type/family byte */
+	  curPacket[1] = workingPtr->type;
+	  /* bytes 3+4: word: FLAP sequence number */
+	  curPacket[2] = (char) ( (workingPtr->seqnum) >> 8);
+	  curPacket[3] = (char) ( (workingPtr->seqnum) & 0xFF);
+	  /* bytes 5+6: word: SNAC len */
+	  curPacket[4] = (char) ( (workingPtr->commandlen) >> 8);
+	  curPacket[5] = (char) ( (workingPtr->commandlen) & 0xFF);
+	  /* bytes 7 and on: raw: SNAC data */
+	  memcpy(&(curPacket[6]), workingPtr->data, workingPtr->commandlen);
+	  
+	  /* full image of raw packet data now in curPacket */
+
+	  if ( write(workingPtr->conn->fd, curPacket, (workingPtr->commandlen + 6)) != (workingPtr->commandlen + 6))
+	    {
+	      perror("write");
+	      printf("\nWARNING: Error in sending packet 0x%4x -- will try again next time\n\n", workingPtr->seqnum);
+	      workingPtr->sent = 0; /* mark it unsent */
+	      return -1;  /* bail out */
+	    }
+	  else
+	    {
+#if debug > 2
+	      printf("\nSENT 0x%4x\n\n", workingPtr->seqnum);
+#endif
+	      workingPtr->sent = 1; /* mark the struct as sent */
+	    }
+#if debug > 2
+	  printf("\nPacket:");
+	  for (i = 0; i < (workingPtr->commandlen + 6); i++)
+	    {
+	      if ((i % 8) == 0)
+		printf("\n\t");
+	      if (curPacket[i] >= ' ' && curPacket[i]<127)
+		 printf("%c=%02x ",curPacket[i], curPacket[i]);
+	      else
+		 printf("0x%2x ", curPacket[i]);
+	    }
+	  printf("\n");
+#endif
+	  workingPtr->lock = 0; /* unlock the struct */
+	  free(curPacket); /* free up full-packet buffer */
+	}
+      workingPtr = workingPtr->next;
+    }
+
+  /* purge sent commands from queue */
+  /*   this may not always occur explicitly--i may put this on a timer later */
+#if debug > 1
+  printf("calling aim_tx_purgequeue()\n");
+#endif
+  aim_tx_purgequeue();
+#if debug > 1
+  printf("back from aim_tx_purgequeu() [you must be a lucky one]\n");
+#endif
+
+  return 0;
+}
+
+/*
+  aim_tx_purgequeue()
+  
+  This is responsable for removing sent commands from the transmit 
+  queue. This is not a required operation, but it of course helps
+  reduce memory footprint at run time!  
+
+ */
+int aim_tx_purgequeue(void)
+{
+  struct command_tx_struct *workingPtr = NULL;
+  struct command_tx_struct *workingPtr2 = NULL;
+#if debug > 1
+  printf("purgequeue(): starting purge\n");
+#endif
+  /* Empty queue: nothing to do */
+  if (aim_queue_outgoing == NULL)
+    {
+#if debug > 1
+      printf("purgequeue(): purge done (len=0)\n");
+#endif
+      return 0;
+    }
+  /* One Node queue: free node and return */
+  else if (aim_queue_outgoing->next == NULL)
+    {
+#if debug > 1
+      printf("purgequeue(): entered case len=1\n");
+#endif
+      /* only free if sent AND unlocked -- dont assume sent structs are done */
+      if ( (aim_queue_outgoing->lock == 0) &&
+	   (aim_queue_outgoing->sent == 1) )
+	{
+#if debug > 1
+	  printf("purgequeue(): purging seqnum 0x%04x\n", aim_queue_outgoing->seqnum);
+#endif
+	  workingPtr2 = aim_queue_outgoing;
+	  aim_queue_outgoing = NULL;
+	  free(workingPtr2->data);
+	  free(workingPtr2);
+	}
+#if debug > 1
+      printf("purgequeue(): purge done (len=1)\n");
+#endif
+      return 0;
+    }
+  else
+    {
+#if debug > 1
+      printf("purgequeue(): entering case len>1\n");
+#endif
+      while(workingPtr->next != NULL)
+	{
+	  if ( (workingPtr->next->lock == 0) &&
+	       (workingPtr->next->sent == 1) )
+	    {
+#if debug > 1
+	      printf("purgequeue(): purging seqnum 0x%04x\n", workingPtr->next->seqnum);
+#endif
+	      workingPtr2 = workingPtr->next;
+	      workingPtr->next = workingPtr2->next;
+	      free(workingPtr2->data);
+	      free(workingPtr2);
+	    }
+	}
+#if debug > 1
+      printf("purgequeue(): purge done (len>1)\n");
+#endif
+      return 0;
+    }
+
+  /* no reach */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_util.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,38 @@
+/*
+ *
+ *
+ *
+ */
+
+#include "aim.h"
+
+int aimutil_put8(u_char *buf, u_short data)
+{
+  buf[0] = data&0xff;
+  return 1;
+}
+
+/*
+ * Endian-ness issues here?
+ */
+int aimutil_put16(u_char *buf, u_short data)
+{
+  buf[0] = (data>>8)&0xff;
+  buf[1] = (data)&0xff;
+  return 2;
+}
+
+int aimutil_put32(u_char *buf, u_long data)
+{
+  buf[0] = (data>>24)&0xff;
+  buf[1] = (data>>16)&0xff;
+  buf[2] = (data>>8)&0xff;
+  buf[3] = (data)&0xff;
+  return 4;
+}
+
+int aimutil_putstr(u_char *dest, u_char *src, int len)
+{
+  memcpy(dest, src, len);
+  return len;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/faimconfig.h	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,42 @@
+#ifndef __FAIMCONFIG_H__
+#define __FAIMCONFIG_H__
+
+/*
+  faimconfig.h
+
+  Contains various compile-time options that apply _only to the faim backend_.
+  Note that setting any of these options in a frontend header does not imply
+  that they'll get set here.  Notably, the 'debug' of this file is _not_ 
+  the same as the frontend 'debug'.  They can be different values.
+
+ */
+
+/* 
+   set debug to be > 0 if you want debugging information spewing
+   on the attached tty.  set to 0 for daily use.  this value
+   is _not_ inherited by the frontend, only this backend.
+
+   Default: 0  
+*/
+#define debug 10
+
+/*
+  define TIS_TELNET_PROXY if you have a TIS firewall (Gauntlet) and
+  you want to use FAIM through the firewall
+
+  Default: undefined
+ */
+/* #define TIS_TELNET_PROXY "proxy.mydomain.com" */
+
+
+/* #define USE_SNAC_FOR_IMS */
+
+/* ---- these shouldn't need any changes ---- */
+
+/* authentication server of OSCAR */
+#define FAIM_LOGIN_SERVER "login.oscar.aol.com"
+/* port on OSCAR authenticator to connect to */
+#define FAIM_LOGIN_PORT 5190
+
+
+#endif /* __FAIMCONFIG_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m4/.cvsignore	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m4/Makefile.am	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,3 @@
+EXTRA_DIST = gnome-x-checks.m4 gnome-gnorba-check.m4 \
+             gnome-pthread-check.m4 gnome.m4 gnome-orbit-check.m4 \
+             esd.m4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m4/esd.m4	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,164 @@
+# Configure paths for ESD
+# Manish Singh    98-9-30
+# stolen back from Frank Belew
+# stolen from Manish Singh
+# Shamelessly stolen from Owen Taylor
+
+dnl AM_PATH_GESD([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for ESD, and define ESD_CFLAGS and ESD_LIBS
+dnl
+AC_DEFUN(AM_PATH_GESD,
+[dnl 
+dnl Get the cflags and libraries from the esd-config script
+dnl
+AC_ARG_WITH(esd-prefix,[  --with-esd-prefix=PFX   Prefix where ESD is installed (optional)],
+            esd_prefix="$withval", esd_prefix="")
+AC_ARG_WITH(esd-exec-prefix,[  --with-esd-exec-prefix=PFX Exec prefix where ESD is installed (optional)],
+            esd_exec_prefix="$withval", esd_exec_prefix="")
+AC_ARG_ENABLE(esdtest, [  --disable-esdtest       Do not try to compile and run a test ESD program],
+		    , enable_esdtest=yes)
+
+  if test x$esd_exec_prefix != x ; then
+     esd_args="$esd_args --exec-prefix=$esd_exec_prefix"
+     if test x${ESD_CONFIG+set} != xset ; then
+        ESD_CONFIG=$esd_exec_prefix/bin/esd-config
+     fi
+  fi
+  if test x$esd_prefix != x ; then
+     esd_args="$esd_args --prefix=$esd_prefix"
+     if test x${ESD_CONFIG+set} != xset ; then
+        ESD_CONFIG=$esd_prefix/bin/esd-config
+     fi
+  fi
+
+  AC_PATH_PROG(ESD_CONFIG, esd-config, no)
+  min_esd_version=ifelse([$1], ,0.2.7,$1)
+  AC_MSG_CHECKING(for ESD - version >= $min_esd_version)
+  no_esd=""
+  if test "$ESD_CONFIG" = "no" ; then
+    no_esd=yes
+  else
+    ESD_CFLAGS=`$ESD_CONFIG $esdconf_args --cflags`
+    ESD_LIBS=`$ESD_CONFIG $esdconf_args --libs`
+
+    esd_major_version=`$ESD_CONFIG $esd_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    esd_minor_version=`$ESD_CONFIG $esd_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    esd_micro_version=`$ESD_CONFIG $esd_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_esdtest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $ESD_CFLAGS"
+      LIBS="$LIBS $ESD_LIBS"
+dnl
+dnl Now check if the installed ESD is sufficiently new. (Also sanity
+dnl checks the results of esd-config to some extent
+dnl
+      rm -f conf.esdtest
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <esd.h>
+
+char*
+my_strdup (char *str)
+{
+  char *new_str;
+  
+  if (str)
+    {
+      new_str = malloc ((strlen (str) + 1) * sizeof(char));
+      strcpy (new_str, str);
+    }
+  else
+    new_str = NULL;
+  
+  return new_str;
+}
+
+int main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.esdtest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = my_strdup("$min_esd_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_esd_version");
+     exit(1);
+   }
+
+   if (($esd_major_version > major) ||
+      (($esd_major_version == major) && ($esd_minor_version > minor)) ||
+      (($esd_major_version == major) && ($esd_minor_version == minor) && ($esd_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** 'esd-config --version' returned %d.%d.%d, but the minimum version\n", $esd_major_version, $esd_minor_version, $esd_micro_version);
+      printf("*** of ESD required is %d.%d.%d. If esd-config is correct, then it is\n", major, minor, micro);
+      printf("*** best to upgrade to the required version.\n");
+      printf("*** If esd-config was wrong, set the environment variable ESD_CONFIG\n");
+      printf("*** to point to the correct copy of esd-config, and remove the file\n");
+      printf("*** config.cache before re-running configure\n");
+      return 1;
+    }
+}
+
+],, no_esd=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_esd" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$ESD_CONFIG" = "no" ; then
+       echo "*** The esd-config script installed by ESD could not be found"
+       echo "*** If ESD was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the ESD_CONFIG environment variable to the"
+       echo "*** full path to esd-config."
+     else
+       if test -f conf.esdtest ; then
+        :
+       else
+          echo "*** Could not run ESD test program, checking why..."
+          CFLAGS="$CFLAGS $ESD_CFLAGS"
+          LIBS="$LIBS $ESD_LIBS"
+          AC_TRY_LINK([
+#include <stdio.h>
+#include <esd.h>
+],      [ return 0; ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding ESD or finding the wrong"
+          echo "*** version of ESD. If it is not finding ESD, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means ESD was incorrectly installed"
+          echo "*** or that you have moved ESD since it was installed. In the latter case, you"
+          echo "*** may want to edit the esd-config script: $ESD_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     ESD_CFLAGS=""
+     ESD_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(ESD_CFLAGS)
+  AC_SUBST(ESD_LIBS)
+  rm -f conf.esdtest
+])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m4/gnome-gnorba-check.m4	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,35 @@
+dnl
+dnl GNOME_GNORBA_HOOK (script-if-gnorba-found, failflag)
+dnl
+dnl if failflag is "failure" it aborts if gnorba is not found.
+dnl
+
+AC_DEFUN([GNOME_GNORBA_HOOK],[
+	GNOME_ORBIT_HOOK([],$2)
+	AC_CACHE_CHECK([for gnorba libraries],gnome_cv_gnorba_found,[
+		gnome_cv_gnorba_found=no
+		if test x$gnome_cv_orbit_found = xyes; then
+			GNORBA_CFLAGS="`gnome-config --cflags gnorba gnomeui`"
+			GNORBA_LIBS="`gnome-config --libs gnorba gnomeui`"
+			if test -n "$GNORBA_LIBS"; then
+				gnome_cv_gnorba_found=yes
+			fi
+		fi
+	])
+	AM_CONDITIONAL(HAVE_GNORBA, test x$gnome_cv_gnorba_found = xyes)
+	if test x$gnome_cv_orbit_found = xyes; then
+		$1
+		GNORBA_CFLAGS="`gnome-config --cflags gnorba gnomeui`"
+		GNORBA_LIBS="`gnome-config --libs gnorba gnomeui`"
+		AC_SUBST(GNORBA_CFLAGS)
+		AC_SUBST(GNORBA_LIBS)
+	else
+	    	if test x$2 = xfailure; then
+			AC_MSG_ERROR(gnorba library not installed or installation problem)
+	    	fi
+	fi
+])
+
+AC_DEFUN([GNOME_GNORBA_CHECK], [
+	GNOME_GNORBA_HOOK([],failure)
+])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m4/gnome-orbit-check.m4	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,33 @@
+dnl
+dnl GNOME_ORBIT_HOOK (script-if-orbit-found, failflag)
+dnl
+dnl if failflag is "failure" it aborts if orbit is not found.
+dnl
+
+AC_DEFUN([GNOME_ORBIT_HOOK],[
+	AC_PATH_PROG(ORBIT_CONFIG,orbit-config,no)
+	AC_PATH_PROG(ORBIT_IDL,orbit-idl,no)
+	AC_CACHE_CHECK([for working ORBit environment],gnome_cv_orbit_found,[
+		if test x$ORBIT_CONFIG = xno -o x$ORBIT_IDL = xno; then
+			gnome_cv_orbit_found=no
+		else
+			gnome_cv_orbit_found=yes
+		fi
+	])
+	AM_CONDITIONAL(HAVE_ORBIT, test x$gnome_cv_orbit_found = xyes)
+	if test x$gnome_cv_orbit_found = xyes; then
+		$1
+		ORBIT_CFLAGS=`orbit-config --cflags client server`
+		ORBIT_LIBS=`orbit-config --use-service=name --libs client server`
+		AC_SUBST(ORBIT_CFLAGS)
+		AC_SUBST(ORBIT_LIBS)
+	else
+    		if test x$2 = xfailure; then
+			AC_MSG_ERROR(ORBit not installed or installation problem)
+    		fi
+	fi
+])
+
+AC_DEFUN([GNOME_ORBIT_CHECK], [
+	GNOME_ORBIT_HOOK([],failure)
+])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m4/gnome-pthread-check.m4	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,16 @@
+dnl
+dnl And better, use gthreads instead...
+dnl
+
+AC_DEFUN([GNOME_PTHREAD_CHECK],[
+	PTHREAD_LIB=""
+	AC_CHECK_LIB(pthread, pthread_create, PTHREAD_LIB="-lpthread",
+		[AC_CHECK_LIB(pthreads, pthread_create, PTHREAD_LIB="-lpthreads",
+		    [AC_CHECK_LIB(c_r, pthread_create, PTHREAD_LIB="-lc_r",
+			[AC_CHECK_FUNC(pthread_create)]
+		    )]
+		)]
+	)
+	AC_SUBST(PTHREAD_LIB)
+	AC_PROVIDE([GNOME_PTHREAD_CHECK])
+])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m4/gnome-x-checks.m4	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,80 @@
+dnl GNOME_X_CHECKS
+dnl
+dnl Basic X11 related checks for X11.  At the end, the following will be
+dnl defined/changed:
+dnl   GTK_{CFLAGS,LIBS}      From AM_PATH_GTK
+dnl   CPPFLAGS		     Will include $X_CFLAGS
+dnl   GNOME_HAVE_SM	     `true' or `false' depending on whether session
+dnl                          management is available.  It is available if
+dnl                          both -lSM and X11/SM/SMlib.h exist.  (Some
+dnl                          Solaris boxes have the library but not the header)
+dnl   XPM_LIBS               -lXpm if Xpm library is present, otherwise ""
+dnl
+dnl The following configure cache variables are defined (but not used):
+dnl   gnome_cv_passdown_{x_libs,X_LIBS,X_CFLAGS}
+dnl
+AC_DEFUN([GNOME_X_CHECKS],
+[
+	AM_PATH_GTK(1.2.0,,AC_MSG_ERROR(GTK not installed, or gtk-config not in path))
+	dnl Hope that GTK_CFLAGS have only -I and -D.  Otherwise, we could
+	dnl   test -z "$x_includes" || CPPFLAGS="$CPPFLAGS -I$x_includes"
+	dnl
+	dnl Use CPPFLAGS instead of CFLAGS because AC_CHECK_HEADERS uses
+	dnl CPPFLAGS, not CFLAGS
+        CPPFLAGS="$CPPFLAGS $GTK_CFLAGS"
+
+        saved_ldflags="$LDFLAGS"
+        LDFLAGS="$LDFLAGS $GTK_LIBS"
+
+	gnome_cv_passdown_x_libs="$GTK_LIBS"
+	gnome_cv_passdown_X_LIBS="$GTK_LIBS"
+	gnome_cv_passdown_X_CFLAGS="$GTK_CFLAGS"
+	gnome_cv_passdown_GTK_LIBS="$GTK_LIBS"
+
+        LDFLAGS="$saved_ldflags $GTK_LIBS"
+
+dnl We are requiring GTK >= 1.1.1, which means this will be fine anyhow.
+	USE_DEVGTK=true
+
+dnl	AC_MSG_CHECKING([whether to use features from (unstable) GTK+ 1.1.x])
+dnl	AC_EGREP_CPP(answer_affirmatively,
+dnl	[#include <gtk/gtkfeatures.h>
+dnl	#ifdef GTK_HAVE_FEATURES_1_1_0
+dnl	   answer_affirmatively
+dnl	#endif
+dnl	], dev_gtk=yes, dev_gtk=no)
+dnl	if test "$dev_gtk" = "yes"; then
+dnl	   USE_DEVGTK=true
+dnl	fi
+dnl	AC_MSG_RESULT("$dev_gtk")
+
+	GNOME_HAVE_SM=true
+	case "$GTK_LIBS" in
+	 *-lSM*)
+	    dnl Already found it.
+	    ;;
+	 *)
+	    dnl Assume that if we have -lSM then we also have -lICE.
+	    AC_CHECK_LIB(SM, SmcSaveYourselfDone,
+	        [GTK_LIBS="-lSM -lICE $GTK_LIBS"],GNOME_HAVE_SM=false,
+		$x_libs -lICE)
+	    ;;
+	esac
+
+	if test "$GNOME_HAVE_SM" = true; then
+	   AC_CHECK_HEADERS(X11/SM/SMlib.h,,GNOME_HAVE_SM=false)
+	fi
+
+	if test "$GNOME_HAVE_SM" = true; then
+	   AC_DEFINE(HAVE_LIBSM)
+	fi
+
+	XPM_LIBS=""
+	AC_CHECK_LIB(Xpm, XpmFreeXpmImage, [XPM_LIBS="-lXpm"], , $x_libs)
+	AC_SUBST(XPM_LIBS)
+
+	AC_REQUIRE([GNOME_PTHREAD_CHECK])
+        LDFLAGS="$saved_ldflags"
+
+	AC_PROVIDE([GNOME_X_CHECKS])
+])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m4/gnome.m4	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,124 @@
+dnl
+dnl GNOME_INIT_HOOK (script-if-gnome-enabled, [failflag], [additional-inits])
+dnl
+dnl if failflag is "fail" then GNOME_INIT_HOOK will abort if gnomeConf.sh
+dnl is not found. 
+dnl
+
+AC_DEFUN([GNOME_INIT_HOOK],[
+	AC_SUBST(GNOME_LIBS)
+	AC_SUBST(GNOMEUI_LIBS)
+	AC_SUBST(GNOMEGNORBA_LIBS)
+	AC_SUBST(GTKXMHTML_LIBS)
+	AC_SUBST(ZVT_LIBS)
+	AC_SUBST(GNOME_LIBDIR)
+	AC_SUBST(GNOME_INCLUDEDIR)
+
+	AC_ARG_WITH(gnome-includes,
+	[  --with-gnome-includes   Specify location of GNOME headers],[
+	CFLAGS="$CFLAGS -I$withval"
+	])
+	
+	AC_ARG_WITH(gnome-libs,
+	[  --with-gnome-libs       Specify location of GNOME libs],[
+	LDFLAGS="$LDFLAGS -L$withval"
+	gnome_prefix=$withval
+	])
+
+	AC_ARG_WITH(gnome,
+	[  --with-gnome            Specify prefix for GNOME files],
+		if test x$withval = xyes; then
+	    		want_gnome=yes
+	    		dnl Note that an empty true branch is not
+			dnl valid sh syntax.
+	    		ifelse([$1], [], :, [$1])
+        	else
+	    		if test "x$withval" = xno; then
+	        		want_gnome=no
+	    		else
+	        		want_gnome=yes
+	    			LDFLAGS="$LDFLAGS -L$withval/lib"
+	    			CFLAGS="$CFLAGS -I$withval/include"
+	    			gnome_prefix=$withval/lib
+	    		fi
+  		fi,
+		want_gnome=yes)
+
+	if test "x$want_gnome" = xyes; then
+
+	    AC_PATH_PROG(GNOME_CONFIG,gnome-config,no)
+	    if test "$GNOME_CONFIG" = "no"; then
+	      no_gnome_config="yes"
+	    else
+	      AC_MSG_CHECKING(if $GNOME_CONFIG works)
+	      if $GNOME_CONFIG --libs-only-l gnome >/dev/null 2>&1; then
+	        AC_MSG_RESULT(yes)
+	        GNOME_GNORBA_HOOK([],$2)
+	        GNOME_LIBS="`$GNOME_CONFIG --libs-only-l gnome`"
+	        GNOMEUI_LIBS="`$GNOME_CONFIG --libs-only-l gnomeui`"
+	        GNOMEGNORBA_LIBS="`$GNOME_CONFIG --libs-only-l gnorba gnomeui`"
+	        GTKXMHTML_LIBS="`$GNOME_CONFIG --libs-only-l gtkxmhtml`"
+		ZVT_LIBS="`$GNOME_CONFIG --libs-only-l zvt`"
+	        GNOME_LIBDIR="`$GNOME_CONFIG --libs-only-L gnorba gnomeui`"
+	        GNOME_INCLUDEDIR="`$GNOME_CONFIG --cflags gnorba gnomeui`"
+                $1
+	      else
+	        AC_MSG_RESULT(no)
+	        no_gnome_config="yes"
+              fi
+            fi
+
+	    if test x$exec_prefix = xNONE; then
+	        if test x$prefix = xNONE; then
+		    gnome_prefix=$ac_default_prefix/lib
+	        else
+ 		    gnome_prefix=$prefix/lib
+	        fi
+	    else
+	        gnome_prefix=`eval echo \`echo $libdir\``
+	    fi
+	
+	    if test "$no_gnome_config" = "yes"; then
+              AC_MSG_CHECKING(for gnomeConf.sh file in $gnome_prefix)
+	      if test -f $gnome_prefix/gnomeConf.sh; then
+	        AC_MSG_RESULT(found)
+	        echo "loading gnome configuration from" \
+		     "$gnome_prefix/gnomeConf.sh"
+	        . $gnome_prefix/gnomeConf.sh
+	        $1
+	      else
+	        AC_MSG_RESULT(not found)
+ 	        if test x$2 = xfail; then
+	          AC_MSG_ERROR(Could not find the gnomeConf.sh file that is generated by gnome-libs install)
+ 	        fi
+	      fi
+            fi
+	fi
+
+	if test -n "$3"; then
+	  n="$3"
+	  for i in $n; do
+	    AC_MSG_CHECKING(extra library $i)
+	    case $i in 
+	      applets)
+		AC_SUBST(GNOME_APPLETS_LIBS)
+		GNOME_APPLETS_LIBS=`$GNOME_CONFIG --libs-only-l applets`
+		AC_MSG_RESULT($GNOME_APPLETS_LIBS);;
+	      capplet)
+		AC_SUBST(GNOME_CAPPLET_LIBS)
+		GNOME_CAPPLET_LIBS=`$GNOME_CONFIG --libs-only-l capplet`
+		AC_MSG_RESULT($GNOME_CAPPLET_LIBS);;
+	      *)
+		AC_MSG_RESULT(unknown library)
+	    esac
+	  done
+	fi
+])
+
+dnl
+dnl GNOME_INIT ([additional-inits])
+dnl
+
+AC_DEFUN([GNOME_INIT],[
+	GNOME_INIT_HOOK([],fail,$1)
+])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pixmaps/.cvsignore	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,2 @@
+Makefile.in
+Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/.cvsignore	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,5 @@
+Makefile.in
+Makefile
+.deps
+.libs
+gaim