Initial commit
This commit is contained in:
commit
8c52e5dba8
|
@ -0,0 +1,21 @@
|
|||
Makefile.in
|
||||
Makefile
|
||||
aclocal.m4
|
||||
configure
|
||||
config.h.in
|
||||
config.h
|
||||
config.log
|
||||
config.cache
|
||||
config.status
|
||||
install-sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
stamp-h.in
|
||||
stamp-h
|
||||
autom4te.cache
|
||||
debian/autoreconf.after
|
||||
debian/autoreconf.before
|
||||
debian/debhelper-build-stamp
|
||||
debian/*.ex
|
||||
debian/ic35link
|
||||
debian/.debhelper
|
|
@ -0,0 +1,5 @@
|
|||
IC35Link was written by Thomas Schulz,
|
||||
see the file THANKS about contributions.
|
||||
|
||||
Thomas Schulz <t.schulz@d2mail.de>
|
||||
|
|
@ -0,0 +1,340 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 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.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,683 @@
|
|||
$Id: ChangeLog,v 1.26 2001/11/20 23:26:42 thosch Exp $
|
||||
ChangeLog for IC35 communication
|
||||
================================
|
||||
|
||||
2001-11-10 version 1.18.1 (CVS only)
|
||||
* ic35mgr.c,mgrtrans.c,mgrtrans.h,mgrproto.h,mgrproto.c: new ic35mgr
|
||||
commands "mmcgettree","mmcputtree" for transfer whole directory tree
|
||||
contributed by Hans-Michael Stahl <hm.stahl@berlin.de>
|
||||
|
||||
2001-08-12 version 1.18 IC35LINK-1-18
|
||||
long pending release with several improvements and corrections
|
||||
according to suggestions and bug reports by users.
|
||||
improvements:
|
||||
- improved README: table of contents, restrictions, more explanations
|
||||
- ic35mgr restore and MMC write 30% faster (proposal by Harald Becker)
|
||||
- ic35sync, ic35mgr, vcaconv now support long options, e.g. "--help"
|
||||
info enquiry with "--help" or "--version" now returns exitcode 0
|
||||
- new autogen.sh script for generate configure etc. after CVS checkout
|
||||
(thanks Konrad Mader for report about missing configure in CVS)
|
||||
- new configure option "--disable-logandcomsim" for conditional compile
|
||||
without logging and com-simulation (proposal by Harald Becker)
|
||||
- new configure options "--enable-ansi" and "--enable-pedantic"
|
||||
bugfixes:
|
||||
- fixed problem where ic35sync with many (ca. 860) addresses failed
|
||||
(thanks Konrad Mader for bug report "get_mod_flen failed")
|
||||
- ic35sync now accepts also empty PIMfile(s), e.g. empty ic35.memo
|
||||
(thanks Malte Schmidt for bug report "ic35.memo: parse error")
|
||||
- ic35mgr MMCard functions now check ic35path before accessing IC35
|
||||
e.g. warn if shell eat backslash (\) in unquoted MMCard1\test.txt
|
||||
(thanks Thomas Lichtenberg for bug report)
|
||||
- restricted ic35mgr to max.blocksize 16350 found by experiments
|
||||
- ic35sync, ic35mgr now abort on open failure of logfile or simfile
|
||||
- fixed com-simulation for adjacent "RD nn" lines and non-logged bytes
|
||||
- fixed compile problem util.c with Linux Mandrake-8.0 and SuSE-7.2
|
||||
(thanks Christian Theile, Karl Stroetmann for bug reports)
|
||||
- corrected warnings from "--enable-ansi" and "--missing-prototypes"
|
||||
- fixed all Makefile.am: maintainer-clean keeps only sources in CVS,
|
||||
install also README and COPYING, clean dependencies and versinfo.c
|
||||
2001-08-12_05
|
||||
* Makefile.am: maintainer-clean delete also INSTALL, as not in CVS
|
||||
* autogen.sh: clearified CONFIGURE_FLAGS and NOCONFIGURE
|
||||
* README: didactic reordering, explain autogen.sh maintainer-mode,
|
||||
initial test with 'ic35sync status', tested some more platforms
|
||||
2001-08-02_22
|
||||
* autogen.sh: new script for generating configure and Makefile.in etc.
|
||||
thanks Konrad Mader <konrad.mader@gmx.de> for problem report about
|
||||
configure missing in CVS
|
||||
* README: explain when and how to use autogen.sh
|
||||
2001-06-18_01 version 1.17.6 (CVS only)
|
||||
* synproto.c: timeout 2.0 sec for L1-ack1 response on L1-command
|
||||
thanks Konrad Mader <konrad.mader@gmx.de> for bug report where
|
||||
sync of ca. 860 addresses caused "get_mod_flen failed"
|
||||
2001-06-09_11
|
||||
* util.c: explicitely #include <time.h>, as using localtime() etc.
|
||||
thanks Christian Theile <ch_theile@gmx.de> for bug report with
|
||||
Mandrake 8.0 gcc 2.96
|
||||
2001-03-03_04
|
||||
* ic35mgr.c,comio.c,comio.h: new option "--nice=NICEVAL" to lower
|
||||
process priority with restore,mmcput, default "--nice=2", works
|
||||
like builtin 'nice -n 2 ic35mgr mmcput ..", see nice(1).
|
||||
(proposal from Harald Becker)
|
||||
2001-03-02_02 version 1.17.5 (CVS only)
|
||||
* configure.in,README: new configure option "--disable-logandcomsim"
|
||||
(proposal from Harald Becker)
|
||||
* ic35sync.c,dataio.c,databin.c,datavca.c,ic35frec.c,syntrans.c,
|
||||
ic35mgr.c,mgrtrans.c,mgrproto.c,comio.{c,h},util.{c,h}:
|
||||
conditional compile for logging and com-simulation (default enabled)
|
||||
* ic35sync.c,ic35mgr.c,comio.c,util.c:
|
||||
log_init(),com_siminit() abort program on failure opening file
|
||||
* util.{c,h}: new fatal() reports error message and aborts program
|
||||
2001-02-22_05
|
||||
* datavca.c bugfix: accept also empty PIMfile(s), e.g. empty ic35.memo
|
||||
ic35sync creates empty ic35.memo if IC35 has no memo records, and
|
||||
next call ic35sync complained "vCard/vCal "ic35.memo": parse error"
|
||||
(thanks Malte Schmidt for bug report)
|
||||
* README: explain 1..3 PIMfiles, more details about export,import,sync
|
||||
2001-02-19_19
|
||||
* comio.c: com_sendw() delay with busy wait instead of interval timer
|
||||
increased write MMCard file throughput to 1740 b/s (with 2kB blocks)
|
||||
(thanks Harald Becker)
|
||||
* ic35mgr.c: max.blocksize 16350 for MMC read/write found by experiments
|
||||
* mgrproto.c: timeout 5.0 sec for response length needed with big blocks
|
||||
2001-02-19_02 version 1.17.4 (CVS only)
|
||||
* ic35mgr.c: MMCard functions now check ic35path before accessing IC35
|
||||
(thanks Thomas Lichtenberg for bug report)
|
||||
* comio.c: fixed com_simrecv() adjacent "RD nn" lines, non-logged bytes
|
||||
* README: remarks about install-strip and uninstall
|
||||
* all Makefile.am: maintainer-clean keeps only sources under CVS
|
||||
* .cvsignore,src/.cvsignore: added missing config.log, programs, .deps
|
||||
2001-02-17_21 version 1.17.3 (CVS only)
|
||||
* ic35sync.c,ic35mgr.c,vcaconv.c: support long options, e.g. "--help"
|
||||
info enquiry with "--help" or "--version" now returns exitcode 0
|
||||
* ic35sync.c,ic35mgr.c,comio.h,comio.c,util.h,util.c:
|
||||
error exit on open failure of logfile or simfile
|
||||
* README: 'configure --enable-ansi' is ok, warning '--enable-pedantic'
|
||||
successful tests on some more platforms (thanks Thomas Lichtenberg)
|
||||
restrictions of ic35sync and ic35mgr
|
||||
* configure.in: pass revision info to configure
|
||||
* Makefile.am: install also README and COPYING
|
||||
* src/Makefile.am: clean dependencies and versinfo.c
|
||||
2001-02-10_04 version 1.17.1 (CVS only)
|
||||
* configure.in: separate "ansi" and "pedantic" gcc compile options
|
||||
* ic35sync.c,ic35mgr.c,datavca.c,port.h,vcc.y,comio.c:
|
||||
corrected warnings from "-ansi" compile
|
||||
* util.c,util.h,comio.c,comio.h:
|
||||
local substitutes for functions missing with "-ansi" compile
|
||||
2001-02-07_04
|
||||
* configure.in: more compile warnings with "--missing-prototypes"
|
||||
* databin.c,mgrtrans.c,vcc.y,vobject.c:
|
||||
corrected warnings from "--missing-prototypes"
|
||||
* README: table of contents, warning about 'configure --enable-ansi'
|
||||
|
||||
2001-02-05_03 IC35LINK-1-17
|
||||
package renamed to "ic35link" and automake/autoconf/CVS reorganization.
|
||||
no changes in sources, programs are unchanged except for version (and
|
||||
except for compile with -O2 instead of -O due to automake/autoconf).
|
||||
new files:
|
||||
NEWS release information
|
||||
AUTHORS authors
|
||||
THANKS contributors
|
||||
configure.in input for autoconf to create configure
|
||||
Makefile.am input for automake to create Makefile.in
|
||||
.cvsignore topdir CVS ignore patterns
|
||||
doc/ subdirectory with documentation
|
||||
doc/Makefile.am input for automake to create doc/Makefile.in
|
||||
doc/.cvsignore CVS ignore patterns
|
||||
src/ subdirectory with sources
|
||||
src/Makefile.am input for automake to create doc/Makefile.in
|
||||
src/.cvsignore CVS ignore patterns
|
||||
|
||||
2001-02-04_02 IC35SYNC-1-16
|
||||
this is a bugfix and redesign release and is the last named "ic35sync".
|
||||
(the package will be renamed to "ic35link" in the next release, when
|
||||
the reorganizations for automake/autoconf and public CVS are done.)
|
||||
improvements and redesign:
|
||||
- ic35sync,ic35mgr,vcaconv now report package version and build info
|
||||
- distribution includes vcc.c to handle missing/bad 'bison' or 'yacc'
|
||||
(e.g. SuSE-7.0's yacc produced bad vcc.o, thanks Michael Bruennert)
|
||||
- reworked and clearified the IC35 manager protocol documentation and
|
||||
implementation (see ic35mgr.txt, mgrtrans.*, mgrproto.*), refer to
|
||||
the IC35 SoftwareDevelopmentKit API MMCard functions in mgrproto.c
|
||||
bugfixes in ic35mgr and ic35sync:
|
||||
- fixed compile error RedHat-7.0 gcc-2.96 (thanks Dieter Schultschik)
|
||||
- corrections for 'ic35mgr status' (thanks Michael Bruennert):
|
||||
mgrtrans.c:status() tries to get IC35 response instead of only wait
|
||||
mgrproto.c:MMCsend() sends blocklength with initial wait
|
||||
corrected output of MMCard2 label
|
||||
- ic35mgr commands backup and restore show error messages on new line
|
||||
- avoid failing 'ic35mgr restore ..' at "disconnect" by delay 3.25 sec
|
||||
after writedatabase() done
|
||||
- avoid failure of 'ic35mgr mmcput file' with occasional slow IC35
|
||||
MMCard write with 3.5 sec timeout for length of response block
|
||||
- corrected MMC closedir,closefile response PDUs having no status-word
|
||||
- corrected to make 'ic35sync status' work also with simulation file
|
||||
2001-02-04_01
|
||||
* ic35sync.c,ic35mgr.c,vcaconv.c,Makefile:
|
||||
import version info from auto-generated "versinfo.c"
|
||||
all programs now report the common package version
|
||||
* util.{c,h}: new log_proginfo(),log_argsinfo() used
|
||||
by ic35sync.c,ic35mgr.c for initial info in logfile
|
||||
* ic35sync.c: corrected com_siminit() before status command
|
||||
* Makefile: include vcc.c in distribution to avoid bison/yacc problems
|
||||
2001-02-03_20
|
||||
* mgrproto.h,mgrtrans.h: moved MMC file attributes and open modes
|
||||
from mgrtrans.h to mgrproto.h as needed for MMCxxxx() functions
|
||||
* mgrproto.c,mgrtrans.c: common conversions functions for FILE_INFO
|
||||
import FIDENSZ for accurate size of FILE_IDEN from IC35 SDK Mmc.h
|
||||
* ic35mgr.txt: incorporated protocol corrections due to experience
|
||||
2001-01-30_01
|
||||
* mgrproto.c: need 3.5 sec timeout for length of response block
|
||||
2001-01-29_13
|
||||
* fixed compile error gcc-2.96 RedHat-7.0 (thanks Dieter Schultschik):
|
||||
synproto.c now passes 'int' instead of 'ushort to 'va_arg', because
|
||||
`short unsigned int' is promoted to `int' when passed through `...'
|
||||
* mgrproto.h,mgrproto.c,mgrtrans.c:
|
||||
new MMCard command functions MMCxxxx() replace sendmcmd(),recvmcmd()
|
||||
for better prototype check and avoid the gcc-2.96 RedHat-7.0 problem
|
||||
refer to IC35 SoftwareDevelopmentKit API MMCard functions
|
||||
* synproto.c,mgrproto.c,ic35frec.c offsetof,alenof macros now in util.h
|
||||
2001-01-27_05
|
||||
* bugfix "ic35mgr status" (thanks to Michael Bruennert):
|
||||
mgrtrans.c:status() tries to get IC35 response instead of only wait
|
||||
mgrproto.c:MMCsend() sends blocklength with initial wait
|
||||
ic35mgr.c: corrected MMCard2 label output
|
||||
* ic35mgr.c,util.{c,h}: extracted _not_impl() to util.{c,h}
|
||||
2001-01-25_05
|
||||
* mgrtrans.c,mgrproto.c,ic35mgr.txt:
|
||||
corrected: closedir,closefile response PDUs do not have status-word
|
||||
* mgrtrans.c: backup,restore show error messages on new line
|
||||
writedatabase() delays 3.25 sec to avoid failure in mdisconnect()
|
||||
* mgrtrans.c,mgrproto.c,mgrproto.h,genproto.h:
|
||||
reorganized manager protocol, new Mcmdrsp(),Msendblk(),Mrecvblk()
|
||||
* ic35mgr.txt: described and incorporated basic protocol operations
|
||||
2001-01-21_21
|
||||
* genproto.c,genproto.h,Makefile,README:
|
||||
new module genproto.{c,h} - general IC35 protocol support
|
||||
* synproto.c,mgrproto.c: import PDU encode/decode with genproto.h
|
||||
* syntrans.c,mgrtrans.c: import general welcome() with genproto.h
|
||||
|
||||
2001-01-20_03 IC35SYNC-1-15
|
||||
new IC35 manager 'ic35mgr' supports access of IC35 MMCard(s)
|
||||
- command "mmcdir" lists contents of MMCard(s)
|
||||
- commands "mmcget","mmcput","mmcdel" read,write,delete MMCard file
|
||||
- commands "backup","restore" IC35 organizer database
|
||||
- ic35mgr.txt now really describes the IC35 manager protocol
|
||||
(previously it was just extracts of Windows 'portmon' logfiles)
|
||||
bugfixes in ic35sync and vcaconv:
|
||||
- "ic35sync sync" now updates record if on IC35, else writes new record
|
||||
- "vcaconv sortvca ic35.vcal" did produce empty output, fixed vobject.c
|
||||
- fixed vcc.y compile warnings
|
||||
- "vcaconv sortvca .." improved: shows properties in sort order sequence
|
||||
todo:
|
||||
- ic35mgr install application on IC35
|
||||
- ic35sync initial sync does not yet write all records to IC35
|
||||
workaround: do "ic35sync import .." before first "ic35sync sync .."
|
||||
* ic35mgr.c: fixed compile warning with unused _not_impl()
|
||||
2001-01-18_02
|
||||
* comio.{c,h},mgrproto.c,mgrtrans.c:
|
||||
new com_sendw() - send datablock with waiting (for slow MMCard ops)
|
||||
com_send() does send without delays at full speed
|
||||
* mgrtrans.c: status() needs 10 msec delay to let IC35 get ready
|
||||
2001-01-17_05
|
||||
* ic35mgr.c,mgrtrans.c:
|
||||
implemented "restore" IC35 organizer database from file, tested OK
|
||||
2001-01-16_05
|
||||
* ic35mgr.c,mgrtrans.h,mgrtrans.c:
|
||||
implemented "backup" IC35 organizer database to file, tested OK
|
||||
* ic35mgr.txt: corrected details IC35 backup: head retry, last ack resp
|
||||
2001-01-14_23
|
||||
* README: IC35 manager modules and usage, short section "programs"
|
||||
2001-01-14_22
|
||||
* comio.c: com_send() using interval timer for delay increased
|
||||
write MMCard file throughput to 1350 b/s (with 2kB blocks)
|
||||
2001-01-14_01
|
||||
* ic35log.sh: new option "-s n" - prepend output with 1:line 2:time
|
||||
CAVEAT: "-s n" does not work for "-lsyn2", "-lsyn4"
|
||||
* Makefile: added missing ic35log,ic35mgr to "all" target
|
||||
2001-01-13_04
|
||||
* comio.c: made "mmcput" faster with 2 stopbits and delay every 29 bytes
|
||||
improved write MMCard to 890 b/s default 2kB blocks (930 b/s with 5kB)
|
||||
err.corr com_recv,comsend: handle un-opened com_fd to avoid segfault
|
||||
RCS branch 1.4.1 with experiments for throughput
|
||||
RCS branch 1.3.1 with com_simrecv() non-logged bytes (yet erroneous)
|
||||
2001-01-12_22
|
||||
ic35mgr "mmcget", "mmcput", "mmcdel" commands tested OK with IC35
|
||||
* ic35mgr.c,mgrtrans.h,mgrtrans.c,mgrproto.h,mgrproto.c:
|
||||
implemented "mmcput" - write file to IC35 MMCard, tested OK (but slow)
|
||||
implemented "mmcdel" - delete file on IC35 MMCard, tested OK (fast ;-)
|
||||
additional 'mode' parameter for mmc_openfile(),sendmcmd(MCMDopenfile,)
|
||||
* ic35mgr.c: new option "-b size" - read/write blocksize (for tests)
|
||||
corrected mmcget,mmcput show progress: space to separate errormessage
|
||||
* mgrproto.c: log checksum error in MPDUsend(),MPDUrecv() for diagnostic
|
||||
* ic35mgr.txt: MMCard operations for write file, delete file
|
||||
table of contents, table of MMCard operation functions and codes
|
||||
moved logfile reference to end, removed hacked log extracts
|
||||
read MMCard file throughput 2250 b/s with default 5kB blocksize
|
||||
write MMCard file throughput 590 b/s default 2kB (610 b/s with 5kB)
|
||||
2001-01-10_02
|
||||
* ic35mgr.c: mmcget,mmcput without 'file' arg derive it from ic35path
|
||||
mmcget converts ic35path lowercase to uppercase, translate '/' to '\'
|
||||
mmcget shows file transfer progress every 5kB read data
|
||||
2001-01-09_05
|
||||
* ic35mgr.c,mgrtrans.h,mgrtrans.c,mgrproto.h,mgrproto.c:
|
||||
implemented "mmcget" - read file from IC35 MMCard, tested OK
|
||||
* mgrproto.c: MPDUrecv() needs receive timeout increased to 2.0 sec
|
||||
2001-01-08_03
|
||||
ic35mgr "mmcdir" corrected and tested OK with IC35
|
||||
* ic35mgr.c: mmcdir output to stdout for simpler redirect to file
|
||||
mmcdir output also MMC file attribute, do not read IC35 status data
|
||||
* mgrtrans.c: status() must always send '\x50' to init IC35,
|
||||
status() optionally reads status data, fixed typo mmctstampstr()
|
||||
* mgrproto.c: reduced MAXRETRY to 5 for MPDUsend(),MPDUrecv()
|
||||
corrected retry protocol MPDUsend(), 10 sec timeout nn_nn response
|
||||
err.corr sendmcmd(): puttxt0() append trailing '\0' to dirpath in pdu
|
||||
* comio.c: delays 100 usec before send every 16th byte (slow MMCard ops)
|
||||
* comio.c,comio.h: com_settimeout() return previous timeout
|
||||
* ic35mgr.txt: details about MMCard ops filestatus block from IC35 SDK
|
||||
read status data from IC35 is optional, initial send 50 is mandatory
|
||||
negative acknowledge in MMCard operations protocol
|
||||
2001-01-07_06
|
||||
* ic35mgr.c,mgrtrans.h,mgrtrans.c,mgrproto.h,mgrproto.c:
|
||||
implemented directory listing of MMCard(s), tested OK with simulation
|
||||
corrected max.length of MMC label to 11 chars (IC35 SDK API Ref.Guide)
|
||||
* mgrtrans.c: corrected mdisconnect(): send 09 recv 90, send 01 recv 90
|
||||
mconnect() reads IC35 status only if statfname specified, log mconnect
|
||||
problem: MMCard(s) directory listing does not work with IC35,
|
||||
checksum error / timeout on send command get directory length
|
||||
uncertain if read IC35 status data needed in ic35mgr.c:ic35mmcdir()
|
||||
2001-01-04_07
|
||||
* ic35mgr.txt: description of MMCard operations and backup,restore
|
||||
* ic35mgr.c,mgrtrans.h,mgrtrans.c,mgrproto.h,mgrproto.c,Makefile
|
||||
first version of IC35 Manager, "status" command working with IC35
|
||||
* syntrans.c: removed not needed headers <time.h>,"dataio.h"
|
||||
2001-01-01_20
|
||||
* ic35mgr.c: framework for (yet non-functional) IC35 Manager commands
|
||||
2000-12-31_18
|
||||
* vcc.y: corrected compile warnings about unused functions
|
||||
fixed yacc/bison warning: %expect 2 shift/reduce conflicts for "items"
|
||||
use YYERROR_VERBOSE for parse error reports, disabled useless YYDEBUG
|
||||
* vobject.c: correct delList(): return removed vobj even if first
|
||||
* vcaconv.c: improved "sortvca": show properties in sort order sequence
|
||||
sort todo by due-time,summary, memo by summary,modify-time
|
||||
compare date+time independant of encoding
|
||||
* ic35sync.c: corrected "sync": update record if on IC35, else write new
|
||||
|
||||
2000-12-28_04 IC35SYNC-1-14
|
||||
ic35sync import,sync step-5 done: "sync" command, misc. improvements
|
||||
- sync command for synchronize vCard,vCalendar format PIMdata with IC35
|
||||
- corrected convert of PIM BDAY birthday to IC35 for yyyy-mm-dd format
|
||||
- PIM multiple CATEGORIES now preserved by prepend category from IC35,
|
||||
single or standard of multiple CATEGORIES are replaced
|
||||
- PIM fullname FN now preserved, IC35 updates first,last name into it
|
||||
- put first 2 EMAIL entries from vCard into IC35 address Email1,Email2
|
||||
- put unspecific telno to IC35 TelWork for "Business", else to TelHome
|
||||
- map IC35 address "(def.)"s in VCARD.NOTE marked "(def1):","(def2):"
|
||||
- conversion IC35 to/from PIM record does now yet delete record fields
|
||||
- extracted data formats from dataio.c into separate modules:
|
||||
datatxt.c text format (output only)
|
||||
databin.c binary IC35 record format
|
||||
datavca.c vCard,vCalendar format
|
||||
vcutil.c vCard,vCalendar utilities
|
||||
vcutil.h header for vCard,vCalendar utilities
|
||||
fixes for gnomecard from gnome-pim_1.2.0:
|
||||
- compare VCARD.REV against old reference date+time from IC35, because
|
||||
gnomecard does not maintain X-PILOTSTAT.
|
||||
- write VCARD.REV:yyyy-mm-ddThh:mm:ss, because yyyymmddThhmmss was
|
||||
ignored by gnomecard.
|
||||
fixes for gnomecal from gnome-pim_1.2.0:
|
||||
- first line of VEVENT.SUMMARY to/from IC35 Summary, remaining lines
|
||||
to/from Notes, because gnomecal does not support VEVENT.DESCRIPTION
|
||||
- keep unsupported property VTODO.DTSTART marked in VTODO.DESCRIPTION
|
||||
- add VEVENT,VTODO.CLASS:PUBLIC, else gnomecal would crash on edit
|
||||
fixes for korganizer v1.1.1:
|
||||
- put UID:IC35id-xxxxxxxx to vCard,vCalender record if no UID there.
|
||||
- produce output vCard,vCal in same CRLF/NL-mode as found on input,
|
||||
as korganizer has NL-terminated lines in vCalendar.
|
||||
- translate IC35 CRLF to/from PIM NL in NOTE and DESCRIPTION fields.
|
||||
- keep unsupported properties VTODO.DTSTART,DUE,CATEGORIES as marked
|
||||
lines in VTODO.DESCRIPTION
|
||||
- korganizer supports only DALARM, map IC35 LED and Beep to/from it
|
||||
vcaconv extensions:
|
||||
- command "prvca" reports vCard/vCalendar parse error.
|
||||
- command "sortvca" outputs sorted vCard,vCalendar to standard output.
|
||||
- command "imphandy" appends vCards with category HANDY from vCard file
|
||||
to standard output, after import the result back into IC35 they are
|
||||
for upload to a mobile phone from IC35 addresses in category HANDY.
|
||||
CAVEAT:
|
||||
- no options for sync conflict resolve, PIMfile always overrides IC35!
|
||||
- IC35 has no different times for LED,Beep alarm, DALARM takes priority
|
||||
- vcaconv conversions do not transfer clean/modified record status
|
||||
- memory leak in vobject.c: all setVObject_*_Value() do not free the
|
||||
previously attached dupStr()-allocated string value
|
||||
* datavca.c,vcutil.{c,h}: support delete empty fields IC35 to/from PIM
|
||||
* vobject.c: correct delList(), delete (only) first in property list
|
||||
2000-12-27_21
|
||||
* comio.c: for simulate do not set DTR, allow "RDx" in simulation file
|
||||
* datavca.c,vcutil.c,vcutil.h:
|
||||
extracted vCard,vCal utilities from datavca.c to vcutil.c,vcutil.h
|
||||
new clr_vobjdirty(),SetModtimeIfdirty() for vCard,vCal modified time
|
||||
* vcaconv.c: use vCard,vCal utilities vcutil.c
|
||||
2000-12-27_01
|
||||
* datavca.c: correct vca_set_recid(): update UID if "IC35id-xxxxxxxx"
|
||||
2000-12-26_04
|
||||
* datavca.c: fixes for gnomecal,korganizer
|
||||
gnomecal does not support VTODO.DTSTART, keep in VTODO.DESCRIPTION
|
||||
avoid gnomecal crash on edit by add VTODO,VEVENT.CLASS:PUBLIC
|
||||
add VTODO,VEVENT.CLASS:PUBLIC, else gnomecal crashes on edit
|
||||
korganizer supports only DALARM, map IC35 LED and Beep to/from it
|
||||
* dataio.c,dataio.h,databin.c,datatxt.c,datavca.c:
|
||||
fix open,close logic: new argument mode=r/w/r+ for xxx_open()
|
||||
* dataio.c: no need to keep filenames
|
||||
2000-12-25_17
|
||||
* ic35sync.c: initial "sync" with empty PIM must export all IC35 recs
|
||||
* datavca.c: fixes for korganizer and gnomecal
|
||||
korganizer does not support VTODO.DTSTART,DUE,CATEGORIES, keep them
|
||||
as marked lines in VTODO.DESCRIPTION
|
||||
gnomecal does not support VEVENT.DESCRIPTION, keep the first line
|
||||
of VEVENT.SUMMARY in IC35 S_Summary, more lines in S_Notes
|
||||
* IC35 address fields with marks "(def1):","(def2):" to/from VCARD.NOTE
|
||||
* README: added installation, usage, disclaimer sections
|
||||
* Makefile: added COPYING (GPL) to distribution
|
||||
2000-12-23_19
|
||||
* datavca.c: default CLRF mode for output CRLF-terminated vCard,vCal
|
||||
unspecific telno to IC35 TelWork for "Business", else to TelHome
|
||||
replace single or standard of multiple categories, else prepend
|
||||
new _vca_type() centralizes/simplifies vCard,vCal record type detect
|
||||
* vcaconv.c: corrected "imphandy" to skip non-digit telno separators
|
||||
2000-12-23_15
|
||||
* dataio.{c,h},Makefile: extracted data formats into separate modules
|
||||
datatxt.c text format (output only)
|
||||
databin.c binary IC35 record format
|
||||
datavca.c vCard,vCalendar format
|
||||
* fixed problem with korganizer: translate IC35 CRLF to PIM NL in NOTEs
|
||||
* fixed SIGSEGV in SetCategory()
|
||||
2000-12-22_01
|
||||
* dataio.c,vcc.y,vobject.c,vobject.h:
|
||||
fixed problem with korganizer, has NL-terminated lines in vCalendar
|
||||
produce output vCard,vCal in same CRLF/NL-mode as found on input
|
||||
2000-12-21_22
|
||||
* dataio.c: corrected some conversions IC35 to/from PIM
|
||||
conversion to IC35 of PIM BDAY birthday failed with yyyy-mm-dd format
|
||||
PIM multiple CATEGORIES now preserved by prepend category from IC35
|
||||
PIM fullname FN now preserved, IC35 updated first,last name into it
|
||||
* vcaconv.c: "sortvca" now sorts VObject property lists to ease tests
|
||||
corrected "imphandy": created vCards lacked REV revised time
|
||||
2000-12-21_15
|
||||
improved reference date+time from IC35:
|
||||
* syntrans.{c,h},ic35sync.c: ReadSysInfo() and WriteSysInfo() replace
|
||||
old get_date_time(),set_date_time(), names like IC35Comm.dll
|
||||
* dataio.{c,h},ic35sync.c: new set_oldic35dt() and get_newic35dt()
|
||||
to convert IC35 old/new reference date+time to/from internal
|
||||
fixes for gnomecard from gnome-pim_1.2.0:
|
||||
* dataio.c: compare VCARD.REV against old reference date+time from IC35
|
||||
because gnomecard does not maintain X-PILOTSTAT
|
||||
write VCARD.REV:yyyy-mm-ddThh:mm:ss, because yyyymmddThhmmss was
|
||||
ignored by gnomecard
|
||||
2000-12-21_03
|
||||
* vobject.{c,h},dataio.c: delList(),delProp() do not cleanVObject()
|
||||
* fixed SEGV: dataio.c:_backup_and_openwr, ic35frec.c:_del_ic35recbuffs
|
||||
* dataio.c: correct vcard_to_ic35addr(): 1st/2nd EMAIL to A_Email1/2
|
||||
* vcaconv.c: new command "sortvca" - sort vCard,vCal file to stdout
|
||||
new command "imphandy" - import vCards for upload to handy telbook
|
||||
2000-12-19_02
|
||||
* syntrans.c: set_date_time() reports set sysinfo
|
||||
* ic35frec.c: set_ic35recdata(NULL,0) clears record-,field-buffers
|
||||
* ic35frec.h: added IC35 record change flag definitions
|
||||
* dataio.c: use IC35 record change flag definitions
|
||||
correct vca_open(): handle empty vCal file, report parse error
|
||||
(e.g. empty vCal file makes "sync" delete all IC35 records!)
|
||||
ic35xxx_to_vyyy(): put UID to record if not there, korganizer needs
|
||||
support pim_delrec(), vca_delrec() uses new delProp(),delList()
|
||||
* vobject.{c,h}: support delete property from vobj, vobj from list
|
||||
* vcaconv.c: command "prvca" reports vCard/vCal parse error
|
||||
(cannot use pim_openinp() like other commands, as pim_getrec()
|
||||
skips the VCALENDER property from vcafile with vCalender only.)
|
||||
* ic35sync.c: implemented "sync" command as ic35sync(),syncfile()
|
||||
importfile() collects IC35 actions, report num.of write/update/commit
|
||||
CAVEAT: no conflict resolve options, PIMfile always overrides IC35!
|
||||
|
||||
2000-12-17_21 IC35SYNC-1-13 not released to public
|
||||
ic35sync import,sync step-4 done: "import" command, misc. improvements
|
||||
- algorithm details described in ic35sync.c:ic35import(),ic35export()
|
||||
- import command for vCard,vCalendar or binary format PIMdata into IC35
|
||||
- status command (new) shows IC35 version, sysinfo, total,mod records
|
||||
- export command improved:
|
||||
export into existing PIMfile(s), backup e.g. ic35vcal to ic35.vcal~
|
||||
map IC35 address fields "(def.)" to/from VCARD:NOTE marked lines
|
||||
change vCard,vCalendar record modified time only if record changed
|
||||
support DCREATED in vCalendar: creation time of VEVENT,VTODO record
|
||||
corrected VEVENT:AALARM,DLARM, were sometimes wrongly created
|
||||
- support X-PILOTSTAT in vCard,vCal: 0=same, other=changed vs. IC35
|
||||
- default format changed to "vca" for primary use vCard,vCalendar
|
||||
- vcaconv may be used as filter with input/output from stdin/stdout
|
||||
- fixed QUOTED-PRINTABLE problem with multi-field properties (like
|
||||
VCARD:N, VCARD:ADR): due to problem with parser vcc.y and for
|
||||
compatibility with other programs using the vCard,vCal output
|
||||
QUOTED-PRINTABLE is not used on multi-field properties.
|
||||
(otherwise the split into field sub-properties fails and the
|
||||
first field (e.g. VCARD:ADR:STREET) gets the string of ALL the
|
||||
fields (e.g. STREET,CITY,etc.) with ";" within it.)
|
||||
todo: sync command, fix memory leak in vobject.c
|
||||
conversion IC35 to/from PIM record does not yet delete record fields,
|
||||
i.e. record on destination may differ and have fields not in source.
|
||||
may be delete field needed only for sync, because import/export are
|
||||
specified to not delete on destination.
|
||||
* ic35sync.c,syntrans.c,synproto.c: support new "status" command
|
||||
2000-12-17_08
|
||||
* dataio.c: attach CHARSET to toplevel prop (e.g. VCARD:N, VCARD:ADR)
|
||||
do not use QUOTED-PRINTABLE on e.g. VCARD:ADR due to parser problem
|
||||
move IC35 address "(def.)" fields with markers to/from VCARD:NOTE
|
||||
corrected for "vcaconv bin2txt .." conversion to standard output
|
||||
corrected StringValue(): handle C and Unicode string values
|
||||
ignore harmless LED,Beep, Start,EndTime differences (xxx_cmpic35rec)
|
||||
log pimfile open,close operations
|
||||
* ic35sync.c: default format now "vca", log ic35sync command line
|
||||
corrected importfile(): commit was too often (vca) or not done (bin)
|
||||
CAVEAT: delete field in convert vCard,vcal to/from IC35 not supported,
|
||||
i.e. record on destination may differ and have fields not in source
|
||||
2000-12-15_23
|
||||
* ic35sync.c: re-designed import, commented import,export algorithms
|
||||
compare all PIMrecs with IC35 and do commit/update/write to IC35
|
||||
do not set sysinfo (date+time) if any IC35 record not in PIMfile
|
||||
do not commit record on IC35 if not in PIMfile
|
||||
use new _xxx_ic35recs() for records from IC35
|
||||
* vcaconv.c,dataio.c: optionally use stdin/stdout to act as filter
|
||||
* dataio.c: set vCard,vCal record modified-time only if record changed
|
||||
added bin_cmpic35rec() - compare record from IC35 with binary record
|
||||
corrected _ChangeString(): handle C and Unicode string values
|
||||
fixed memory leak: pim_close() calls inpfmt close to free record list
|
||||
2000-12-14_23
|
||||
* dataio.c:
|
||||
ignore categoryIDs, repeat fields if no repeat (vca_cmpic35rec)
|
||||
corrected bin_open(): start with binlist after bin_rewind()
|
||||
corrected vca_open(): must add all memo records separately to vcalist
|
||||
corrected VCARD:FN space in fullname only if FirstName AND LastName
|
||||
new bin_updic35rec() for pim_putrec() with e.g. "vcaconv bin2txt .."
|
||||
* vcaconv.c: re-designed for generic PIM operations in dataio.c
|
||||
2000-12-14_00
|
||||
* ic35sync.c: corrections and improvements in importfile():
|
||||
must always update_frec() owner address data with recid=05000001,
|
||||
otherwise on IC35 in category "Address", but not as owner data
|
||||
write back recordID and CLEAN status to PIM only if write to IC35 OK
|
||||
fix memory leak: release newly created ic35rec
|
||||
shorten progress,error messages of import and export commands
|
||||
pim_cmpic35rec() params were swapped, close IC35 file after error
|
||||
* dataio.{c,h}: prepare for vcaconv with generic operations pim_xxx()
|
||||
pim_getrec() with fileid FILE_ANY=0 to get next record from any file
|
||||
pim_putrec() converts inpfmt record to pimfmt and writes to outfile
|
||||
pim_openinp() opens file for input and sets new inpfmt
|
||||
pim_openout() opens file for output and sets pimfmt
|
||||
removed old put_record(),_get_binrec(),_get_vcarec()
|
||||
CAVEAT memory leak: record list from pim_openinp() not freed
|
||||
2000-12-12_06
|
||||
* dataio.{c,h}: support DCREATED creation time of VEVENT,VTODO record
|
||||
support X-PILOTSTAT in vCard,vCal: 0=same, other=changed vs. IC35
|
||||
generic operations pim_xxx(), use function tables per format
|
||||
ic35xxx_to_vyyy() update existing instead of create vCard,vCal record
|
||||
read from existing pimfile(s), so that "ic35sync export" preserves
|
||||
corrected ic35sched_to_vevent(): create VEVENT:AALARM,DALARM only
|
||||
if S_AlarmBefore is non-zero, S_Alarm_Repeat may be absent and thus
|
||||
AlarmNoLED,AlarmNoBeep misleading
|
||||
* syntrans.{c,h}: readfile() extracted to ic35sync.c:exportfile()
|
||||
* ic35sync.c: implemented "import" command as ic35import(),importfile()
|
||||
stub for "sync" command ic35sync(),syncfile(), yet non-functional
|
||||
CAVEAT: memory leak in vobject.c: all setVObject_*_Value() do not free
|
||||
previously attached dupStr()-allocated string value
|
||||
dataio.c lacks some bin_xxx operations for import from binary format
|
||||
delete PIM-record not supported yet, missing support in vobject.c
|
||||
|
||||
2000-12-07_04 IC35SYNC-1-12 not released to public
|
||||
ic35sync import,sync step-3 done: convert vCard,vCal to IC35 record
|
||||
* dataio.c: convert vCard,vCal to IC35 record vxxxx_to_ic35yyyy()
|
||||
correct ic35addr_to_vcard(): set VCAdrProp if have any address field
|
||||
* dataio.{c,h}: export vCard,vCal to IC35 conversion as _get_vcarec()
|
||||
* ic35frec.c: corrected errors found with vCard,vCal to IC35 conversion
|
||||
* vcaconv.c: support "vca2bin", new "bin2txt" conversions
|
||||
* ic35sync.c: renamed ic35sync() to ic35export(), as that's what it does
|
||||
stubs ic35import(), ic35sync() for un-implemented functions
|
||||
connect() argument rdtime to retrieve value from IC35
|
||||
2000-12-03_23
|
||||
* ic35sync.txt: marked uncertain topics with "???"
|
||||
experiments found new commands: read record by record-ID (01 05)
|
||||
and write record data update (01 09), keeps recID on IC35 unchanged
|
||||
* syntrans.{c,h},synproto.{c,h}: implemented new commands
|
||||
read record by record-ID and write updated record data
|
||||
* ic35log.sh: support new commands readrecrid,updatrec
|
||||
2000-12-02_07
|
||||
ic35sync import,sync step-2 done:
|
||||
- new protocol functions for import,sync tested OK
|
||||
- new knowledge about import,sync from experiments
|
||||
todo: vCard,vCal to IC35 record, commands import,sync
|
||||
* synproto.c: corrected CMDfgetmlen, CMDcategory, CMDsetdtime
|
||||
* syntrans.{c,h}: connect() argument rdtime to retrieve value from IC35
|
||||
* vcaconv.c,dataio.c: handle binfile records without data
|
||||
* ic35log.sh: process ic35sync logfiles, fragmented response readmodrec
|
||||
* ic35sync.txt: new knowledge about open file, changeflag, write record
|
||||
first all read then write,del,commit, "date+time" may be any string
|
||||
|
||||
2000-12-01_20 IC35SYNC-1-11 not released to public
|
||||
intermediate freeze after ic35sync import,sync step-1 done:
|
||||
- new functions: set_date_time, category, get_mod_flen, read_mod_frec,
|
||||
write_frec, delete_frec, commit_frec
|
||||
- IC35 record access functions ic35frec.{c,h}
|
||||
- 4byte record-ID combined from file-id (MSB) and record-id (LSW)
|
||||
- support last-modified-time for vCard,vCalendar
|
||||
- protocol-analyser ic35log.sh replaces and extends ic35prot.awk
|
||||
todo: test new funcs, vCard,vCal to IC35 record, commands import,sync
|
||||
* dataio.c: use 4byte record-ID in binary format
|
||||
* ic35sync.c: IC35 file descriptions now from "ic35frec.h"
|
||||
2000-12-01_19
|
||||
* ic35sync.txt,ic35frec.h: comment max.lengths of record fields
|
||||
* dataio.c,syntrans.c,ic35frec.{c,h}:
|
||||
hide ic35 file description internals, use acces functions
|
||||
* ic35frec.c: truncate to max.field-length, set nflds from recID
|
||||
added missing 1byte-fields T_Completed,T_Priority
|
||||
* vcaconv.c: usage on "-h", report unknown conversion
|
||||
2000-12-01_02
|
||||
* ic35frec.{c,h}: IC35 record access and file descriptions
|
||||
* dataio.{c,h},syntrans.{c,h},vcaconv.c:
|
||||
adapted for IC35 record access functions and 4byte record-ID
|
||||
* synproto.c: adapted for 4byte record-ID combined of fileid,recid
|
||||
* Makefile: new module ic35frec.{c,h}, ic35log replaces ic35prot.awk
|
||||
target "clean" also removes .depend file
|
||||
2000-11-29_21
|
||||
* syntrans.{c,h}: missed commit_frec() for import,sync (yet untested)
|
||||
2000-11-28_04
|
||||
* dataio.c: support last-modified-time for vCard,vCalendar
|
||||
concatenate IC35 file-id and record-id for XPilotIdProp
|
||||
export ic35_dtime() for use in syntrans.c:set_date_time()
|
||||
* syntrans.c: do disconnect on welcome() error to avoid hang IC35
|
||||
* syntrans.{c,h}: functions for import,sync (untested): set_date_time,
|
||||
category, get_mod_flen, read_mod_frec, write_frec, delete_frec
|
||||
* synproto.{c,h}: import,sync commands: CMD{fdelrec,fgetmlen,fgetmrec}
|
||||
2000-11-27_15
|
||||
* ic35sync.txt: record-id, file-id, get number of modified records
|
||||
new commands: read next modified record, delete record
|
||||
updated correspondance with IC35Comm.dll to current knowledge
|
||||
comment logs Delete.tar.gz:*.log, how M.Bruennert made them
|
||||
* ic35log.sh: replaces ic35prot.awk, ic35prot2.awk
|
||||
ic35prot.awk,ic35prot2.awk: moved to Attic/
|
||||
2000-11-27_01
|
||||
* ic35prot.awk: err.corr prxdata(), _plen was undefined if skip < 3
|
||||
2000-11-25_18
|
||||
* ic35prot2.awk: cosmetics, comment IC35Comm.dll functions
|
||||
2000-11-25_03
|
||||
* ic35prot2.awk: decode record field contents, comment variables
|
||||
2000-11-24_04
|
||||
* ic35prot.awk: prepend data with WRx,RDx (hex) WRa,RDa (ASCII)
|
||||
skip also checksum if Level-1 headers are skipped with "-vskip=3"
|
||||
* ic35prot2.awk: decode IC35sync PDUs from WRx,RDx transmission logs
|
||||
from 'portmon' processed with 'awk -f ic35prot.awk -vskip=3'
|
||||
|
||||
2000-11-22_08 IC35SYNC-1-10
|
||||
* ic35sync supports output IC35 PIM data in vCard,vCalendar format
|
||||
new option "-f format" and command,pimfile args replace "-o outfile"
|
||||
write date+time to logfile
|
||||
* restrictions of implemented vCard,vCalendar output:
|
||||
- strings with non-printable chars get "QUOTED-PRINTABLE" property
|
||||
uncertain if it should be "ENCODING=QUOTED-PRINTABLE"
|
||||
- strings with 8bit-chars also get "CHARSET=ISO-8859-1" property
|
||||
uncertain if this is compliant to standard, because vobject.h
|
||||
does not contain "CHARSET", but both "vCard Version 2.1" and
|
||||
"vCalendar Version 1.0" explicitely allow "Character Set"
|
||||
- IC35 "Memo" has no standard vCard,vCalendar format representation
|
||||
using proprietary extension of VMEMO records
|
||||
* vcc.y,vobject.{c,h}: extended by non-standard "VMEMO" records
|
||||
for IC35 "Memo" representation
|
||||
* dataio.c: VEVENT recurrence rules and alarms
|
||||
* ic35sync.txt: corrected LED-,Beep-alarmflags
|
||||
2000-11-21_04
|
||||
* moved IC35 file descriptions from syntrans.* to dataio.*
|
||||
to avoid vcaconv link needing syntrans.o,synproto.o etc.
|
||||
* dataio.c: put_record() supports output vCard,vCalendar output
|
||||
2000-11-20_02
|
||||
* added vCard,vCalendar API: vcc.h vcc.y vobject.h vobject.c port.h
|
||||
from gnome-pim-1.2.0.tar.gz:gnome-pim-1.2.0/libversit/
|
||||
see ftp://ftp.gnome.org/pub/GNOME/stable/sources/gnome-pim/
|
||||
other sources for vCard,vCalendar API:
|
||||
- kpilot_3.1.10-1.0.tar.gz (based on KPilot 3.1b9)
|
||||
from ftp://kde.tdyc.com/pub/kde/debian/dists/potato/contrib/source/
|
||||
see also http://www.slac.com/pilone/kpilot_home/index.html
|
||||
- versit consortium' SDK for Windows DLLs
|
||||
from http://www.imc.org/pdi/sdkdllsr.zip
|
||||
* new vcaconv.c vCard,vCalendar conversions, e.g. for offline tests
|
||||
with IC35 binary data
|
||||
* restrictions of implemented vCard,vCalendar output:
|
||||
- sometimes non-7bit-ASCII chars lack QuotedPrintable and CharSet
|
||||
- VEVENT recurrence rules not implemented
|
||||
- VEVENT alarms AALARM,DALARM not implemented
|
||||
- IC35 "Memo" has no standard vCard,vCalendar format representation
|
||||
2000-11-19_07
|
||||
* Makefile: ask before overwrite distribution tar.gz
|
||||
* ic35sync.c: write date+time to logfile; replaced "-o outfile"
|
||||
with new option "-f format" and command,pimfile arguments
|
||||
* syntrans.c: reset serial device on abort with Ctrl-C
|
||||
* comio.c: correct comrecv(): fdsets undefined if select() returns -1
|
||||
* avoid gcc warnings about rcsid[]s not used
|
||||
|
||||
2000-11-19_00 IC35SYNC-1-9
|
||||
added README, ic35sync.txt,ic35mgr.txt, ic35prot.awk
|
||||
* Makefile: integrated help, target for tar.gz distribution
|
||||
* syntrans.{c,h},ic35sync.c: export connect(), details internal
|
||||
abort on bad power and wrong password responses
|
||||
check for ready-reponse '\x80' from IC35
|
||||
* ic35sync.c: write ic35sync version/rcsid to logfile
|
||||
* util.{c,h}: log_init() interface changed (loglevel argument)
|
||||
* ic35sync.txt: mention logfiles used for protocol analysis
|
||||
|
||||
2000-11-07_03 IC35SYNC-1-8
|
||||
ic35sync.c split into modules
|
||||
|
||||
2000-11-05_05 IC35SYNC-1-7
|
||||
version 1.7 released to Michael Bruennert
|
||||
read PIM data from IC35 tested OK
|
||||
CAVEAT:
|
||||
- PIM data export in "home grown" format not compatible to anything
|
||||
- cannot write PIM data to IC35, neither synchronize
|
||||
- unsupported commands "set date+time", "category", "reset chgflag"
|
||||
- ugly one-module-source
|
||||
2000-11-04_19 ic35sync.c 1.1
|
||||
hacking finished, now for compile and tests ..
|
||||
2000-10-31
|
||||
start hacking code
|
|
@ -0,0 +1,368 @@
|
|||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. This file is offered as-is,
|
||||
without warranty of any kind.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell command './configure && make && make install'
|
||||
should configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the 'README' file for
|
||||
instructions specific to this package. Some packages provide this
|
||||
'INSTALL' file but do not implement all of the features documented
|
||||
below. The lack of an optional feature in a given package is not
|
||||
necessarily a bug. More recommendations for GNU packages can be found
|
||||
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||
|
||||
The 'configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a 'Makefile' in each directory of the package.
|
||||
It may also create one or more '.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script 'config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file 'config.log' containing compiler output (useful mainly for
|
||||
debugging 'configure').
|
||||
|
||||
It can also use an optional file (typically called 'config.cache' and
|
||||
enabled with '--cache-file=config.cache' or simply '-C') that saves the
|
||||
results of its tests to speed up reconfiguring. Caching is disabled by
|
||||
default to prevent problems with accidental use of stale cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how 'configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the 'README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point 'config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file 'configure.ac' (or 'configure.in') is used to create
|
||||
'configure' by a program called 'autoconf'. You need 'configure.ac' if
|
||||
you want to change it or regenerate 'configure' using a newer version of
|
||||
'autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. 'cd' to the directory containing the package's source code and type
|
||||
'./configure' to configure the package for your system.
|
||||
|
||||
Running 'configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type 'make' to compile the package.
|
||||
|
||||
3. Optionally, type 'make check' to run any self-tests that come with
|
||||
the package, generally using the just-built uninstalled binaries.
|
||||
|
||||
4. Type 'make install' to install the programs and any data files and
|
||||
documentation. When installing into a prefix owned by root, it is
|
||||
recommended that the package be configured and built as a regular
|
||||
user, and only the 'make install' phase executed with root
|
||||
privileges.
|
||||
|
||||
5. Optionally, type 'make installcheck' to repeat any self-tests, but
|
||||
this time using the binaries in their final installed location.
|
||||
This target does not install anything. Running this target as a
|
||||
regular user, particularly if the prior 'make install' required
|
||||
root privileges, verifies that the installation completed
|
||||
correctly.
|
||||
|
||||
6. You can remove the program binaries and object files from the
|
||||
source code directory by typing 'make clean'. To also remove the
|
||||
files that 'configure' created (so you can compile the package for
|
||||
a different kind of computer), type 'make distclean'. There is
|
||||
also a 'make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
7. Often, you can also type 'make uninstall' to remove the installed
|
||||
files again. In practice, not all packages have tested that
|
||||
uninstallation works correctly, even though it is required by the
|
||||
GNU Coding Standards.
|
||||
|
||||
8. Some packages, particularly those that use Automake, provide 'make
|
||||
distcheck', which can by used by developers to test that all other
|
||||
targets like 'make install' and 'make uninstall' work correctly.
|
||||
This target is generally not run by end users.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the 'configure' script does not know about. Run './configure --help'
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give 'configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here is
|
||||
an example:
|
||||
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you can use GNU 'make'. 'cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the 'configure' script. 'configure' automatically checks for the source
|
||||
code in the directory that 'configure' is in and in '..'. This is known
|
||||
as a "VPATH" build.
|
||||
|
||||
With a non-GNU 'make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use 'make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
On MacOS X 10.5 and later systems, you can create libraries and
|
||||
executables that work on multiple system types--known as "fat" or
|
||||
"universal" binaries--by specifying multiple '-arch' options to the
|
||||
compiler but only a single '-arch' option to the preprocessor. Like
|
||||
this:
|
||||
|
||||
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CPP="gcc -E" CXXCPP="g++ -E"
|
||||
|
||||
This is not guaranteed to produce working output in all cases, you
|
||||
may have to build one architecture at a time and combine the results
|
||||
using the 'lipo' tool if you have problems.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, 'make install' installs the package's commands under
|
||||
'/usr/local/bin', include files under '/usr/local/include', etc. You
|
||||
can specify an installation prefix other than '/usr/local' by giving
|
||||
'configure' the option '--prefix=PREFIX', where PREFIX must be an
|
||||
absolute file name.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like '--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run 'configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them. In general, the default
|
||||
for these options is expressed in terms of '${prefix}', so that
|
||||
specifying just '--prefix' will affect all of the other directory
|
||||
specifications that were not explicitly provided.
|
||||
|
||||
The most portable way to affect installation locations is to pass the
|
||||
correct locations to 'configure'; however, many packages provide one or
|
||||
both of the following shortcuts of passing variable assignments to the
|
||||
'make install' command line to change installation locations without
|
||||
having to reconfigure or recompile.
|
||||
|
||||
The first method involves providing an override variable for each
|
||||
affected directory. For example, 'make install
|
||||
prefix=/alternate/directory' will choose an alternate location for all
|
||||
directory configuration variables that were expressed in terms of
|
||||
'${prefix}'. Any directories that were specified during 'configure',
|
||||
but not in terms of '${prefix}', must each be overridden at install time
|
||||
for the entire installation to be relocated. The approach of makefile
|
||||
variable overrides for each directory variable is required by the GNU
|
||||
Coding Standards, and ideally causes no recompilation. However, some
|
||||
platforms have known limitations with the semantics of shared libraries
|
||||
that end up requiring recompilation when using this method, particularly
|
||||
noticeable in packages that use GNU Libtool.
|
||||
|
||||
The second method involves providing the 'DESTDIR' variable. For
|
||||
example, 'make install DESTDIR=/alternate/directory' will prepend
|
||||
'/alternate/directory' before all installation names. The approach of
|
||||
'DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||
does not work on platforms that have drive letters. On the other hand,
|
||||
it does better at avoiding recompilation issues, and works well even
|
||||
when some directory options were not specified in terms of '${prefix}'
|
||||
at 'configure' time.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving 'configure' the
|
||||
option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
|
||||
|
||||
Some packages pay attention to '--enable-FEATURE' options to
|
||||
'configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to '--with-PACKAGE' options, where PACKAGE
|
||||
is something like 'gnu-as' or 'x' (for the X Window System). The
|
||||
'README' should mention any '--enable-' and '--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, 'configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the 'configure' options '--x-includes=DIR' and
|
||||
'--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Some packages offer the ability to configure how verbose the
|
||||
execution of 'make' will be. For these packages, running './configure
|
||||
--enable-silent-rules' sets the default to minimal output, which can be
|
||||
overridden with 'make V=1'; while running './configure
|
||||
--disable-silent-rules' sets the default to verbose, which can be
|
||||
overridden with 'make V=0'.
|
||||
|
||||
Particular systems
|
||||
==================
|
||||
|
||||
On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC
|
||||
is not installed, it is recommended to use the following options in
|
||||
order to use an ANSI C compiler:
|
||||
|
||||
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||
|
||||
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||
|
||||
HP-UX 'make' updates targets which have the same time stamps as their
|
||||
prerequisites, which makes it generally unusable when shipped generated
|
||||
files such as 'configure' are involved. Use GNU 'make' instead.
|
||||
|
||||
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||
parse its '<wchar.h>' header file. The option '-nodtk' can be used as a
|
||||
workaround. If GNU CC is not installed, it is therefore recommended to
|
||||
try
|
||||
|
||||
./configure CC="cc"
|
||||
|
||||
and if that doesn't work, try
|
||||
|
||||
./configure CC="cc -nodtk"
|
||||
|
||||
On Solaris, don't put '/usr/ucb' early in your 'PATH'. This
|
||||
directory contains several dysfunctional programs; working variants of
|
||||
these programs are available in '/usr/bin'. So, if you need '/usr/ucb'
|
||||
in your 'PATH', put it _after_ '/usr/bin'.
|
||||
|
||||
On Haiku, software installed for all users goes in '/boot/common',
|
||||
not '/usr/local'. It is recommended to use the following options:
|
||||
|
||||
./configure --prefix=/boot/common
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features 'configure' cannot figure out
|
||||
automatically, but needs to determine by the type of machine the package
|
||||
will run on. Usually, assuming the package is built to be run on the
|
||||
_same_ architectures, 'configure' can figure that out, but if it prints
|
||||
a message saying it cannot guess the machine type, give it the
|
||||
'--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as 'sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS
|
||||
KERNEL-OS
|
||||
|
||||
See the file 'config.sub' for the possible values of each field. If
|
||||
'config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option '--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with '--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for 'configure' scripts to share,
|
||||
you can create a site shell script called 'config.site' that gives
|
||||
default values for variables like 'CC', 'cache_file', and 'prefix'.
|
||||
'configure' looks for 'PREFIX/share/config.site' if it exists, then
|
||||
'PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
'CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all 'configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to 'configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the 'configure' command line, using 'VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified 'gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
|
||||
Autoconf limitation. Until the limitation is lifted, you can use this
|
||||
workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
'configure' Invocation
|
||||
======================
|
||||
|
||||
'configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
'--help'
|
||||
'-h'
|
||||
Print a summary of all of the options to 'configure', and exit.
|
||||
|
||||
'--help=short'
|
||||
'--help=recursive'
|
||||
Print a summary of the options unique to this package's
|
||||
'configure', and exit. The 'short' variant lists options used only
|
||||
in the top level, while the 'recursive' variant lists options also
|
||||
present in any nested packages.
|
||||
|
||||
'--version'
|
||||
'-V'
|
||||
Print the version of Autoconf used to generate the 'configure'
|
||||
script, and exit.
|
||||
|
||||
'--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally 'config.cache'. FILE defaults to '/dev/null' to
|
||||
disable caching.
|
||||
|
||||
'--config-cache'
|
||||
'-C'
|
||||
Alias for '--cache-file=config.cache'.
|
||||
|
||||
'--quiet'
|
||||
'--silent'
|
||||
'-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to '/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
'--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
'configure' can determine that directory automatically.
|
||||
|
||||
'--prefix=DIR'
|
||||
Use DIR as the installation prefix. *note Installation Names:: for
|
||||
more details, including other options available for fine-tuning the
|
||||
installation locations.
|
||||
|
||||
'--no-create'
|
||||
'-n'
|
||||
Run the configure checks, but stop before creating any output
|
||||
files.
|
||||
|
||||
'configure' also accepts some other, not widely useful, options. Run
|
||||
'configure --help' for more details.
|
|
@ -0,0 +1,21 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
## $Id: Makefile.am,v 1.4 2001/08/12 03:29:57 thosch Rel $
|
||||
## Copyright (C) 2001 Thomas Schulz
|
||||
##
|
||||
## automakefile for ic35link
|
||||
|
||||
pkgdata_DATA = \
|
||||
README \
|
||||
COPYING
|
||||
|
||||
EXTRA_DIST = $(pkgdata_DATA)
|
||||
|
||||
SUBDIRS = doc src
|
||||
|
||||
if MAINTAINER_MODE
|
||||
MAINTAINERCLEANFILES = \
|
||||
aclocal.m4 install-sh missing mkinstalldirs INSTALL \
|
||||
Makefile.in stamp-h.in config.h.in configure
|
||||
else
|
||||
MAINTAINERCLEANFILES =
|
||||
endif
|
|
@ -0,0 +1,248 @@
|
|||
$Id: NEWS,v 1.18 2001/08/12 03:39:35 thosch Rel $
|
||||
NEWS: release info about IC35Link
|
||||
=================================
|
||||
|
||||
2001-08-12 version 1.18 IC35LINK-1-18
|
||||
long pending release with several improvements and corrections
|
||||
according to suggestions and bug reports by users.
|
||||
improvements:
|
||||
- improved README: table of contents, restrictions, more explanations
|
||||
- ic35mgr restore and MMC write 30% faster (proposal by Harald Becker)
|
||||
- ic35sync, ic35mgr, vcaconv now support long options, e.g. "--help"
|
||||
info enquiry with "--help" or "--version" now returns exitcode 0
|
||||
- new autogen.sh script for generate configure etc. after CVS checkout
|
||||
(thanks Konrad Mader for report about missing configure in CVS)
|
||||
- new configure option "--disable-logandcomsim" for conditional compile
|
||||
without logging and com-simulation (proposal by Harald Becker)
|
||||
- new configure options "--enable-ansi" and "--enable-pedantic"
|
||||
bugfixes:
|
||||
- fixed problem where ic35sync with many (ca. 860) addresses failed
|
||||
(thanks Konrad Mader for bug report "get_mod_flen failed")
|
||||
- ic35sync now accepts also empty PIMfile(s), e.g. empty ic35.memo
|
||||
(thanks Malte Schmidt for bug report "ic35.memo: parse error")
|
||||
- ic35mgr MMCard functions now check ic35path before accessing IC35
|
||||
e.g. warn if shell eat backslash (\) in unquoted MMCard1\test.txt
|
||||
(thanks Thomas Lichtenberg for bug report)
|
||||
- restricted ic35mgr to max.blocksize 16350 found by experiments
|
||||
- ic35sync, ic35mgr now abort on open failure of logfile or simfile
|
||||
- fixed com-simulation for adjacent "RD nn" lines and non-logged bytes
|
||||
- fixed compile problem util.c with Linux Mandrake-8.0 and SuSE-7.2
|
||||
(thanks Christian Theile, Karl Stroetmann for bug reports)
|
||||
- corrected warnings from "--enable-ansi" and "--missing-prototypes"
|
||||
- fixed all Makefile.am: maintainer-clean keeps only sources in CVS,
|
||||
install also README and COPYING, clean dependencies and versinfo.c
|
||||
|
||||
2001-02-05 version 1.17 IC35LINK-1-17
|
||||
package renamed to "ic35link" and automake/autoconf/CVS reorganization.
|
||||
no changes in sources, programs are unchanged except for version.
|
||||
sources,documents now reside in src,doc subdirectories respectively.
|
||||
|
||||
2001-02-04 version 1.16 IC35SYNC-1-16
|
||||
this is a bugfix and redesign release and is the last named "ic35sync".
|
||||
(the package will be renamed to "ic35link" in the next release, when
|
||||
the reorganizations for automake/autoconf and public CVS are done.)
|
||||
improvements and redesign:
|
||||
- ic35sync,ic35mgr,vcaconv now report package version and build info
|
||||
- distribution includes vcc.c to handle missing/bad 'bison' or 'yacc'
|
||||
(e.g. SuSE-7.0's yacc produced bad vcc.o, thanks Michael Bruennert)
|
||||
- reworked and clearified the IC35 manager protocol documentation and
|
||||
implementation (see ic35mgr.txt, mgrtrans.*, mgrproto.*), refer to
|
||||
the IC35 SoftwareDevelopmentKit API MMCard functions in mgrproto.c
|
||||
bugfixes in ic35mgr and ic35sync:
|
||||
- fixed compile error RedHat-7.0 gcc-2.96 (thanks Dieter Schultschik)
|
||||
- corrections for 'ic35mgr status' (thanks Michael Bruennert):
|
||||
mgrtrans.c:status() tries to get IC35 response instead of only wait
|
||||
mgrproto.c:MMCsend() sends blocklength with initial wait
|
||||
corrected output of MMCard2 label
|
||||
- ic35mgr commands backup and restore show error messages on new line
|
||||
- avoid failing 'ic35mgr restore ..' at "disconnect" by delay 3.25 sec
|
||||
after writedatabase() done
|
||||
- avoid failure of 'ic35mgr mmcput file' with occasional slow IC35
|
||||
MMCard write with 3.5 sec timeout for length of response block
|
||||
- corrected MMC closedir,closefile response PDUs having no status-word
|
||||
- corrected to make 'ic35sync status' work also with simulation file
|
||||
|
||||
2001-01-20 version 1.15 IC35SYNC-1-15
|
||||
new IC35 manager 'ic35mgr' supports access of IC35 MMCard(s)
|
||||
- command "mmcdir" lists contents of MMCard(s)
|
||||
- commands "mmcget","mmcput","mmcdel" read,write,delete MMCard file
|
||||
- commands "backup","restore" IC35 organizer database
|
||||
- ic35mgr.txt now really describes the IC35 manager protocol
|
||||
(previously it was just extracts of Windows 'portmon' logfiles)
|
||||
bugfixes in ic35sync and vcaconv:
|
||||
- "ic35sync sync" now updates record if on IC35, else writes new record
|
||||
- "vcaconv sortvca ic35.vcal" did produce empty output, fixed vobject.c
|
||||
- fixed vcc.y compile warnings
|
||||
- "vcaconv sortvca .." improved: shows properties in sort order sequence
|
||||
todo:
|
||||
- ic35mgr install application on IC35
|
||||
- ic35sync initial sync does not yet write all records to IC35
|
||||
workaround: do "ic35sync import .." before first "ic35sync sync .."
|
||||
|
||||
2000-12-28 version 1.14 IC35SYNC-1-14
|
||||
ic35sync import,sync step-5 done: "sync" command, misc. improvements
|
||||
- sync command for synchronize vCard,vCalendar format PIMdata with IC35
|
||||
- corrected convert of PIM BDAY birthday to IC35 for yyyy-mm-dd format
|
||||
- PIM multiple CATEGORIES now preserved by prepend category from IC35,
|
||||
single or standard of multiple CATEGORIES are replaced
|
||||
- PIM fullname FN now preserved, IC35 updates first,last name into it
|
||||
- put first 2 EMAIL entries from vCard into IC35 address Email1,Email2
|
||||
- put unspecific telno to IC35 TelWork for "Business", else to TelHome
|
||||
- map IC35 address "(def.)"s in VCARD.NOTE marked "(def1):","(def2):"
|
||||
- conversion IC35 to/from PIM record does now yet delete record fields
|
||||
- extracted data formats from dataio.c into separate modules:
|
||||
datatxt.c text format (output only)
|
||||
databin.c binary IC35 record format
|
||||
datavca.c vCard,vCalendar format
|
||||
vcutil.c vCard,vCalendar utilities
|
||||
vcutil.h header for vCard,vCalendar utilities
|
||||
fixes for gnomecard from gnome-pim_1.2.0:
|
||||
- compare VCARD.REV against old reference date+time from IC35, because
|
||||
gnomecard does not maintain X-PILOTSTAT.
|
||||
- write VCARD.REV:yyyy-mm-ddThh:mm:ss, because yyyymmddThhmmss was
|
||||
ignored by gnomecard.
|
||||
fixes for gnomecal from gnome-pim_1.2.0:
|
||||
- first line of VEVENT.SUMMARY to/from IC35 Summary, remaining lines
|
||||
to/from Notes, because gnomecal does not support VEVENT.DESCRIPTION
|
||||
- keep unsupported property VTODO.DSTART marked in VTODO.DESCRIPTION
|
||||
- add VEVENT,VTODO.CLASS:PUBLIC, else gnomecal would crash on edit
|
||||
fixes for korganizer v1.1.1:
|
||||
- put UID:IC35id-xxxxxxxx to vCard,vCalender record if no UID there.
|
||||
- produce output vCard,vCal in same CRLF/NL-mode as found on input,
|
||||
as korganizer has NL-terminated lines in vCalendar.
|
||||
- translate IC35 CRLF to/from PIM NL in NOTE and DESCRIPTION fields.
|
||||
- keep unsupported properties VTODO.DSTART,DUE,CATEGORIES as marked
|
||||
lines in VTODO.DESCRIPTION
|
||||
- korganizer supports only DALARM, map IC35 LED and Beep to/from it
|
||||
vcaconv extensions:
|
||||
- command "prvca" reports vCard/vCalendar parse error.
|
||||
- command "sortvca" outputs sorted vCard,vCalendar to standard output.
|
||||
- command "imphandy" appends vCards with category HANDY from vCard file
|
||||
to standard output, after import the result back into IC35 they are
|
||||
for upload to a mobile phone from IC35 addresses in category HANDY.
|
||||
CAVEAT:
|
||||
- no options for sync conflict resolve, PIMfile always overrides IC35!
|
||||
- IC35 has no different times for LED,Beep alarm, DALARM takes priority
|
||||
- vcaconv conversions do not transfer clean/modified record status
|
||||
- memory leak in vobject.c: all setVObject_*_Value() do not free the
|
||||
previously attached dupStr()-allocated string value
|
||||
|
||||
2000-12-17 version 1.13 IC35SYNC-1-13 (not released to public)
|
||||
ic35sync import,sync step-4 done: "import" command, misc. improvements
|
||||
- algorithm details described in ic35sync.c:ic35import(),ic35export()
|
||||
- import command for vCard,vCalendar or binary format PIMdata into IC35
|
||||
- status command (new) shows IC35 version, sysinfo, total,mod records
|
||||
- export command improved:
|
||||
export into existing PIMfile(s), backup e.g. ic35vcal to ic35.vcal~
|
||||
map IC35 address fields "(def.)" to/from VCARD:NOTE marked lines
|
||||
change vCard,vCalendar record modified time only if record changed
|
||||
support DCREATED in vCalendar: creation time of VEVENT,VTODO record
|
||||
corrected VEVENT:AALARM,DLARM, were sometimes wrongly created
|
||||
- support X-PILOTSTAT in vCard,vCal: 0=same, other=changed vs. IC35
|
||||
- default format changed to "vca" for primary use vCard,vCalendar
|
||||
- vcaconv may be used as filter with input/output from stdin/stdout
|
||||
- fixed QUOTED-PRINTABLE problem with multi-field properties (like
|
||||
VCARD:N, VCARD:ADR): due to problem with parser vcc.y and for
|
||||
compatibility with other programs using the vCard,vCal output
|
||||
QUOTED-PRINTABLE is not used on multi-field properties.
|
||||
(otherwise the split into field sub-properties fails and the
|
||||
first field (e.g. VCARD:ADR:STREET) gets the string of ALL the
|
||||
fields (e.g. STREET,CITY,etc.) with ";" within it.)
|
||||
todo: sync command, fix memory leak in vobject.c
|
||||
conversion IC35 to/from PIM record does not yet delete record fields,
|
||||
i.e. record on destination may differ and have fields not in source.
|
||||
may be delete field needed only for sync, because import/export are
|
||||
specified to not delete on destination.
|
||||
|
||||
2000-12-07 version 1.12 IC35SYNC-1-12 (not released to public)
|
||||
ic35sync import,sync step-3 done:
|
||||
convert vCard,vCalendar format to IC35 record
|
||||
ic35sync import,sync step-2 done:
|
||||
new protocol functions for import,sync tested OK
|
||||
new knowledge about import,sync from experiments
|
||||
new features:
|
||||
- vcaconv supports "vca2bin", new "bin2txt" conversions
|
||||
- ic35log.sh supports new commands readrecrid,updatrec
|
||||
processes ic35sync logfiles, fragmented response readmodrec
|
||||
- syntrans.{c,h}: connect() argument rdtime to retrieve value from IC35
|
||||
corrections:
|
||||
- corrected ic35addr_to_vcard(): set VCAdrProp if have any address field
|
||||
- vcaconv.c,dataio.c: handle binfile records without data
|
||||
- synproto.c: corrected CMDfgetmlen, CMDcategory, CMDsetdtime
|
||||
documentation ic35sync.txt:
|
||||
- marked uncertain topics with "???"
|
||||
- experiments found new commands: read record by record-ID (01 05) and
|
||||
write record data update (01 09), keeps recID on IC35 unchanged
|
||||
- new knowledge about open file, changeflag, write record
|
||||
first all read then write,del,commit, "date+time" may be any string
|
||||
todo: ic35sync commands import,sync
|
||||
|
||||
2000-12-01 version 1.11 IC35SYNC-1-11 (not released to public)
|
||||
intermediate freeze after ic35sync import,sync step-1 done:
|
||||
- new functions: set_date_time, category, get_mod_flen, read_mod_frec,
|
||||
write_frec, delete_frec, commit_frec
|
||||
- IC35 record access functions ic35frec.{c,h}
|
||||
- 4byte record-ID combined from file-id (MSB) and record-id (LSW)
|
||||
- support last-modified-time for vCard,vCalendar
|
||||
- protocol-analyser ic35log.sh replaces and extends ic35prot.awk
|
||||
todo: test new funcs, vCard,vCal to IC35 record, commands import,sync
|
||||
|
||||
2000-11-22 version 1.10 IC35SYNC-1-10
|
||||
- ic35sync supports output IC35 PIM data in vCard,vCalendar format
|
||||
new option "-f format" and command,pimfile args replace "-o outfile"
|
||||
write date+time to logfile
|
||||
- added vCard,vCalendar API: vcc.h vcc.y vobject.h vobject.c port.h
|
||||
from gnome-pim-1.2.0.tar.gz:gnome-pim-1.2.0/libversit/
|
||||
see ftp://ftp.gnome.org/pub/GNOME/stable/sources/gnome-pim/
|
||||
other sources for vCard,vCalendar API:
|
||||
- kpilot_3.1.10-1.0.tar.gz (based on KPilot 3.1b9)
|
||||
from ftp://kde.tdyc.com/pub/kde/debian/dists/potato/contrib/source/
|
||||
see also http://www.slac.com/pilone/kpilot_home/index.html
|
||||
- versit consortium' SDK for Windows DLLs
|
||||
from http://www.imc.org/pdi/sdkdllsr.zip
|
||||
- restrictions of implemented vCard,vCalendar output:
|
||||
- strings with non-printable chars get "QUOTED-PRINTABLE" property
|
||||
uncertain if it should be "ENCODING=QUOTED-PRINTABLE"
|
||||
- strings with 8bit-chars also get "CHARSET=ISO-8859-1" property
|
||||
uncertain if this is compliant to standard, because vobject.h
|
||||
does not contain "CHARSET", but both "vCard Version 2.1" and
|
||||
"vCalendar Version 1.0" explicitely allow "Character Set"
|
||||
- IC35 "Memo" has no standard vCard,vCalendar format representation
|
||||
using proprietary extension of VMEMO records
|
||||
- new vcaconv: vCard,vCalendar conversions, e.g. for offline tests
|
||||
with IC35 binary data
|
||||
moved IC35 file descriptions from syntrans.* to dataio.*
|
||||
to avoid vcaconv link needing syntrans.o,synproto.o etc.
|
||||
- ic35sync.txt: corrected LED-,Beep-alarmflags
|
||||
- Makefile: ask before overwrite distribution tar.gz
|
||||
- syntrans.c: reset serial device on abort with Ctrl-C
|
||||
- comio.c: correct comrecv(): fdsets undefined if select() returns -1
|
||||
- avoid gcc warnings about rcsid[]s not used
|
||||
|
||||
2000-11-19 version 1.9 IC35SYNC-1-9 (not released to public)
|
||||
- added README, ic35sync.txt,ic35mgr.txt, ic35prot.awk
|
||||
- Makefile: integrated help, target for tar.gz distribution
|
||||
- syntrans.{c,h},ic35sync.c: export connect(), details internal
|
||||
abort on bad power and wrong password responses
|
||||
check for ready-reponse '\x80' from IC35
|
||||
- ic35sync.c: write ic35sync version/rcsid to logfile
|
||||
- util.{c,h}: log_init() interface changed (loglevel argument)
|
||||
- ic35sync.txt: mention logfiles used for protocol analysis
|
||||
|
||||
2000-11-07 version 1.8 IC35SYNC-1-8 (not released to public)
|
||||
ic35sync.c split into modules
|
||||
|
||||
2000-11-05 version 1.7 IC35SYNC-1-7
|
||||
first usable version, read PIM data from IC35 tested OK.
|
||||
CAVEAT:
|
||||
- PIM data export in "home grown" format not compatible to anything
|
||||
- cannot write PIM data to IC35, neither synchronize
|
||||
- unsupported commands "set date+time", "category", "reset chgflag"
|
||||
- ugly one-module-source
|
||||
|
||||
2000-11-04 version 1.1
|
||||
hacking finished, now for compile and tests ..
|
||||
|
||||
2000-10-31
|
||||
start hacking code
|
||||
|
|
@ -0,0 +1,417 @@
|
|||
$Id: README,v 1.19 2001/08/12 03:36:44 thosch Rel $
|
||||
IC35Link for Linux
|
||||
==================
|
||||
|
||||
IC35Link provides tools to communicate with the Siemens IC35
|
||||
over a serial port.
|
||||
|
||||
Contents
|
||||
Abstract
|
||||
Installation
|
||||
configure, make, install
|
||||
create configure script
|
||||
Usage of ic35sync
|
||||
Examples
|
||||
Restrictions
|
||||
Usage of ic35mgr
|
||||
Restrictions
|
||||
Files in the distribution
|
||||
Documents
|
||||
Miscellaneous
|
||||
Tools
|
||||
Sources in the src directory
|
||||
References
|
||||
Standard Disclaimer, Warnings, Copyright
|
||||
|
||||
Abstract
|
||||
--------
|
||||
The tools included in the IC35Link package are:
|
||||
- ic35sync
|
||||
synchronizes IC35 address, schedule, todo and memo data with
|
||||
Personal Information Management databases (PIMfiles).
|
||||
- ic35mgr
|
||||
The IC35 manager is for accessing IC35 MMCard(s), backup,restore
|
||||
the IC35 PIM-database and install applications on the IC35.
|
||||
CAVEAT: install applications on the IC35 is (as of version 1.17)
|
||||
not yet implemented.
|
||||
- vcaconv
|
||||
is a converter for PIMfiles in vCard,vCalendar and binary formats.
|
||||
it was mainly used during development. For non-developers the
|
||||
"imphandy" conversion might be useful to manage the phonebook of
|
||||
a mobile phone with the IC35: it converts vCards into the "HANDY"
|
||||
category for uploading them from this category on the IC35 to the
|
||||
phonebook of the mobile phone (after import or sync with IC35).
|
||||
- ic35log
|
||||
is for pretty-printing ic35sync, ic35mgr (and 'portmon') logfiles
|
||||
and useful mainly for developers.
|
||||
- ic35sync.txt
|
||||
describes the IC35 synchronization protocol (in german).
|
||||
- ic35mgr.txt
|
||||
describes the IC35 manager protocols (in german).
|
||||
All programs give help about usage if called with the short "-h" or
|
||||
the long "--help" option.
|
||||
|
||||
Starting with version 1.17 the package is named "ic35link", because
|
||||
it provides more than just IC35 synchronization under GNU/Linux.
|
||||
Up to version 1.16 the package name was "ic35sync".
|
||||
|
||||
Installation
|
||||
------------
|
||||
Unpack the archive ic35link-*.tar.gz (you appeareantly did that ;-).
|
||||
configure, make, install
|
||||
Do the usual
|
||||
./configure
|
||||
make
|
||||
su # superuser login for install
|
||||
make install-strip # strip symbols and debugging info
|
||||
exit # superuser logout
|
||||
Installation is done to /usr/local/bin and /usr/local/share/ic35link
|
||||
by default, change that with 'configure --prefix=/some/other/path'.
|
||||
For details run 'configure --help' and see the file INSTALL.
|
||||
The 'configure' options of major interest are:
|
||||
--prefix=/opt
|
||||
install to /opt/bin/ instead of default /usr/local/bin/
|
||||
--disable-logandcomsim
|
||||
compile without logging and simulated communication support
|
||||
--disable-warnings
|
||||
disable compile warnings
|
||||
--enable-ansi
|
||||
enable strict ANSI-C compilation
|
||||
--enable-pedantic
|
||||
enable pedantic compile warnings
|
||||
be warned to get several compile errors and/or warnings
|
||||
feel free to fix them (and send me the patches :-)
|
||||
* The programs are compiled with debugging info. Should you want
|
||||
to install them with that, use 'make install' instead of the
|
||||
'make install-strip' above.
|
||||
* The programs and documents can be uninstalled with 'make uninstall'.
|
||||
* If you modify the vCard/vCalendar parser source vcc.y, you will
|
||||
need 'bison' version 1.25 or newer. Compilation with 'yacc' will
|
||||
not work and/or create a vcc.c producing 'parser stack overflow'
|
||||
errors.
|
||||
create configure script
|
||||
If you use an archive ic35link-*.tar.gz you should not need this.
|
||||
If you obtained ic35link from the public CVS repository you have
|
||||
to generate the configure script and Makefile.in with
|
||||
sh autogen.sh
|
||||
It will check for autoconf and automake, you'll have to install
|
||||
these packages if some of the checks fail.
|
||||
If all goes well it will automatically run './configure' with the
|
||||
options passed to autogen.sh and "--enable-maintainer-mode". The
|
||||
latter enables 'make maintainer-clean', which deletes everything
|
||||
not in the CVS repository, e.g. also the configure script.
|
||||
Setting the environment variable NOCONFIGURE to some non-empty
|
||||
value will prevent autogen.sh from running configure.
|
||||
|
||||
|
||||
Usage of ic35sync
|
||||
-----------------
|
||||
ic35sync synchronizes IC35 address, schedule, todo and memo data
|
||||
with Personal Information Management databases (PIMfiles) mainly
|
||||
in vCard,vCalendar format. Get information about usage with:
|
||||
ic35sync --help
|
||||
ic35sync supports 4 modes of operation, given as command argument:
|
||||
- status
|
||||
reports IC35 status: firmware version, timestamp of last sync
|
||||
operation and total and modified number of records per IC35 file.
|
||||
No PIMfiles are accessed, contents of IC35 are not changed, thus
|
||||
good for an initial test.
|
||||
- export
|
||||
does export IC35 data to PIMfile(s), data in IC35 is not changed
|
||||
and no IC35 or PIM records will be deleted. The sychronisation
|
||||
stamp will not be written to IC35 and any changemarks on records
|
||||
in the IC35 remain intact.
|
||||
This is the initial operation to start using IC35 data also with
|
||||
Linux Personal Information Managers. It is also usable to backup
|
||||
all the IC35 data.
|
||||
Records from existing PIMfile(s) can afterwards be propagated to
|
||||
IC35 with an 'import' or 'sync' operation.
|
||||
- import
|
||||
does import data from PIMfile(s) into IC35, changes in PIMfile(s)
|
||||
reflect only the IC35 record numbers and status, no IC35 or PIM
|
||||
records will be deleted. The synchronisation stamp (current date
|
||||
and time) will be written to IC35 only if all IC35 records match
|
||||
with PIMfile, e.g. if the IC35 was empty before the import.
|
||||
This is the initial operation to start using Linux PIM databases
|
||||
also on IC35. it can be used also to restore data into IC35.
|
||||
Any records previously existing in IC35 can then be propagated
|
||||
into PIMfile(s) with an 'export' or 'sync' operation.
|
||||
- sync
|
||||
synchronizes changes in IC35 and PIMfile(s): records modified in
|
||||
IC35 will be updated to PIMfile(s), records deleted in IC35 will
|
||||
be deleted from PIMfile(s) and vice versa.
|
||||
If changes to the same record were made in both the IC35 and the
|
||||
PIMfile, the latter takes precedence, i.e. PIM overrides IC35.
|
||||
All record changemarks on IC35 will be cleared and the current
|
||||
date and time will be written to IC35 as synchronisation stamp,
|
||||
because after sync all IC35 records match with PIMfile(s).
|
||||
With the vCard/vCalendar format (default or option "--format vca")
|
||||
up to 3 PIMfile(s) can be specified on the ic35sync commandline:
|
||||
If 3 PIMfiles are specified, the first file is for Addresses, the
|
||||
second file is for Schedule and ToDo, the third file is for Memo.
|
||||
If 2 PIMfiles are specified, the first file is for Adresses and the
|
||||
second file for Schedule, ToDo and Memo. Korganizer and gnomecal
|
||||
will work with the second file only if there are not VMEMO-records
|
||||
in it, i.e. only if there is not any Memo note on the IC35!
|
||||
If 1 PIMfile is specified, this single file is used for all data
|
||||
from Adresses, Schedule, ToDo and Memo. Korganizer, gnomecal and
|
||||
and gnomecard cannot work with that single file!
|
||||
If no PIMfiles are specified, the default filenames are used, which
|
||||
are ic35.vcard for Adresses, ic35.vcal for Schedule and ToDo, and
|
||||
ic35.memo for Memo, the files are assumed in the current directory.
|
||||
|
||||
Examples
|
||||
* GNOME addressbook and calendar
|
||||
IC35 syncstation connected at /dev/ttyS1, IC35 password is "secret"
|
||||
initial export from IC35:
|
||||
ic35sync -d /dev/ttyS1 -p secret export \
|
||||
~/.gnome/GnomeCard.gcrd ~/.gnome/user-cal.vcf ic35.memo
|
||||
synchronize changes in IC35 and addressbook,calendar:
|
||||
ic35sync -d /dev/ttyS1 -p secret sync \
|
||||
~/.gnome/GnomeCard.gcrd ~/.gnome/user-cal.vcf ic35.memo
|
||||
* KDE KOrganizer and GNOME addressbook
|
||||
initial import into IC35 at /dev/ic35, no IC35 password:
|
||||
ic35sync import ~/.gnome/GnomeCard.gcrd \
|
||||
~/.kde/share/apps/korganizer/calendar.vcs ic35.memo
|
||||
synchronize changes in IC35 and addressbook,KOrganizer:
|
||||
ic35sync sync ~/.gnome/GnomeCard.gcrd \
|
||||
~/.kde/share/apps/korganizer/calendar.vcs ic35.memo
|
||||
|
||||
Restrictions
|
||||
* ic35sync yet has no options for resolving synchronize conflicts.
|
||||
If the same record is modified on both sides, the modification in
|
||||
the PIMfile takes precedence and overrides the changes on IC35.
|
||||
* ic35sync yet has a proprietary VMEMO format for memo records.
|
||||
The VMEMO format was invented by me following the vCard/vCalendar
|
||||
standard. Unfortunately there is no GUI software supporting it.
|
||||
Suggestions for the memo records are welcome.
|
||||
* ic35sync should be used with _existing_ vCalendar files, because
|
||||
Korganizer and gnomecal rely on their own file formats and do not
|
||||
work properly with vCalendar files _created_ by ic35sync.
|
||||
Korganizer uses newline characters as line separators and wants
|
||||
its own PRODID.
|
||||
gnomecal uses carriagereturn linefeed sequences as line separators
|
||||
and wants its own PRODID and VERSION.
|
||||
ic35sync does respect and not change the format of an existing
|
||||
vCalendar file to avoid confusing Korganizer/gnomecal.
|
||||
* ic35sync's sync operation is rather slow, because always all IC35
|
||||
records are read to find the records, which were deleted from the
|
||||
PIMfile(s). This is needed, as Korganizer, gnomecal and gnomecard
|
||||
leave no traces (e.g. delete-flags) from deleted records.
|
||||
* gnomecal does not support VEVENT.DESCRIPTION but multiple lines
|
||||
in VEVENT.SUMMARY.
|
||||
ic35sync maps the first line of VEVENT.SUMMARY to/from the IC35
|
||||
"Summary" field and all remaining lines to/from the IC35 "Notes"
|
||||
field.
|
||||
* gnomecal does not support VTODO.DTSTART.
|
||||
ic35sync maps the IC35 "Start" field to/from a line marked with
|
||||
"DTSTART:" in VTODO.DESCRIPTION.
|
||||
* gnomecard does not support the X-PILOTSTAT change mark.
|
||||
ic35sync regards VCARD records as changed if their with revised
|
||||
time VCARD.REV is newer than the date and time of the last sync.
|
||||
* korganizer does not support VTODO.CATEGORIES, VTODO.DTSTART and
|
||||
VTODO.DUE
|
||||
ic35sync maps the IC35 Category and the "Start" and "Due" fields
|
||||
to/from lines marked "CATEGORIES:", "DTSTART:" and "DUE:" in the
|
||||
VTODO.DESCRIPTION.
|
||||
* korganozer supports only VEVENT.DALARM, but not VEVENT.AALARM
|
||||
ic35sync maps IC35 "LED" and "Beep" alarms to/from VEVENT.DALARM.
|
||||
* the IC35 address fields "(Def.)" have no VCARD counterparts.
|
||||
ic35sync maps them to/from lines marked "(def1):" and "(def2):"
|
||||
in VCARD.NOTE.
|
||||
|
||||
|
||||
Usage of ic35mgr
|
||||
----------------
|
||||
The IC35 manager currently supports access of the IC35 MMCard(s)
|
||||
and backup,restore the IC35 internal PIM-database to/from a file.
|
||||
Get help about usage with
|
||||
ic35mgr --help
|
||||
and experiment (and please tell me about problems, suggestions and
|
||||
wanted features, e-mail address below).
|
||||
|
||||
Restrictions
|
||||
* The ic35mgr MMCard access commands mmcget,mmcput,mmcdel accept the
|
||||
filepath in the IC35 native form (e.g. MMcard1\IC35\APP\REVERSI.APP)
|
||||
or more convenient with lowercase characters and slash separators
|
||||
(e.g. mmcard1/ic35/app/reversi.app).
|
||||
The filepath argument in the IC35 native form must be enclosed in
|
||||
single (') or double (") quotes to prevent the shell from eating
|
||||
the backslash (\) characters.
|
||||
* Reading a MMCard file with mmcget will set the timestamp of the
|
||||
local file to that of the MMCard file.
|
||||
Even when only reading a MMCard file, the IC35 will set the MMCard
|
||||
file's timestamp to the current date and time.
|
||||
* Installing application programs on the IC35 is planned, but not yet
|
||||
implemented. If someone (from Siemens) would provide me with the
|
||||
specification of the installation protocol would ease this a lot.
|
||||
|
||||
|
||||
Files in the Distribution
|
||||
-------------------------
|
||||
Documents
|
||||
README
|
||||
sic! you're reading this
|
||||
NEWS
|
||||
release information about IC35Link
|
||||
ChangeLog
|
||||
sic! details about what was changed
|
||||
TODO
|
||||
sic! what remains to be done and whish list
|
||||
COPYING
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
AUTHORS
|
||||
who has written IC35Link
|
||||
THANKS
|
||||
who has contributed to IC35Link
|
||||
doc/ic35sync.txt
|
||||
description of IC35sync protocol, yet only (?) german
|
||||
doc/ic35mgr.txt
|
||||
description of IC35manager protocol, yet only (?) german
|
||||
|
||||
Miscellaneous
|
||||
INSTALL
|
||||
generic installation instructions for 'configure'
|
||||
autogen.sh
|
||||
generates configure and Makefile.in etc.
|
||||
config.h
|
||||
configuration header created by configure
|
||||
config.h.in
|
||||
input for configure to create config.h, created by autoheader
|
||||
configure
|
||||
configuration script, created by autoconf
|
||||
configure.in
|
||||
input for autoconf to create configure
|
||||
Makefile
|
||||
makes 'make' make it ;-) created by configure
|
||||
Makefile.in
|
||||
input for configure to create Makefile, created by automake
|
||||
Makefile.am
|
||||
input for automake to create Makefile.in
|
||||
|
||||
Tools
|
||||
src/ic35log.sh
|
||||
make logfiles of IC35 communications more readable. supported are
|
||||
logfiles created by "portmon" (from www.sysinternals.com) and the
|
||||
logfiles from ic35sync and ic35mgr (of course ;-).
|
||||
|
||||
Sources in the src directory
|
||||
ic35sync.c
|
||||
IC35 synchronize PersonalInformationManagement (PIM) data
|
||||
ic35mgr.c
|
||||
IC35 manager: access MMCard, backup,restore database
|
||||
dataio.c
|
||||
dataio.h
|
||||
PIM data import to / export from IC35 database records
|
||||
datatxt.c
|
||||
support for text output IC35 record
|
||||
databin.c
|
||||
support for binary IC35 record format (PIM)files
|
||||
datavca.c
|
||||
support for vCard,vCalendar format PIMfiles
|
||||
vcutil.h
|
||||
vcutil.c
|
||||
utilities for vCard,vCalendar
|
||||
ic35frec.h
|
||||
ic35frec.c
|
||||
IC35 record access and file descriptions
|
||||
syntrans.c
|
||||
syntrans.h
|
||||
IC35 synchronize transactions:
|
||||
connect, disconnect
|
||||
open, close, read, write IC35 database file
|
||||
synproto.c
|
||||
synproto.h
|
||||
IC35 synchronize protocol
|
||||
mgrtrans.c
|
||||
mgrtrans.h
|
||||
IC35 manager transactions:
|
||||
connect, disconnect
|
||||
MMCard status, directory, file access
|
||||
mgrproto.c
|
||||
mgrproto.h
|
||||
IC35 manager protocol
|
||||
genproto.c
|
||||
genproto.h
|
||||
general IC35 protocol support
|
||||
comio.c
|
||||
comio.h
|
||||
basic serial communication with IC35
|
||||
util.c
|
||||
util.h
|
||||
utilities: logging, errors, messages
|
||||
vcc.h
|
||||
export header for vCard,vCalendar API
|
||||
vcc.y
|
||||
parser for vCard-,vCalendar-files
|
||||
vobject.h
|
||||
vobject.c
|
||||
API for vCard,vCalendar VObject
|
||||
port.h
|
||||
compilation environment for vCard,vCalendar API
|
||||
vcaconv.c
|
||||
vCard,vCalendar conversion, e.g. to/from binary IC35 data
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
The vCard,vCalendar API sources were taken from gnome-pim-1.2.0,
|
||||
and fixed a bit to reduce compile warnings.
|
||||
Sources for vCard,vCalendar API:
|
||||
- Gnome-PIM gnome-pim-1.2.0.tar.gz
|
||||
from ftp://ftp.gnome.org/pub/GNOME/stable/sources/gnome-pim/
|
||||
- KPilot kpilot_3.1.10-1.0.tar.gz (based on KPilot 3.1b9)
|
||||
from ftp://kde.tdyc.com/pub/kde/debian/dists/potato/contrib/source/
|
||||
see also http://www.slac.com/pilone/kpilot_home/index.html
|
||||
- versit consortium's SDK for Windows DLLs
|
||||
from http://www.imc.org/pdi/sdkdllsr.zip
|
||||
The autogen.sh script was taken from gnome-pim-1.3.2 and fixed
|
||||
a bit to fit the needs of ic35link.
|
||||
|
||||
|
||||
Standard Disclaimer, Warnings, Copyright
|
||||
----------------------------------------
|
||||
THIS SOFTWARE HAS BUGS (as any software has ;-). Use it at your
|
||||
own risk. I take no responsibility for any data loss or damage,
|
||||
etc. done by this software, i.e. should your IC35 crash or explode
|
||||
while using ic35sync or ic35mgr, sorry.
|
||||
Besides my home machine this software was successfully used with:
|
||||
- KDE-1.1.2 Korganizer v1.1.1
|
||||
- Gnome-1.2 gnomecard,gnomecal from gnome-pim-1.2.0
|
||||
- IC35 Firmware V1.28
|
||||
- IC35 Firmware V1.38 (thanks Thomas Lichtenberg)
|
||||
- Debian-2.2r2 kernel 2.0.36 gcc-2.95.2 Pentium-I/133MHz /dev/ttyS3
|
||||
- Debian-2.2r2 kernel-2.2.13 gcc-2.95.2 Pentium-III/400MHz /dev/ttyS1
|
||||
- SuSE-7.2 (thanks Karl Stroetmann)
|
||||
- SuSE-7.0 kernel-2.2.16 gcc-2.95.2-98 AMD-K5/100MHz /dev/ttyS1
|
||||
- SuSE-7.0 kernel-2.2.16 gcc-2.95.2-98 Pentium-III/450MHz /dev/ttyS0
|
||||
- SuSE-6.0 kernel-2.0.36 gcc-2.7.2.3-5 BAYCOM Notebook Pentium-I/166MHz
|
||||
- Mandrake-7.2 AMD-Duron/750MHz /dev/ttyS1 (thanks Malte Schmidt)
|
||||
- Mandrake-8.0 gcc-2.96 (thanks Christian Theile)
|
||||
|
||||
That being said, I _really_ want comments regarding this software
|
||||
as well as suggestions and bug reports.
|
||||
|
||||
t.schulz@d2mail.de Thomas Schulz 2000-12-25
|
||||
Geibelstrasse 57
|
||||
D-22303 Hamburg
|
||||
Germany
|
||||
|
||||
Copyright (C) 2000,2001 Thomas Schulz
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program in the file COPYING; if not, write to the
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
People who contributed to IC35Link, in almost chronological order:
|
||||
|
||||
- Thomas Schulz <t.schulz@d2mail.de>
|
||||
the initial author (myself :-), needed it for lack of a Windows-System
|
||||
|
||||
- Michael Bruennert <michael.bruennert@eikon.tum.de>
|
||||
was the first one (besides me) interested in IC35sync/Linux,
|
||||
supplied lots of 'portmon' logs from IC35sync under Windows/NT,
|
||||
which made protocol analysis and implementation possible, and
|
||||
gave feedback about bugs under SuSE-7.0
|
||||
|
||||
- "Logbuch IC35" <Logbuch-IC35@exmail.de>
|
||||
supplied webspace for ic35sync_1.14.tar.gz and ic35sync_1.15.tar.gz
|
||||
|
||||
- Uwe Stobinski <uwe.stobinski@addcom.de>
|
||||
made an excellent IC35 website, hosted an "IC35 Wettbewerb" and
|
||||
supplied webspace for ic35sync_1.14.tar.gz and ic35sync_1.15.tar.gz
|
||||
|
||||
- Norbert Kolb <Norbert.Kolb@htl.de>
|
||||
offered means for publishing IC35sync/Linux
|
||||
and made many proposals for improving it
|
||||
|
||||
- Dieter Schultschik <schultschik@chello.at>
|
||||
alias <tscherno.bill@gmx.net>
|
||||
gave feedback about bugs under RedHat-7.0
|
||||
|
||||
- Harald Becker <harald@kristall.de>
|
||||
contributed ideas for faster write MMCard files and
|
||||
suggested compile without logging and com-simulation
|
||||
|
||||
- Oliver Zechlin <Oliver.Zechlin@mch.siemens.de>
|
||||
promised to supply me with the IC35 communication protocol specs
|
||||
and gave me "Goodies" for my "IC35 Wettbewerb" contribution
|
||||
|
||||
- Thomas Lichtenberg <thomas@ThomasLichtenberg.de>
|
||||
reported some bugs and did tests with IC35 firmware V1.38
|
||||
and under SuSE-7.0 and SuSE-6.0
|
||||
|
||||
- Malte Schmidt <malte.schmidt@gmx.de>
|
||||
reported some bugs and did tests with Mandrake-7.2
|
||||
|
||||
- Konrad Mader <konrad.mader@gmx.de>
|
||||
reported bug with ic35sync many addresses and some more
|
||||
inspired autogen.sh due to configure missing in CVS
|
||||
|
||||
- Christian Theile <ch_theile@gmx.de>
|
||||
reported compile problem with Mandrake-8.0
|
||||
|
||||
- Karl Stroetmann <Karl.Stroetmann@mchp.siemens.de>
|
||||
reported compile problem with SuSE-7.2
|
||||
|
||||
- Hans-Michael Stahl <hm.stahl@berlin.de>
|
||||
contributed ic35mgr "mmcgettree","mmcputtree" commands for whole dirtree
|
||||
|
||||
organizations whose work helped me:
|
||||
- Debian http://www.debian.org
|
||||
for the best (in my opinion) FreeSoftware GNU/Linux System
|
||||
- IMC consortium http://www.imc.org
|
||||
for the vCard,vCalendar standards and API
|
||||
- SourceForge http://sourceforge.net
|
||||
for hosting IC35Link and its CVS Repository
|
||||
|
|
@ -0,0 +1,741 @@
|
|||
$Id: TODO,v 1.21 2001/08/09 23:59:22 thosch Rel $
|
||||
TODO for IC35 communication
|
||||
===========================
|
||||
|
||||
legend
|
||||
------
|
||||
F task to do
|
||||
yyyy-mm-dd_hh WHAT
|
||||
details ..
|
||||
F sub-tasks ..
|
||||
F is current state from:
|
||||
- todo
|
||||
= work
|
||||
+ done
|
||||
x canc cancelled as no more need/want
|
||||
WHAT is task change from:
|
||||
todo task invented
|
||||
+nn% task nn% done
|
||||
done task done
|
||||
canc task cancelled
|
||||
|
||||
- documentation for newbies
|
||||
2001-08-03_13 todo Klaus Krenz <Klaus.Krenz@t-online.de> had problems
|
||||
- explain COM?-ports are /dev/ttyS?, symlink /dev/ic35, access rights
|
||||
- initial test with 'ic35sync status' and/or 'ic35mgr mmcdir'
|
||||
- for 'mmc*' commands put backslashed path in quotes
|
||||
- segfault empty fields in gcrd-file 'TITLE:' or 'BDAY:'
|
||||
2001-06-17_21 todo bug report by Konrad Mader <konrad.mader@gmx.de>
|
||||
empty 'BDAY:' does not segfault, but put 'BDAY' (no colon) into PIMfile
|
||||
and next ic35sync complains "parse error"
|
||||
seem like output error, i.e. shall output 'BDAY:' not 'BDAY'
|
||||
- report protocol error reasons (e.g. get_modflen timeout)
|
||||
2001-06-17_21 todo bug report by Konrad Mader <konrad.mader@gmx.de>
|
||||
should do better error reports for easier finding protocol problems
|
||||
get_modflen timeout failure for 860 addresses fixed 2001-06-17_23
|
||||
- combine ic35sync,ic35mgr into one program ic35link
|
||||
2001-02-25_20 todo proposed by Harald Becker
|
||||
- backward compatible: symlink ic35sync -> ic35link and ic35mgr -> ic35link
|
||||
behave like before if argv[0] is "ic35sync" or "ic35mgr"
|
||||
- partial help like CVS
|
||||
--help
|
||||
--help-options
|
||||
--help-commands
|
||||
-H <command> or --help <command>
|
||||
- fixes suggested by GNU Coding Standards and automake/autoconf
|
||||
2001-02-03_15 todo
|
||||
+ configure.in: use AC_REVISION
|
||||
+ fix warnings from -Wmissing-prototypes
|
||||
+ fix warnings from -ansi
|
||||
- fix warnings from -pedantic
|
||||
+ long options --version --help etc. --info shows build-info
|
||||
+ info enquiry with --version --help --info shall exit(0) !
|
||||
- use config.h in sources where needed (e.g. VERSION), see gnotepad+
|
||||
+ open device with O_NOCTTY
|
||||
- test on okosuse (yacc/bison), test on tls
|
||||
- misc: scripts for sync with gnome, korganizer
|
||||
- bugs to <email> at end of --help message
|
||||
- use 'autogen' for options and usage, see /usr/doc/autogen/autogen.ps
|
||||
- update copyright 2001, add license notice
|
||||
- ic35mgr.txt extensions
|
||||
2001-01-31_02 todo
|
||||
- new command 05 - retry read statusblock 16400-16 bytes
|
||||
in WinNT logs from Michael Logs270101.tar.gz
|
||||
- reponse 91 from IC35 for powerfail ? (see ic35mmcput52rcv91.log)
|
||||
- analyse & describe contents of IC35 statusblock, logo-bitmap
|
||||
see ic35mgr.txt 1.8.1
|
||||
- ic35mgr communication improves
|
||||
2001-01-30_01 todo
|
||||
- use #define for busywait delaytime and blocksize
|
||||
PIII/500MHz 16/3212 1/187
|
||||
- measure and improve timeouts in mgrproto.c
|
||||
? handle backup problem (Michael Bruennert): recv 90 instead of datablock
|
||||
- handle mgrproto problem: abort on recv 90 instead A0 after send ack/nak
|
||||
- mgrtrans.c: more disconn retry to catch >8.5 sec tmo on lost char
|
||||
maybe do twice Mcmdrsp(MCMDreset,MRSPgotcmd)
|
||||
- ic35sync syn{trans,proto}.* re-organize like mgr{trans,proto}.*
|
||||
2001-01-29_12 todo
|
||||
- ic35sync local database
|
||||
2001-01-26_01 todo
|
||||
to avoid read all IC35 records to check for deleted in PIMfiles
|
||||
and for store "sysinfo" date+time to check match with IC35
|
||||
may also need sync local databases between e.g. work-,home-system
|
||||
use XML-format for local database ?!
|
||||
- ic35mgr handle Ctl-C user interrupt
|
||||
2001-01-12_21 todo
|
||||
for mmcput,mmcget do mmc_close on SIGINT, for other ignore SIG_INT
|
||||
e.g. mmc_readfile,mmc_writefile return ERRor on SIG_INT
|
||||
- ic35mgr get/put multiple file, sync dirtree
|
||||
2001-01-12_19 todo
|
||||
- get multiple files:
|
||||
mmcget MMCard1/dir/* get all files from dir
|
||||
mmcget MMCard1/*.I35 get multiple files
|
||||
mmcget MMCard1/dir/ get recursively all files in dir and below
|
||||
mmcget MMCard1/ get recursively all files from MMCard
|
||||
recursive get creates local directory tree like to MMCard subtree
|
||||
additional localdir/ arg puts files below localdir/
|
||||
put multiple files with same logic
|
||||
problem: make dir on IC35 MMCard, use mmc_opendir(,MMCcreatrunc) ?
|
||||
- synchronize MMCard with local dirtree
|
||||
option "-n" to test what would be sync'd
|
||||
- interactive transfer multiple files and walk dirs (like ftp)
|
||||
2001-05-30_22 todo request guenther dreher-esders <guenther@esders-web.de>
|
||||
- guenther wants to 'ic35mgr mmcput MMCard1/x*.txt' for reading big text
|
||||
on IC35 split into many smaller files
|
||||
- ic35sync support XML format
|
||||
2001-01-09_17 todo proposed by Norbert Kolb
|
||||
see xmlFiles.pdf.gz from Harald Becker
|
||||
2001-02-25_20 work Harald Becker
|
||||
- ic35sync sync/import/export e.g. ToDoList alone
|
||||
2001-01-09_17 todo proposed by Norbert Kolb
|
||||
- analyse and implement IC35 manager install application,bitmap,midi
|
||||
2000-12-31 todo
|
||||
- send application
|
||||
- send IC35 start graphic bitmap
|
||||
- send MIDI file
|
||||
? remove application
|
||||
? remove bitmap, MIDI file
|
||||
- problem IC35 does not alarm
|
||||
2000-12-30_20 todo
|
||||
problem after: restore cfgmsg27.i35, set date+time, import 20001230.*
|
||||
reason: old repeated events "ww" 20001023,20001027 with endrepeat before today
|
||||
2000-12-31_17 50% reason found
|
||||
ic35sync do not write events with endrepeat before today ?
|
||||
- ic35sync corrections
|
||||
2000-12-30_19 todo
|
||||
+ on read_id_frec from IC35 fail do writerec instead of updaterec
|
||||
2000-12-31_18 +30%
|
||||
- write to IC35 all Sched,ToDo,Memo which not on IC35 (for initial sync)
|
||||
- sync overwrites IC35 changes after: reset,delall,restore IC35
|
||||
because IC35 appearently does not restore sysinfo date+time ?!
|
||||
- shared library e.g. for perl module ic35-communications
|
||||
2000-12-29_02 todo proposed by Norbert Kolb
|
||||
- vcaconv vca2bin,bin2vca,bin2txt transfer recstat
|
||||
design-problem ? updic35rec() and putic35rec() to not transfer recstat
|
||||
see experimental dataio.c 1.32.2
|
||||
2000-12-26_03 todo
|
||||
- ic35sync conflict resolve options
|
||||
2000-12-25_06 todo
|
||||
- PIM override IC35 (default)
|
||||
- IC35 overrides PIM
|
||||
- duplicate conflict records
|
||||
- inspect for sync,import/export: gnome-pilot,-conduits, pilot-link
|
||||
- search sourceforge etc. for other PIM-programs
|
||||
- reduce ic35sync log volume
|
||||
2000-12-14_21 todo
|
||||
option for loglevel, buffer higher level log lines in FIFO
|
||||
flush buffered log to file on error, discard if buffer gets full
|
||||
- ic35sync minor improvements
|
||||
2000-12-17_17 todo
|
||||
+ fix vcc.y compile warnings
|
||||
x extract rcskvf() from ic35sync.c,ic35mgr.c to util.c
|
||||
no more need with VERSION from configure.in
|
||||
- pimfile(s) writable not pre-checked, pim_close() does not return write-error
|
||||
- write and backup pimfile(s) only if really changed: global dirty-flag
|
||||
- pim_open(),pim_close() are misleading names
|
||||
xxx_open(),xxx_close re-design: who/where store filenames ?
|
||||
see experimental dataio.c 1.32.1 and datavca.c 1.38.1
|
||||
- dataio.c: use field map tables for vCard,vCal to/from IC35
|
||||
- syntrans.c: internal fd, no need for fd-argument
|
||||
implicit close on next open_file() and disconnect()
|
||||
- synproto.c: finer checks in recvrsp()
|
||||
- malloc/error traps with setjmp(),longjmp()
|
||||
- improve gnomecard
|
||||
2000-12-17_21 todo
|
||||
- does not change X-PILOTSTAT !
|
||||
fix: set X-PILOTSTAT:1 when VCARD changed
|
||||
- changes VCARD.REV to UTC not local time !
|
||||
- does update *ALL* VCARD.REV times on exit
|
||||
reason: gnomecard wants yyyy-mm-ddThh:mm:ss, drops yyyymmddThhmmss
|
||||
fix: accept also yyyymmddThhmmss
|
||||
- default e-mail type is AOL, better change to INTERNET
|
||||
- default birthday 1970-01-01 is bad, should be empty
|
||||
- improve gnomecal
|
||||
2000-12-25_19 todo
|
||||
- extra field for VTODO.DTSTART
|
||||
- extra field for VEVENT.DESCRIPTION
|
||||
- do not crash if VEVENT,VTODO.CLASS:PUBLIC missing
|
||||
- do not update *ALL* LAST-MODIFIED and DCREATED on exit
|
||||
- add missing standard categories Personal,Business(,Unfiled)
|
||||
- show/edit VTODO.STATUS
|
||||
? output correct VCAL.VERSION:1.0 instead of 1.2.0
|
||||
? seems to mis-behave with X-PILOTSTAT,X-PILOTID
|
||||
- improve korganizer
|
||||
2000-12-25_19 todo
|
||||
- support VTODO.DTSTART,DUE
|
||||
- support VTODO.CATEGORIES
|
||||
- support also AALARM, distinguish from DALARM
|
||||
? korganizer prios are 1,2,3,4 ? prios are duplicate ?
|
||||
- problem: memory leak in vobject.c setVObjectStringZValue()
|
||||
2000-12-12_02 todo
|
||||
setVObjectStringZValue() and relatives discard previous string
|
||||
although it may be malloc()ated'd and free() should be done.
|
||||
* vobject.c has 'strTbl[]' possibly usable to fix memory leak
|
||||
but strcasecmp prohibits use for any string
|
||||
strTbl[] used in lookupStr unUseStr cleanStrTbl
|
||||
lookupStr called by newVObject lookupProp
|
||||
unUseStr called by deleteVObject
|
||||
hashStr called by lookupStr unUseStr
|
||||
- solution-1:
|
||||
extend above vobject.c utilities with strcmp() instead of strcasecmp()
|
||||
- solution-2:
|
||||
always create new VObject instead of changing string values
|
||||
re-create vobj-list and/or vprop-list, then use cleanVObject()
|
||||
- solution-3:
|
||||
deleteStr() previous string value before set new string value
|
||||
- test-data for vCard,vCal to/from IC35 record conversion
|
||||
2000-12-11_12 todo
|
||||
- max.fieldlengths for each record
|
||||
- Addresses
|
||||
- name only
|
||||
- no, one, two, three email-addrs
|
||||
- telnos home,work,cell,fax
|
||||
- non-ASCII in Name,ADR,ORG,..
|
||||
- IC35 "(def.)" fields
|
||||
- Schedule
|
||||
- no alarm, LED-alarm, beep-alarm, LED+beep-alarm
|
||||
- alarm 0,1,5,10,30 mins, 1,2,10 hours, 1,2 days before
|
||||
- no repeat, repeat every d days, w weeks, m monwday, n monmday, y years
|
||||
- ToDoList
|
||||
- prio normal,high,low
|
||||
- completed no,yes, other status
|
||||
- Memo
|
||||
- ic35sync tests for export
|
||||
2000-12-15_12 todo
|
||||
restore IC35 from MMC, export from IC35 as reference PIMfile
|
||||
run tests: save PIMfile-1, export to PIMfile-2, compare PIMfile-1,-2
|
||||
= export to new PIMfile
|
||||
= export to existing same PIMfile
|
||||
no changes in PIMfile
|
||||
- add IC35 records, export
|
||||
only added PIMrecords shall be affected (modified+created time, recID)
|
||||
- change IC35 records, export
|
||||
only changed PIMrecords shall be affected (modified time)
|
||||
- add records to PIMfile, export
|
||||
added records in PIMfile shall be unaffected
|
||||
- change PIMrecords, export
|
||||
changed PIMrecords shall be overwritten from IC35
|
||||
- ic35sync tests for import
|
||||
2000-12-15_12 todo
|
||||
restore IC35 from MMC, export from IC35 as reference
|
||||
run tests: export-1,import,export-2, compare export-1,-2
|
||||
= import reference to IC35, i.e. re-import same data
|
||||
changeflags on IC35 shall be reset, PIMfile unaffected
|
||||
no write/update to IC35
|
||||
= reset IC35, import reference into empty IC35
|
||||
write all PIMrecords, new IC35-recIDs in PIMfile
|
||||
owner addr shall appear as such
|
||||
= add records to PIMfile, import
|
||||
added PIMrecords on IC35, IC35-recIDs in added PIMrecords
|
||||
- small PIMfile with all new records, import
|
||||
all PIMrecords on IC35, IC35-recIDs in PIMrecords
|
||||
= add records to IC35, import reference
|
||||
added IC35 records shall have changeflag, no set_date+time
|
||||
= change records in IC35, import reference
|
||||
changed IC35 records shall be overwritten from PIMfile
|
||||
- ic35sync tests for sync
|
||||
2000-12-19_02 todo
|
||||
= some test data in testdelfld{1,2,3}.vca
|
||||
sync testdelfld1.vca
|
||||
import testdelfld2.vca
|
||||
export testout2.vca
|
||||
copy testdelfld2.vca to testdelfld3t.vca, del fields,recs, set X-PILOTSTAT:1
|
||||
sync testdelfld3t.vca
|
||||
export testout3.vca should be same as testdelfld3t.vca
|
||||
IC35: mark all records edited
|
||||
copy testout2.vca to testdelfld4.vca
|
||||
sync testdelfld4.vca should be same as testdelfld3t.vca
|
||||
- specify more tests
|
||||
- ic35sync interactive ?
|
||||
2000-11-06_23 todo
|
||||
- implicit connect, on exit disconnect
|
||||
- set date, category
|
||||
- open file, close file
|
||||
- read file record
|
||||
- write file record
|
||||
- delete file record
|
||||
- reset file record changeflag
|
||||
- improve source comments
|
||||
2000-12-01_17 todo
|
||||
- ic35frec.c: IC35REC access logic
|
||||
- synproto.c: PDU parameters
|
||||
- ic35log.sh improvements and tests
|
||||
2000-12-01_14 todo
|
||||
- test with WindowsNT-2line logs: see below
|
||||
- test with WindowsNT-1line logs: see below
|
||||
- test with Windows98 logs: see below
|
||||
- improve ic35prot() structure to make it more clear / readable
|
||||
|
||||
DONE
|
||||
+ split ic35sync.c into modules:
|
||||
2000-11-06_23 todo
|
||||
+ util.c logging, error,message
|
||||
+ comio.c serial communication
|
||||
+ synproto.c L1,L2,L3 protocols
|
||||
+ syntrans.c L4 protocol: IC35sync transactions
|
||||
+ dataio.c import/export Addresses,Memo,Schedule,ToDoList as vCard,vCal
|
||||
+ ic35sync.c main, IC35sync session
|
||||
+ Makefile
|
||||
2000-11-07_03 done
|
||||
+ ic35sync minor improves
|
||||
2000-11-07_01 todo
|
||||
+ util.c
|
||||
+ log_init() set also loglevel, default logtag=NULL ?
|
||||
+ log ic35sync version/rcsid to logfile
|
||||
+ syntrans.c
|
||||
+ combined connect = welcome,identify,power,authenticate,getdtime ?
|
||||
+ welcome: "WELCOME\x80" no need send "A" ?
|
||||
+ stop on wrong password: response != 0101
|
||||
+ Makefile
|
||||
+ targets dist,dist_co for ic35sync_<vers>.tar.gz
|
||||
+ integrated help
|
||||
2000-11-15_04 +70% todo: Makefile
|
||||
2000-11-18_23 done
|
||||
+ ic35 record access
|
||||
2000-11-15_02 todo
|
||||
+ access record-field
|
||||
+ num.of record-fields to struct ic35file
|
||||
+ output binary record-data for offline vCard,vCal develop
|
||||
2000-11-19_01 done
|
||||
+ ic35sync export in vCard, vCalendar format
|
||||
2000-11-06_23 todo
|
||||
sources:
|
||||
* /local/pkg/ic35/sdkdllsr.zip
|
||||
vcc.h vcc.y vobject.h vobject.c
|
||||
* kpilot_3.1.10-1.0.tar.gz
|
||||
kpilot-3.1.10/conduits/vcalconduit/ vcal-conduit.h vcal-conduit.cc
|
||||
kpilot-3.1.10/conduits/vcalconduit/versit/ vcc.h vcc.y vobject.h vobject.c
|
||||
* gnome-pim_1.2.0.orig.tar.gz
|
||||
gnome-pim-1.2.0/libversit/ vcc.h vcc.y vobject.h vobject.c
|
||||
* gnome-pilot-conduits_0.4
|
||||
* gnome-pilot_0.1.55-0pre
|
||||
* jpilot_0.97
|
||||
* pilot-manager_1.107
|
||||
* pilot-link_0.9.3
|
||||
2000-11-19_20 work
|
||||
+ vcaconv:
|
||||
+ IC35 raw data -> vCard,vCal
|
||||
+ pretty-print vCard,vCal
|
||||
+ move ic35file definitions to dataio.c to vcaconv link syntrans etc.
|
||||
+ design output from IC35 to vCard,vCal file, maybe same file
|
||||
+ XPilotId instead of UID
|
||||
+ output text fields quoted printable if non-7bitASCII
|
||||
use CHARSET=ISO-8859-1;QUOTED-PRINTABLE
|
||||
+ Schedule: repeated events, recurrence rule
|
||||
+ Schedule: DALARM = LED, AALARM = beep
|
||||
+ whattodo with Memo in vCal format ?
|
||||
use VMEMO record VCMemoProp, extend vcc.*,vobject.*
|
||||
2000-11-20_05 +50%
|
||||
2000-11-21_06 +70%
|
||||
2000-11-22_08 done
|
||||
x ic35sync export in vCard, vCalendar format: canceled tasks
|
||||
2000-11-22_08 todo
|
||||
x vcaconv: vCard,vCal -> IC35 raw data
|
||||
x what is XPilotStatus for ? ICAL_PILOT_SYNC_{NONE,MOD,DEL}
|
||||
2000-12-01_15 canc replaced by ic35sync import,sync step-2,-3
|
||||
+ improve ic35prot.awk
|
||||
2000-11-07_23 todo
|
||||
+ test with WindowsNT-2line:
|
||||
+ Simple_hex.log
|
||||
+ Portmon_export.log
|
||||
+ Import1.log
|
||||
+ Import.tar.gz:Import.log
|
||||
+ test with Windows98:
|
||||
+ mgr_conn_disc.log
|
||||
+ mgr_conn_disc_mmc.log.gz
|
||||
+ sync_missoutlook.log
|
||||
+ mgr_rwdfile_20001107.tar.gz:*.log
|
||||
2000-11-15_01 +90% usable, todo: missing tests & improve structure
|
||||
2000-11-27_13 canc ic35prot.awk replaced by ic35log.sh
|
||||
x improve ic35prot.awk: canceled tasks
|
||||
2000-11-07_23 todo
|
||||
x test with WindowsNT-1line:
|
||||
x Manager.tar.gz:*.LOG
|
||||
x BackupRestore.tar.gz:*.log
|
||||
x improve structure to make it more clear / readable
|
||||
2000-11-27_13 canc ic35prot.awk replaced by ic35log.sh
|
||||
+ improve ic35-prot-analyzer
|
||||
20001124_20 todo
|
||||
+ print 2nd ff. recdata fragments, 'currfid' less hacked
|
||||
+ integrate in one script
|
||||
+ ic35prot.awk faster and more clear
|
||||
no need to support ASCII input
|
||||
move ASCII output to separate pass
|
||||
20001127_13 done
|
||||
+ analyse Delete.tar.gz delete record etc.
|
||||
2000-11-18_01 todo
|
||||
+ meaning of new commands 01 02, 01 07
|
||||
01 07 = read next modified record
|
||||
01 02 = delete record
|
||||
x meaning of category response 01 01, 00 01
|
||||
moved to "ic35sync experiments"
|
||||
2000-11-24_01 done
|
||||
+ ic35sync.txt: document readrecmod, deleterec
|
||||
20001124_20 todo
|
||||
20001127_15 done
|
||||
+ ic35sync import,sync step-1
|
||||
20001124_20 todo
|
||||
+ dataio.c: use rec-id AND file-id as UID/X-PILOTID
|
||||
+ dataio.c: implement REV, LAST-MODIFIED
|
||||
+ get_mod_flen
|
||||
+ read_mod_frec
|
||||
+ delete_frec
|
||||
+ write_frec
|
||||
+ set_date_time
|
||||
+ category
|
||||
20001128_04 done
|
||||
+ ic35 record access
|
||||
2000-11-21_02 todo
|
||||
+ use ulong frid instead of uchar fid, ushort rid
|
||||
+ internal IC35 record structure for easier access
|
||||
+ break into fields, _get_recfld()'s static buffer is bad!
|
||||
2000-12-01_02 +90% todo: opaque IC35FILE
|
||||
+ hide ic35 file description internals, use acces functions
|
||||
+ use 4byte record-ID in binary format
|
||||
2000-12-01_19 done
|
||||
+ ic35log.sh process ic35sync logfiles, create simulation files from them
|
||||
2000-12-01_14 todo
|
||||
2000-12-02_02 done
|
||||
+ ic35sync experiments:
|
||||
2000-11-06_23 todo
|
||||
tests for category,filename in ic35sync.c 1.11.1 branch
|
||||
+ check wrong password:
|
||||
complains with 0100 (not 0101) only if password on power-on enabled
|
||||
+ check category response
|
||||
+ unknown category
|
||||
+ category with no records, e.g. "Unfiled"
|
||||
+ category with modified record(s)
|
||||
+ category with new record(s)
|
||||
+ new category with new record(s)
|
||||
+ new category without records
|
||||
+ set category influence on read_mod_frec ? NO!
|
||||
mostly response for existing category is 01 01, for non-exist 00 01
|
||||
but not always, still unclear what the category sematics are
|
||||
+ test bad filename or other files, e.g. Messages ?
|
||||
open compares only first any-case letter, unmatched opens "Schedule
|
||||
2000-12-02_05 done
|
||||
+ ic35sync import,sync step-2
|
||||
20001124_20 todo
|
||||
tests in ic35sync.c 1.11.1 branch
|
||||
+ commit_frec
|
||||
+ test functions for import,sync:
|
||||
+ category
|
||||
+ set_date_time
|
||||
allows setting any text, tested up to 14 chars, maybe up to 16 chars
|
||||
+ get_mod_flen, read_mod_frec
|
||||
+ write_frec
|
||||
+ delete_frec
|
||||
+ commit_frec
|
||||
+ field modified on PC: only write_frec or also del old frec ?
|
||||
must delete_frec old, as write_frec gets new rec-ID (does NOT overwrite)
|
||||
20001202_07 done
|
||||
+ ic35sync experiments for new commands
|
||||
20001201_20 todo
|
||||
+ 00 01 ? file command ? ic35r{66,68}.log
|
||||
IC35 accepts 1st command, response: E3,49 CD 0F
|
||||
then IC35 hangs no more accepting commands
|
||||
? 01 01 ? del all? NO! ic35r{62,63,65}.log
|
||||
IC35 returns "done" response A0 03 00, record unchanged
|
||||
* 01 02 fd_-- ri_--_-- fi delete_frec
|
||||
* 01 03 fd_-- 00 00 00 00 get_flen
|
||||
* 01 04 fd_-- 00 00 00 00 get_mod_flen
|
||||
+ 01 05 fd_-- ri_--_-- fi read by recID ic35r{60,69,6A}.log
|
||||
response non-exist Memo recID: A0,49 3E 81 D3 0D 60 xx xx xx 07
|
||||
i.e. recID=0DD3813E, ch=60, 4 flens for Memo record
|
||||
response non-exist Schedule recID: A0,49 FE AA 20 0E 00 xx xx xx ..
|
||||
i.e. recID=0E20AAFE, ch=00, 10 flens for Schedule record
|
||||
* 01 06 fd_-- 00 00 00 00 read_frec
|
||||
* 01 07 fd_-- 00 00 00 00 read_mod_frec
|
||||
* 01 08 fd_-- 00 00 00 00 write_frec
|
||||
+ 01 09 fd_-- ri_--_-- fi ... update_frec ic35r{61,6B,6C}.log
|
||||
re-writes record keeping same recID
|
||||
* 01 0A fd_-- ri_--_-- fi commit_frec
|
||||
2000-12-03_09 done
|
||||
+ ic35sync import,sync step-3
|
||||
20001124_20 todo
|
||||
vCard,vCal to IC35 record, test with vcaconv
|
||||
+ CategoryID cannot be mapped, use 0x00 and assume IC35 to create it
|
||||
+ Category: assume IC35 auto-creates new category
|
||||
+ vcard_to_ic35addr
|
||||
+ vevent_to_ic35sched
|
||||
+ vtodo_to_ic35todo
|
||||
+ vmemo_to_ic35memo
|
||||
20001207_04 done
|
||||
+ problem: QUOTED-PRINTABLE fails with multi-field props like ADR,N,ORG,..
|
||||
2000-12-16_15 todo
|
||||
with QUOTED-PRINTABLE e.g. ADR fields are not separated, but
|
||||
first field gets value of all fields with ';' embedded.
|
||||
known but unfixed problem, see: http://www.imc.org/imc-vcard/mail-archive/
|
||||
+ solution-1
|
||||
do not use QUOTED-PRINTABLE on multi-field props, but only CHARSET
|
||||
x solution-2
|
||||
further debug problem to find real cause and fix
|
||||
2000-12-16_21 done
|
||||
+ ic35sync import,sync step-4 (import)
|
||||
2000-11-24_20 todo
|
||||
import,sync do both use set_date_time
|
||||
+ what is XPilotStatus for ? ICAL_PILOT_SYNC_{NONE,MOD,DEL}
|
||||
+ need update vCard,vCal from IC35rec to avoid destroy unmapped fields
|
||||
+ import vCard,vCal or binary into IC35
|
||||
2000-12-17_08 done
|
||||
+ vcaconv optionally sort output needed for test
|
||||
2000-12-17_06 todo
|
||||
sort vCard,vCal to stdout
|
||||
2000-12-20_16 done
|
||||
+ problems with gnomecard
|
||||
2000-12-17_21 todo
|
||||
+ does not change X-PILOTSTAT, cannot not rely on X-PILOTSTAT alone
|
||||
fix: detect change with create/modify-time VCARD.REV > last-sync-time
|
||||
+ does update *ALL* VCARD.REV times on exit
|
||||
reason: gnomecard wants yyyy-mm-ddThh:mm:ss, drops yyyymmddThhmmss
|
||||
fix: produce VCARD.REV:yyyy-mm-ddThh:mm:ss
|
||||
2000-12-21_15 done
|
||||
+ problems with korganizer
|
||||
2000-12-17_21 todo
|
||||
+ wants VCAL PRODID:-//K Desktop Environment//NONSGML KOrganizer//EN
|
||||
fixed ic35sync: do not change found VCAL:PRODID
|
||||
must manually edit vCal output before load new into korganizer
|
||||
+ complains if VEVENT,VTODO lack UID and does not load those without
|
||||
fixed ic35sync: also put UID to VCAL:VEVENT,VTODO (and VCARD, VMEMO)
|
||||
+ expects and produces NL-terminated lines, misbehaves on CRLF-terminated
|
||||
fix ic35sync: auto-detect CRLF or NL and produce same output
|
||||
+ output causes parse-error if CR in NOTE,DESC,..
|
||||
need translate NOTE,DESC: PIM NL <-> IC35 CRLF
|
||||
+ does not support VTODO.DTSTART,DUE
|
||||
fix ic35sync: map to marked lines in VTODO
|
||||
+ does not support VTODO.CATEGORIES, keep IC35 on PIM->IC35 update
|
||||
x has VEVENT.CATEGORIES, but IC35 has not
|
||||
2000-12-24_20 done
|
||||
+ problems with gnomecal
|
||||
2000-12-17_21 todo
|
||||
+ does not support VTODO.DTSTART, but keeps in vCal on exit
|
||||
fix ic35sync: keep marked line in VTODO.DESCRIPTION
|
||||
+ crashes if VTODO,VEVENT.CLASS:PUBLIC is missing
|
||||
fix ic35sync: put CLASS:PUBLIC to VTODO,VEVENT if missing
|
||||
+ does not support VEVENT.DESCRIPTION, removes it from vCal on exit
|
||||
vevent_to_ic35sched: 1st line to S_Subject, more lines to S_Notes
|
||||
ic35sched_to_vevent: for gnomecal append S_Notes to VEVENT.SUMMARY
|
||||
x outputs bad VCAL.VERSION:1.2.0, ic35sync keeps found version
|
||||
2000-12-25_19 done
|
||||
+ ic35sync import,sync step-5 (sync)
|
||||
2000-12-15_12 todo
|
||||
+ sync vCard,vCal with IC35
|
||||
+ conflict resolve: initial sync empty PIM must not delete all IC35!
|
||||
+ inspect for sync,import: gnome-pim, kpilot
|
||||
2000-12-25_06 done
|
||||
+ ic35sync some improvements
|
||||
2000-12-17_17 todo
|
||||
+ comio.c: for simulate do not set DTR neither open comport
|
||||
+ comio.c: log input V.24 signals on change
|
||||
+ comio.c: allow also WRx and RDx in simulation file
|
||||
+ dataio.c: remove unused _get_vcarec()
|
||||
+ dataio.c big, split: dataio.c 341 datatxt.c 92 databin.c 385 datavca.c 1528
|
||||
+ dataio.c: translate CRLF<->NL in NOTES,DESCRIPTION
|
||||
+ dataio.c utils, special conversions depend on PRODID Gnome,KOrganizer
|
||||
put/get IC35 fields unsupported by PIM with mark in NOTE/DESCRIPTION
|
||||
+ KOrganizer: VTODO.CATEGORIES,DTSTART,DUE to/from VTODO.DESCRIPTION
|
||||
+ gnomecal: VTODO.DTSTART to/from VTODO.DESCRIPTION
|
||||
+ gnomecal: VEVENT.DESCRIPTION 1st line S_Subject, more S_Notes
|
||||
+ all: "(def1):","(def2):" to/from VCARD.NOTE
|
||||
+ cmp_ic35rec() from dataio.c to ic35frec.c:cmp_ic35rec ?
|
||||
2000-12-25_23 done
|
||||
+ ic35sync delete fields
|
||||
currently IC35 to/from PIM record conversions do not delete fields
|
||||
2000-12-27_19 todo
|
||||
2000-12-29_04 done
|
||||
+ correct vcaconv
|
||||
produces empty output on 'vcaconv sortvca ic35.vcal'
|
||||
2000-12-31_01 todo
|
||||
fix: correct error in vobject.c
|
||||
2000-12-31_18 done
|
||||
+ analyse IC35 manager protocol
|
||||
2000-11-06_23 todo
|
||||
+ init, exit
|
||||
+ backup database.org
|
||||
+ restore database.org
|
||||
+ read MMCard directories
|
||||
+ read file from MMCard
|
||||
2001-01-04_06 +70%
|
||||
+ write file to MMCard
|
||||
+ delete file on MMCard
|
||||
2001-01-10_03 done
|
||||
+ implement IC35 manager MMCard operations
|
||||
2000-12-31_18 todo
|
||||
+ init, exit
|
||||
+ read MMCard directories
|
||||
+ read file from MMCard
|
||||
2001-01-10_02 +60%
|
||||
+ write file to MMCard
|
||||
+ delete file on MMCard
|
||||
2001-01-12_22 done
|
||||
+ implement IC35 manager backup,restore operations
|
||||
2000-12-31_18 todo
|
||||
+ backup database.org
|
||||
+ restore database.org
|
||||
2001-01-17_06 done
|
||||
+ improve ic35mgr throughput
|
||||
2001-01-12_20 todo
|
||||
ic35mgr-1.17.4, busy wait 3.25ms every 16 byte block, 2 stopbits
|
||||
backup 426128 read 16384 117.3248 3632 b/s
|
||||
block recv 16384 3.3211 4924 b/s
|
||||
restore 426128 write 16384 140.4816 3033 b/s
|
||||
block send 16384 3.5056 4674 b/s
|
||||
ic35mgr-1.12a, with com_sendw(), itimer pause every 29 chars, 2 stopbits
|
||||
reversi.app 16452 read 5120 6.5236 2522 b/s
|
||||
reversi.app 16452 write 2048 11.9835 1373 b/s
|
||||
+ comio.c,comio.h: separate com_sendw() with wait
|
||||
+ mgrproto.c: use com_sendw() with wait only for big blocks
|
||||
measurements:
|
||||
install MMCard:browser.app 376900 117.69 3202 b/s
|
||||
install MMCard:sc_info.app 16452 10.07 1634 b/s
|
||||
install MMCard:convert.app 49220 15.22 3234 b/s
|
||||
restore MMCard1\20010124.I35 52222 25.962 2011 b/s
|
||||
backup MMCard1\20010121.I35 50701 20.625 2458 b/s
|
||||
ic35mgr-1.10a, with com_sendw(), itimer pause every 29 chars, 2 stopbits
|
||||
reversi.app 16452 read 5120 6.5678 2505 b/s
|
||||
reversi.app 16452 write 2048 12.0640 1364 b/s
|
||||
backup 426128 read 16384 117.4514 3628 b/s
|
||||
block recv 16384 3.3287 4922 b/s
|
||||
restore 426128 write 16384 203.6398 2093 b/s
|
||||
block send 16384 6.0531 2707 b/s
|
||||
status 16400 recv 16384 1.8257 8983 b/s
|
||||
itimer, pause every 29 chars, 2 stopbits
|
||||
reversi.app 16452 write 5120 11.8633 1387 b/s
|
||||
2048 12.3224 1335 b/s rewrite 13.8034 1192 b/s
|
||||
mgrep.app 32836 write 2048 24.6884 1330 b/s
|
||||
domind.app 49220 write 2048 37.1055 1326 b/s
|
||||
domind.app 49220 read 5120 20.0052 2460 b/s
|
||||
usleep(29*400) every 29 bytes, 2 stopbits
|
||||
reversi.app 16452 write 5120 17.69 929 b/s
|
||||
2048 18.42 893 b/s
|
||||
usleep(100) every 16 bytes
|
||||
reversi.app 16452 write 5120 26.965 610 b/s
|
||||
2048 27.764 593 b/s rewrite 29.094 565 b/s
|
||||
1024 29.465 558 b/s
|
||||
reversi.app 16452 read 10240 6.825 2410 b/s
|
||||
5120 7.284 2259 b/s 7.385 2228 b/s
|
||||
2048 8.485 1939 b/s
|
||||
1024 10.204 1612 b/s
|
||||
256 20.396 807 b/s
|
||||
15 243.773 67 b/s
|
||||
2001-01-18_02 done
|
||||
+ fix compile errors with gcc-2.96 under RedHat-7.0
|
||||
2001-01-19_17 todo reported by Dieter Schultschik
|
||||
+ synproto.c:sendcmd() line-531,537,542,548,549,554,567,594
|
||||
531:fd, 537:fd, 542:fd, 548:fd, 549:index, 554:fd, 567:fd, 594:fd
|
||||
`short unsigned int' is promoted to `int' when passed through `...'
|
||||
(so you should pass `int' not `short unsigned int' to `va_arg')
|
||||
+ mgrproto.c similar problem
|
||||
+ generally avoid va_arg with sendcmd() etc, replace sendcmd(CMDfclosem,fd)
|
||||
with e.g. sendCMDfclose(fd) would yield compile-time prototype checking
|
||||
2001-01-29_13 done
|
||||
+ improve ic35mgr
|
||||
2001-01-12_20 todo
|
||||
+ mgrproto.c: recvmrsp() / MPDUrecv() discard checksum
|
||||
+ mgrtrans.c: protocol comments, identify,disconn,.. belong to mgrproto.c
|
||||
+ move backup protocol from mgrtrans.c to mgrproto.{c,h}
|
||||
concentrate log,progress,errmsg separate from communication protocol
|
||||
+ move putxxx(),getxxx(),chksum() from mgrtrans.c,xxxproto.{c,h}
|
||||
and also welcome() etc. to genproto.{c,h}
|
||||
2001-01-24_03 +50%
|
||||
+ move _not_impl() from ic35mgr.c to util.{c,h}
|
||||
+ recvmrsp() always return mstate, not pdulen
|
||||
+ mgrproto.c: common structs for same PDUs
|
||||
2001-01-29_12 +70%
|
||||
+ mgrproto.c: common convert direntry and FILE_INFO
|
||||
+ mgrproto.c: define iden/FILE_IDEN details, export size, how mismatch?
|
||||
+ mgrproto.h: move attribs,modes from mgrtrans.h (else mgrproto.c unusable)
|
||||
for backward compatible #include mgrproto.h in mgrtrans.c
|
||||
x mgrtrans.c: common struct for MMCDIR MMCFILE
|
||||
x extract rcskvf() from ic35sync.c,ic35mgr.c to util.c
|
||||
with VERSION imported rcskvf() is obsolete
|
||||
2001-02-03_18 done
|
||||
+ supply also vcc.c problem found by Harald Becker, Michael Bruennert
|
||||
2001-01-19_09 todo
|
||||
supply also vcc.c for systems without or with bad bison/yacc
|
||||
SuSE-7.0 yacc-91.7.30-220 is bad, need bison >= 1.25
|
||||
2001-02-04_01 done
|
||||
+ automake/autoconf
|
||||
2000-12-29_02 todo proposed by Norbert Kolb
|
||||
* see Software-Release-Practice-HOWTO, GNU Coding Standards
|
||||
* must unset CDPATH, else re-automake fails!
|
||||
+ configure.in Makefile.am, then run:
|
||||
aclocal; autoheader; automake --add-missing --gnu; autoconf; ./configure
|
||||
+ re-org into dirs src/ docs/
|
||||
+ make CVS-tree, use .cvsignore
|
||||
+ AUTHORS
|
||||
+ THANKS or CREDITS
|
||||
+ NEWS: compact version info
|
||||
+ README: re-org like Software-Release-Practice-HOWTO suggests
|
||||
x acconfig.h: ISODATE NOT NEEDED
|
||||
+ program-versions from VERSION,ISODATE, remove rcskvf
|
||||
+ step-1: do it with current Makefile
|
||||
+ build-info like gnotepad+
|
||||
+ fix also top-entry in logfiles
|
||||
2001-02-05_03 done
|
||||
+ README / more docs, e.g. restrictions & workarounds
|
||||
2001-01-26_03 todo
|
||||
+ Korganizer: PRODID, workaround missing vCal properties (...)
|
||||
+ GnomeCal: PRODID, workaround missing vCal properties (...)
|
||||
+ GnomeCard: missiong X-PILOT-STAT support and workaround
|
||||
+ problem with bash eating backslash of ic35path
|
||||
+ errors/warnings with 'configure --enable-pedantic'
|
||||
+ compile problem with yacc (if vcc.y changed)
|
||||
+ no sync conflict resolve yet
|
||||
+ proprietary VMEMO format
|
||||
2001-02-17_21 done
|
||||
+ ic35mgr mmcget/mmcput check ic35path before connect
|
||||
bug-report from Thomas Lichtenberg
|
||||
2001-02-06_00 todo
|
||||
valid ic35path:
|
||||
+ auto-translate leading anycase mmcard[12], lower to upper, '/' to '\'
|
||||
+ leading "MMCard[12]/"
|
||||
+ adjacent / or \ not allowed
|
||||
+ max 1 dot between '/' and '/' or end
|
||||
+ max 8 chars before dot
|
||||
+ max 3 chars after dot
|
||||
tests (mail from Thomas Lichtenberg):
|
||||
+ ic35mgr mmcdel MMCard1\IC35\BITMAP\INDIANER.BMP
|
||||
+ ic35mgr mmcput MMCard1\TEST\TEST1.TXT test.txt
|
||||
2001-02-18_07 done
|
||||
+ correct com_simrecv(): dummy for non-logged receive bytes, adjacent "RD nn"
|
||||
2001-01-04_05 todo
|
||||
+ err.corr: fill block from adjacent "RD nn" lines, dummy non-logged
|
||||
x handle checksum problem due to dummy bytes
|
||||
cannot, must patch simfile with expected checksum(s)
|
||||
2001-02-18_23 done
|
||||
+ configure --disable-logandcomsim
|
||||
2001-02-25_20 todo proposed by Harald Becker
|
||||
+ configure option for disable logging and simulation for production version
|
||||
default enabled
|
||||
+ use macros LPRINTF(()), LOG_INIT(()), etc. to reduce codesize
|
||||
2001-03-02_02 done
|
||||
+ reduce priority when using busywait
|
||||
2001-02-25_20 todo proposed by Harald Becker
|
||||
+ use for restore,mmcput only, nice(+2), man 2 nice
|
||||
+ option "-n niceval" or "--nice niceval", default niceval 2
|
||||
allowed for users 0..19 for root -20..19, 0 is normal prio
|
||||
2001-03-03_04 done
|
||||
+ autogen.sh script for generating configure, Makefile.in, etc.
|
||||
2001-05-30_11 todo problem report by Konrad Mader <konrad.mader@gmx.de>
|
||||
2001-08-02_22 done
|
|
@ -0,0 +1,230 @@
|
|||
#!/bin/sh
|
||||
# $Id: autogen.sh,v 1.4 2001/08/12 03:34:50 thosch Rel $
|
||||
# Copyright (C) 2001 Thomas Schulz
|
||||
#
|
||||
# Run this to generate configure and all the initial makefiles, etc.
|
||||
# This is the long version with lots of checks instead of the short version
|
||||
# aclocal && autoheader && automake --add-missing --gnu && autoconf
|
||||
# It will automagically run './configure $CONFIGURE_FLAGS', prevent that
|
||||
# by setting the environment variable NOCONFIGURE to a non-empty value.
|
||||
|
||||
# NOCONFIGURE=true # would disable auto-configure
|
||||
CONFIGURE_FLAGS="--enable-maintainer-mode" # default flags for configure
|
||||
# ACLOCAL_FLAGS= # additional flags for aclocal
|
||||
|
||||
|
||||
DIE=0
|
||||
srcdir=`dirname $0`
|
||||
eval `grep '^PACKAGE=' $srcdir/configure.in`
|
||||
|
||||
if [ -n "$GNOME2_PATH" ]; then
|
||||
ACLOCAL_FLAGS="-I $GNOME2_PATH/share/aclocal $ACLOCAL_FLAGS"
|
||||
PATH="$GNOME2_PATH/bin:$PATH"
|
||||
export PATH
|
||||
fi
|
||||
|
||||
#
|
||||
# check for autoconf
|
||||
#
|
||||
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Error**: You must have \`autoconf' installed to compile $PACKAGE"
|
||||
echo "Download the appropriate package for your distribution,"
|
||||
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
|
||||
DIE=1
|
||||
}
|
||||
|
||||
#
|
||||
# check for xml-i18n-toolize if needed
|
||||
#
|
||||
(grep "^AM_PROG_XML_I18N_TOOLS" $srcdir/configure.in >/dev/null) && {
|
||||
(xml-i18n-toolize --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Error**: You must have \`xml-i18n-toolize' installed to compile $PACKAGE"
|
||||
echo "Get ftp://ftp.gnome.org/pub/GNOME/stable/sources/xml-i18n-tools/xml-i18n-tools-0.6.tar.gz"
|
||||
echo "(or a newer version if it is available)"
|
||||
DIE=1
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# check for libtool if needed
|
||||
#
|
||||
(grep "^AM_PROG_LIBTOOL" $srcdir/configure.in >/dev/null) && {
|
||||
(libtool --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Error**: You must have \`libtool' installed to compile $PACKAGE"
|
||||
echo "Get ftp://ftp.gnu.org/pub/gnu/libtool-1.2d.tar.gz"
|
||||
echo "(or a newer version if it is available)"
|
||||
DIE=1
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# check for gettext if needed
|
||||
#
|
||||
#grep "^AM_GNU_GETTEXT" $srcdir/configure.in >/dev/null && {
|
||||
# grep "sed.*POTFILES" $srcdir/configure.in >/dev/null || \
|
||||
# (gettext --version) < /dev/null > /dev/null 2>&1 || {
|
||||
# echo
|
||||
# echo "**Error**: You must have \`gettext' installed to compile $PACKAGE"
|
||||
# echo "Get ftp://alpha.gnu.org/gnu/gettext-0.10.35.tar.gz"
|
||||
# echo "(or a newer version if it is available)"
|
||||
# DIE=1
|
||||
# }
|
||||
#}
|
||||
|
||||
#grep "^AM_GNOME_GETTEXT" $srcdir/configure.in >/dev/null && {
|
||||
# grep "sed.*POTFILES" $srcdir/configure.in >/dev/null || \
|
||||
# (gettext --version) < /dev/null > /dev/null 2>&1 || {
|
||||
# echo
|
||||
# echo "**Error**: You must have \`gettext' installed to compile $PACKAGE"
|
||||
# echo "Get ftp://alpha.gnu.org/gnu/gettext-0.10.35.tar.gz"
|
||||
# echo "(or a newer version if it is available)"
|
||||
# DIE=1
|
||||
# }
|
||||
#}
|
||||
|
||||
#
|
||||
# check for automake
|
||||
#
|
||||
(automake --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Error**: You must have \`automake' installed to compile $PACKAGE"
|
||||
echo "Download the appropriate package for your distribution,"
|
||||
echo "or get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
|
||||
echo "(or a newer version if it is available)"
|
||||
DIE=1
|
||||
NO_AUTOMAKE=yes
|
||||
}
|
||||
|
||||
#
|
||||
# check for aclocal
|
||||
#
|
||||
# if no automake, don't bother testing for aclocal
|
||||
test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Error**: Missing \`aclocal'. The version of \`automake'"
|
||||
echo "installed doesn't appear recent enough."
|
||||
echo "Download the appropriate package for your distribution,"
|
||||
echo "or get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
|
||||
echo "(or a newer version if it is available)"
|
||||
DIE=1
|
||||
}
|
||||
|
||||
if test "$DIE" -eq 1; then # some tools are missing
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$*" -a -z "$NOCONFIGURE"; then
|
||||
echo "**Warning**: I am going to run \`configure $CONFIGURE_FLAGS'"
|
||||
echo "If you wish to pass additional flags to it, please specify them on"
|
||||
echo "the \`$0' command line."
|
||||
echo
|
||||
fi
|
||||
|
||||
case $CC in
|
||||
xlc )
|
||||
am_opt=--include-deps;;
|
||||
esac
|
||||
|
||||
for coin in `find $srcdir -name configure.in -print`
|
||||
do
|
||||
dr=`dirname $coin`
|
||||
if test -f $dr/NO-AUTO-GEN; then
|
||||
echo skipping $dr -- flagged as no auto-gen
|
||||
else
|
||||
echo processing $dr
|
||||
macrodirs=`sed -n -e 's,AM_ACLOCAL_INCLUDE(\(.*\)),\1,gp' < $coin`
|
||||
( cd $dr
|
||||
macrosdir=`find . -name macros -print`
|
||||
for i in $macrodirs; do
|
||||
if test -f $i/gnome-gettext.m4; then
|
||||
DELETEFILES="$DELETEFILES $i/gnome-gettext.m4"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "deletefiles is $DELETEFILES"
|
||||
aclocalinclude="$ACLOCAL_FLAGS"
|
||||
for k in $aclocalinclude; do
|
||||
if test -d $k; then
|
||||
if [ -f $k/gnome.m4 -a "$GNOME_INTERFACE_VERSION" = "1" ]; then
|
||||
rm -f $DELETEFILES
|
||||
fi
|
||||
fi
|
||||
done
|
||||
for k in $macrodirs; do
|
||||
if test -d $k; then
|
||||
aclocalinclude="$aclocalinclude -I $k"
|
||||
if [ -f $k/gnome.m4 -a "$GNOME_INTERFACE_VERSION" = "1" ]; then
|
||||
rm -f $DELETEFILES
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if grep "^AM_GNU_GETTEXT" configure.in >/dev/null; then
|
||||
if grep "sed.*POTFILES" configure.in >/dev/null; then
|
||||
: do nothing -- we still have an old unmodified configure.in
|
||||
else
|
||||
echo "Creating $dr/aclocal.m4 ..."
|
||||
test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
|
||||
echo "Running gettextize... Ignore non-fatal messages."
|
||||
echo "no" | gettextize --force --copy
|
||||
echo "Making $dr/aclocal.m4 writable ..."
|
||||
test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
|
||||
fi
|
||||
fi
|
||||
if grep "^AM_GNOME_GETTEXT" configure.in >/dev/null; then
|
||||
echo "Creating $dr/aclocal.m4 ..."
|
||||
test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
|
||||
echo "Running gettextize... Ignore non-fatal messages."
|
||||
echo "no" | gettextize --force --copy
|
||||
echo "Making $dr/aclocal.m4 writable ..."
|
||||
test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
|
||||
fi
|
||||
if grep "^AM_PROG_XML_I18N_TOOLS" configure.in >/dev/null; then
|
||||
echo "Running xml-i18n-toolize... Ignore non-fatal messages."
|
||||
xml-i18n-toolize --copy --force --automake
|
||||
fi
|
||||
if grep "^AM_PROG_LIBTOOL" configure.in >/dev/null; then
|
||||
if test -z "$NO_LIBTOOLIZE" ; then
|
||||
echo "Running libtoolize..."
|
||||
libtoolize --force --copy
|
||||
fi
|
||||
fi
|
||||
echo "Running aclocal $aclocalinclude ..."
|
||||
aclocal $aclocalinclude || {
|
||||
echo
|
||||
echo "**Error**: aclocal failed. This may mean that you have not"
|
||||
echo "installed all of the packages you need, or you may need to"
|
||||
echo "set ACLOCAL_FLAGS to include \"-I \$prefix/share/aclocal\""
|
||||
echo "for the prefix where you installed the packages whose"
|
||||
echo "macros were not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if grep "^AM_CONFIG_HEADER" configure.in >/dev/null; then
|
||||
echo "Running autoheader..."
|
||||
autoheader || { echo "**Error**: autoheader failed."; exit 1; }
|
||||
fi
|
||||
echo "Running automake --gnu $am_opt ..."
|
||||
automake --add-missing --gnu $am_opt ||
|
||||
{ echo "**Error**: automake failed."; exit 1; }
|
||||
echo "Running autoconf ..."
|
||||
autoconf || { echo "**Error**: autoconf failed."; exit 1; }
|
||||
) || exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
if test x$NOCONFIGURE = x; then
|
||||
echo
|
||||
echo Running $srcdir/configure $CONFIGURE_FLAGS "$@" ...
|
||||
$srcdir/configure $CONFIGURE_FLAGS "$@" \
|
||||
&& echo Now type \`make\' to compile $PACKAGE || exit 1
|
||||
else
|
||||
echo
|
||||
echo Skipping configure process.
|
||||
echo "Now type \`./configure $CONFIGURE_FLAGS'"
|
||||
echo "and then \`make' to compile $PACKAGE"
|
||||
echo " or type \`./configure --help' and see README for configure options."
|
||||
fi
|
|
@ -0,0 +1,348 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand '-c -o'.
|
||||
|
||||
scriptversion=2018-03-07.03; # UTC
|
||||
|
||||
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
nl='
|
||||
'
|
||||
|
||||
# We need space, tab and new line, in precisely that order. Quoting is
|
||||
# there to prevent tools from complaining about whitespace usage.
|
||||
IFS=" "" $nl"
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file lazy
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts. If the determined conversion
|
||||
# type is listed in (the comma separated) LAZY, no conversion will
|
||||
# take place.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN* | MSYS*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv/,$2, in
|
||||
*,$file_conv,*)
|
||||
;;
|
||||
mingw/*)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin/* | msys/*)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine/*)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_cl_dashL linkdir
|
||||
# Make cl look for libraries in LINKDIR
|
||||
func_cl_dashL ()
|
||||
{
|
||||
func_file_conv "$1"
|
||||
if test -z "$lib_path"; then
|
||||
lib_path=$file
|
||||
else
|
||||
lib_path="$lib_path;$file"
|
||||
fi
|
||||
linker_opts="$linker_opts -LIBPATH:$file"
|
||||
}
|
||||
|
||||
# func_cl_dashl library
|
||||
# Do a library search-path lookup for cl
|
||||
func_cl_dashl ()
|
||||
{
|
||||
lib=$1
|
||||
found=no
|
||||
save_IFS=$IFS
|
||||
IFS=';'
|
||||
for dir in $lib_path $LIB
|
||||
do
|
||||
IFS=$save_IFS
|
||||
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.dll.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/$lib.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/lib$lib.a"; then
|
||||
found=yes
|
||||
lib=$dir/lib$lib.a
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS=$save_IFS
|
||||
|
||||
if test "$found" != yes; then
|
||||
lib=$lib.lib
|
||||
fi
|
||||
}
|
||||
|
||||
# func_cl_wrapper cl arg...
|
||||
# Adjust compile command to suit cl
|
||||
func_cl_wrapper ()
|
||||
{
|
||||
# Assume a capable shell
|
||||
lib_path=
|
||||
shared=:
|
||||
linker_opts=
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.[oO][bB][jJ])
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fo"$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fe"$file"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-I)
|
||||
eat=1
|
||||
func_file_conv "$2" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-I*)
|
||||
func_file_conv "${1#-I}" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-l)
|
||||
eat=1
|
||||
func_cl_dashl "$2"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-l*)
|
||||
func_cl_dashl "${1#-l}"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-L)
|
||||
eat=1
|
||||
func_cl_dashL "$2"
|
||||
;;
|
||||
-L*)
|
||||
func_cl_dashL "${1#-L}"
|
||||
;;
|
||||
-static)
|
||||
shared=false
|
||||
;;
|
||||
-Wl,*)
|
||||
arg=${1#-Wl,}
|
||||
save_ifs="$IFS"; IFS=','
|
||||
for flag in $arg; do
|
||||
IFS="$save_ifs"
|
||||
linker_opts="$linker_opts $flag"
|
||||
done
|
||||
IFS="$save_ifs"
|
||||
;;
|
||||
-Xlinker)
|
||||
eat=1
|
||||
linker_opts="$linker_opts $2"
|
||||
;;
|
||||
-*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||
func_file_conv "$1"
|
||||
set x "$@" -Tp"$file"
|
||||
shift
|
||||
;;
|
||||
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||
func_file_conv "$1" mingw
|
||||
set x "$@" "$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
if test -n "$linker_opts"; then
|
||||
linker_opts="-link$linker_opts"
|
||||
fi
|
||||
exec "$@" $linker_opts
|
||||
exit 1
|
||||
}
|
||||
|
||||
eat=
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand '-c -o'.
|
||||
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file 'INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
|
||||
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
|
||||
func_cl_wrapper "$@" # Doesn't return...
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
# So we strip '-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no '-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# '.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
|
@ -0,0 +1,201 @@
|
|||
dnl ---------------------------------------------------------------------------
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
dnl $Id: configure.in,v 1.9 2001/11/20 23:28:10 thosch Exp $
|
||||
dnl Copyright (C) 2001 Thomas Schulz
|
||||
dnl ---------------------------------------------------------------------------
|
||||
AC_INIT(src/ic35sync.c)
|
||||
AC_REVISION($Revision: 1.9 $ $Date: 2001/11/20 23:28:10 $)
|
||||
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl This is the only place where the package version appears
|
||||
dnl ---------------------------------------------------------------------------
|
||||
PACKAGE=ic35link
|
||||
VERSION=1.18.1
|
||||
ISODATE=2001-11-10
|
||||
AC_SUBST(ISODATE)
|
||||
AC_DEFINE_UNQUOTED(ISODATE, "$ISODATE", release date)
|
||||
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl Initialize automake
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl ??? AUTOMAKE_OPTIONS=no-dependencies
|
||||
AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
|
||||
AC_PREFIX_DEFAULT(/usr/local)
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl checks for needed compilers
|
||||
dnl ---------------------------------------------------------------------------
|
||||
AC_PROG_CC
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl option: disable logging and com-simulation
|
||||
dnl ---------------------------------------------------------------------------
|
||||
logandcomsim=yes
|
||||
AC_MSG_CHECKING(if we want logging and com-simulation)
|
||||
AC_ARG_ENABLE(
|
||||
logandcomsim,
|
||||
[ --enable-logandcomsim [default=yes] enable logging and com-simulation],
|
||||
logandcomsim="$enableval", logandcomsim="yes"
|
||||
)
|
||||
AC_MSG_RESULT($logandcomsim)
|
||||
if test "$logandcomsim" != "yes"; then
|
||||
AC_DEFINE_UNQUOTED(NO_LOGSIM, 1, disable log and com-simulation)
|
||||
fi
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl option: disable clean compiles
|
||||
dnl ---------------------------------------------------------------------------
|
||||
compiler_warnings=yes
|
||||
AC_MSG_CHECKING(if we want compiler warnings)
|
||||
AC_ARG_ENABLE(
|
||||
warnings,
|
||||
[ --enable-warnings [default=yes] enable gcc compiler warnings],
|
||||
compiler_warnings="$enableval", compiler_warnings="yes"
|
||||
)
|
||||
AC_MSG_RESULT($compiler_warnings)
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl option: ansi warnings
|
||||
dnl ---------------------------------------------------------------------------
|
||||
AC_MSG_CHECKING(whether to compile with strict ANSI)
|
||||
AC_ARG_ENABLE(
|
||||
ansi,
|
||||
[ --enable-ansi [default=no] enable gcc strict ansi checking],
|
||||
,
|
||||
[enable_ansi="no"])
|
||||
AC_MSG_RESULT($enable_ansi)
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl option: pedantic warnings
|
||||
dnl ---------------------------------------------------------------------------
|
||||
AC_MSG_CHECKING(whether to compile with pedantic warnings)
|
||||
AC_ARG_ENABLE(
|
||||
pedantic,
|
||||
[ --enable-pedantic [default=no] enable gcc pedantic checking],
|
||||
,
|
||||
[enable_pedantic="no"])
|
||||
AC_MSG_RESULT($enable_pedantic)
|
||||
|
||||
if test "$ac_cv_prog_CC" = gcc -o "$ac_cv_prog_CC" = g++; then
|
||||
if test $compiler_warnings = yes; then
|
||||
if echo "$CFLAGS" | grep "\-Wall" > /dev/null 2> /dev/null; then
|
||||
CFLAGS="$CFLAGS"
|
||||
else
|
||||
echo "updating CFLAGS with extra '-Wall' option"
|
||||
CFLAGS="$CFLAGS -Wall"
|
||||
fi
|
||||
|
||||
if echo "$CFLAGS" | grep "\-Wmissing-prototypes" > /dev/null 2> /dev/null; then
|
||||
CFLAGS="$CFLAGS"
|
||||
else
|
||||
echo "updating CFLAGS with extra '-Wmissing-prototypes' option"
|
||||
CFLAGS="$CFLAGS -Wmissing-prototypes"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$enable_ansi" = "yes"; then
|
||||
if echo "$CFLAGS" | grep "\-ansi" > /dev/null 2> /dev/null; then
|
||||
CFLAGS="$CFLAGS"
|
||||
else
|
||||
CFLAGS="$CFLAGS -ansi"
|
||||
echo "updating CFLAGS with extra '-ansi' option"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$enable_pedantic" = "yes"; then
|
||||
if echo "$CFLAGS" | grep "\-pedantic" > /dev/null 2> /dev/null; then
|
||||
CFLAGS="$CFLAGS"
|
||||
else
|
||||
CFLAGS="$CFLAGS -pedantic"
|
||||
echo "updating CFLAGS with extra '-pedantic' option"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl generate the config header
|
||||
dnl ---------------------------------------------------------------------------
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl Checks for programs.
|
||||
dnl ---------------------------------------------------------------------------
|
||||
AC_PROG_INSTALL
|
||||
dnl AC_PROG_CC was checked above already
|
||||
AC_PROG_YACC
|
||||
AC_PROG_AWK
|
||||
AC_PROG_LN_S
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl Checks for header files.
|
||||
dnl ---------------------------------------------------------------------------
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(fcntl.h malloc.h sys/ioctl.h unistd.h)
|
||||
AC_HEADER_TIME
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
dnl ---------------------------------------------------------------------------
|
||||
AC_C_CONST
|
||||
AC_TYPE_SIZE_T
|
||||
AC_HEADER_TIME
|
||||
AC_STRUCT_TM
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl Checks for library functions.
|
||||
dnl ---------------------------------------------------------------------------
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_FUNC_MEMCMP
|
||||
AC_TYPE_SIGNAL
|
||||
AC_FUNC_STRFTIME
|
||||
dnl ??? AC_CHECK_USLEEP
|
||||
dnl ??? AC_CHECK_ITIMER
|
||||
AC_FUNC_UTIME_NULL
|
||||
AC_FUNC_VPRINTF
|
||||
AC_CHECK_FUNCS(gettimeofday mktime select strdup strerror strspn strstr)
|
||||
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl Makefiles to create:
|
||||
dnl ---------------------------------------------------------------------------
|
||||
AC_OUTPUT(Makefile src/Makefile doc/Makefile)
|
||||
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl output our configuration
|
||||
dnl ---------------------------------------------------------------------------
|
||||
echo
|
||||
echo these are the options selected:
|
||||
echo
|
||||
if test "$USE_MAINTAINER_MODE" = "yes"; then
|
||||
echo " maintainer mode : YES"
|
||||
else
|
||||
echo " maintainer mode : NO"
|
||||
fi
|
||||
if test "$logandcomsim" = "yes"; then
|
||||
echo " log and com-simulation : YES"
|
||||
else
|
||||
echo " log and com-simulation : NO"
|
||||
fi
|
||||
if test "$compiler_warnings" = "yes"; then
|
||||
echo " gcc compiler warnings : YES"
|
||||
else
|
||||
echo " gcc compiler warnings : NO"
|
||||
fi
|
||||
if test "$enable_ansi" = "yes"; then
|
||||
echo " gcc compile with strict ansi : YES"
|
||||
else
|
||||
echo " gcc compile with strict ansi : NO"
|
||||
fi
|
||||
if test "$enable_pedantic" = "yes"; then
|
||||
echo " gcc compiler pedantic checking: YES"
|
||||
else
|
||||
echo " gcc compiler pedantic checking: NO"
|
||||
fi
|
||||
echo
|
|
@ -0,0 +1,6 @@
|
|||
ic35link for Debian
|
||||
------------------
|
||||
|
||||
This package currently "builds" on debian unstable but I won't recommend it at the current state.
|
||||
|
||||
-- crt0mega <crt0mega@c-r-t.tk> Tue, 15 Sep 2020 20:13:25 +0200
|
|
@ -0,0 +1,8 @@
|
|||
ic35link for Debian
|
||||
------------------
|
||||
|
||||
Currently, every modifications to convince gcc of building this package are managed with quilt.
|
||||
|
||||
|
||||
-- crt0mega <crt0mega@c-r-t.tk> Tue, 15 Sep 2020 20:13:25 +0200
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
ic35link (1.18.1-1) unstable; urgency=medium
|
||||
|
||||
* Initial release after adding compiler-workarounds and fixing some minor errors
|
||||
|
||||
-- crt0mega <crt0mega@c-r-t.tk> Tue, 15 Sep 2020 20:13:25 +0200
|
|
@ -0,0 +1,16 @@
|
|||
Source: ic35link
|
||||
Section: unknown
|
||||
Priority: optional
|
||||
Maintainer: crt0mega <crt0mega@c-r-t.tk>
|
||||
Build-Depends: debhelper-compat (= 12)
|
||||
Standards-Version: 4.5.0
|
||||
#Homepage: <insert the upstream URL, if relevant>
|
||||
#Vcs-Browser: https://salsa.debian.org/debian/ic35link
|
||||
#Vcs-Git: https://salsa.debian.org/debian/ic35link.git
|
||||
|
||||
Package: ic35link
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: Revived managing and syncing software for IC35
|
||||
This is a revival of the old ic35link software by Thomas Schulz.
|
||||
|
|
@ -0,0 +1 @@
|
|||
COPYING
|
|
@ -0,0 +1,3 @@
|
|||
ic35link-dbgsym_1.18.1-1_amd64.deb debug optional automatic=yes
|
||||
ic35link_1.18.1-1_amd64.buildinfo unknown optional
|
||||
ic35link_1.18.1-1_amd64.deb unknown optional
|
|
@ -0,0 +1,2 @@
|
|||
README.Debian
|
||||
README.source
|
|
@ -0,0 +1,20 @@
|
|||
Document: ic35link
|
||||
Title: Debian ic35link Manual
|
||||
Author: <insert document author here>
|
||||
Abstract: This manual describes what ic35link is
|
||||
and how it can be used to
|
||||
manage online manuals on Debian systems.
|
||||
Section: unknown
|
||||
|
||||
Format: debiandoc-sgml
|
||||
Files: /usr/share/doc/ic35link/ic35link.sgml.gz
|
||||
|
||||
Format: postscript
|
||||
Files: /usr/share/doc/ic35link/ic35link.ps.gz
|
||||
|
||||
Format: text
|
||||
Files: /usr/share/doc/ic35link/ic35link.text.gz
|
||||
|
||||
Format: HTML
|
||||
Index: /usr/share/doc/ic35link/html/index.html
|
||||
Files: /usr/share/doc/ic35link/html/*.html
|
|
@ -0,0 +1,3 @@
|
|||
shlibs:Depends=libc6 (>= 2.15)
|
||||
misc:Depends=
|
||||
misc:Pre-Depends=
|
|
@ -0,0 +1,16 @@
|
|||
--- a/src/datatxt.c
|
||||
+++ b/src/datatxt.c
|
||||
@@ -67,11 +67,11 @@
|
||||
++idx; /* increment rec.index */
|
||||
}
|
||||
get_ic35recdata( rec, NULL, &len );
|
||||
- fprintf(outfp,"File \"%s\" Record %3d IC35id=%08lX cflag=%02X length=%d\n",
|
||||
+ fprintf(outfp,"File \"%s\" Record %3d IC35id=%08lX cflag=%02X length=%ld\n",
|
||||
ic35fname(fileid), idx, ic35recid(rec), ic35recchg(rec), len);
|
||||
for ( fi = 0; fi < ic35fnflds( fileid ); ++fi ) {
|
||||
get_ic35recfld( rec, FILEfld(fileid,fi), &fld, &len );
|
||||
- fprintf( outfp, "f%d(%d)\t", fi, len );
|
||||
+ fprintf( outfp, "f%d(%ld)\t", fi, len );
|
||||
if ( len != 0 ) {
|
||||
fprintf( outfp, "\"" );
|
||||
for ( i = 0; i < len; ++i ) {
|
|
@ -0,0 +1,11 @@
|
|||
--- a/src/ic35mgr.c
|
||||
+++ b/src/ic35mgr.c
|
||||
@@ -519,7 +519,7 @@
|
||||
mmcget(ic35path, NULL);
|
||||
free(ic35path);
|
||||
break;
|
||||
- default:
|
||||
+ default:;
|
||||
}
|
||||
}
|
||||
rc = mmc_closedir( dirp );
|
|
@ -0,0 +1,14 @@
|
|||
Adding several $CFLAGs as a workaround for building this currently broken package with current gcc versions
|
||||
--- a/configure.in
|
||||
+++ b/configure.in
|
||||
@@ -116,6 +116,10 @@
|
||||
fi
|
||||
fi
|
||||
|
||||
+dnl ---------------------------------------------------------------------------
|
||||
+dnl Add several cflags as a workaround
|
||||
+dnl ---------------------------------------------------------------------------
|
||||
+CFLAGS="$CFLAGS -Wno-format-overflow -Wno-stringop-overflow -Wno-builtin-declaration-mismatch -Wno-aggressive-loop-optimizations -Wno-unused-result -Wno-pointer-to-int-cast"
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl generate the config header
|
|
@ -0,0 +1,3 @@
|
|||
gcc-build-workaround
|
||||
fix-formats
|
||||
fix-label
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/make -f
|
||||
# See debhelper(7) (uncomment to enable)
|
||||
# output every command that modifies files on the build system.
|
||||
#export DH_VERBOSE = 1
|
||||
|
||||
|
||||
# see FEATURE AREAS in dpkg-buildflags(1)
|
||||
#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
# see ENVIRONMENT in dpkg-buildflags(1)
|
||||
# package maintainers to append CFLAGS
|
||||
#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
|
||||
# package maintainers to append LDFLAGS
|
||||
#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
|
||||
|
||||
|
||||
%:
|
||||
dh $@ --with autoreconf
|
||||
|
||||
|
||||
# dh_make generated override targets
|
||||
# This is example for Cmake (See https://bugs.debian.org/641051 )
|
||||
#override_dh_auto_configure:
|
||||
# dh_auto_configure -- # -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)
|
||||
|
|
@ -0,0 +1 @@
|
|||
3.0 (quilt)
|
|
@ -0,0 +1,791 @@
|
|||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2018-03-07.03; # UTC
|
||||
|
||||
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by 'PROGRAMS ARGS'.
|
||||
object Object file output by 'PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputting dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
# Get the directory component of the given path, and save it in the
|
||||
# global variables '$dir'. Note that this directory component will
|
||||
# be either empty or ending with a '/' character. This is deliberate.
|
||||
set_dir_from ()
|
||||
{
|
||||
case $1 in
|
||||
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
|
||||
*) dir=;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Get the suffix-stripped basename of the given path, and save it the
|
||||
# global variable '$base'.
|
||||
set_base_from ()
|
||||
{
|
||||
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
|
||||
}
|
||||
|
||||
# If no dependency file was actually created by the compiler invocation,
|
||||
# we still have to create a dummy depfile, to avoid errors with the
|
||||
# Makefile "include basename.Plo" scheme.
|
||||
make_dummy_depfile ()
|
||||
{
|
||||
echo "#dummy" > "$depfile"
|
||||
}
|
||||
|
||||
# Factor out some common post-processing of the generated depfile.
|
||||
# Requires the auxiliary global variable '$tmpdepfile' to be set.
|
||||
aix_post_process_depfile ()
|
||||
{
|
||||
# If the compiler actually managed to produce a dependency file,
|
||||
# post-process it.
|
||||
if test -f "$tmpdepfile"; then
|
||||
# Each line is of the form 'foo.o: dependency.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# $object: dependency.h
|
||||
# and one to simply output
|
||||
# dependency.h:
|
||||
# which is needed to avoid the deleted-header problem.
|
||||
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
|
||||
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
|
||||
} > "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
}
|
||||
|
||||
# A tabulation character.
|
||||
tab=' '
|
||||
# A newline character.
|
||||
nl='
|
||||
'
|
||||
# Character ranges might be problematic outside the C locale.
|
||||
# These definitions help.
|
||||
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
lower=abcdefghijklmnopqrstuvwxyz
|
||||
digits=0123456789
|
||||
alpha=${upper}${lower}
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Avoid interferences from the environment.
|
||||
gccflag= dashmflag=
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
cygpath_u="cygpath -u -f -"
|
||||
if test "$depmode" = msvcmsys; then
|
||||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
if test "$depmode" = msvc7msys; then
|
||||
# This is just like msvc7 but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvc7
|
||||
fi
|
||||
|
||||
if test "$depmode" = xlc; then
|
||||
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
|
||||
gccflag=-qmakedep=gcc,-MF
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||
## the command line argument order; so add the flags where they
|
||||
## appear in depend2.am. Note that the slowdown incurred here
|
||||
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||
*) set fnord "$@" "$arg" ;;
|
||||
esac
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
done
|
||||
"$@"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
|
||||
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
|
||||
## (see the conditional assignment to $gccflag above).
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say). Also, it might not be
|
||||
## supported by the other compilers which use the 'gcc' depmode.
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The second -e expression handles DOS-style file names with drive
|
||||
# letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the "deleted header file" problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
## Some versions of gcc put a space before the ':'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||
## to the object. Take care to not repeat it in the output.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
|
||||
| tr "$nl" ' ' >> "$depfile"
|
||||
echo >> "$depfile"
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
xlc)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
tcc)
|
||||
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
|
||||
# FIXME: That version still under development at the moment of writing.
|
||||
# Make that this statement remains true also for stable, released
|
||||
# versions.
|
||||
# It will wrap lines (doesn't matter whether long or short) with a
|
||||
# trailing '\', as in:
|
||||
#
|
||||
# foo.o : \
|
||||
# foo.c \
|
||||
# foo.h \
|
||||
#
|
||||
# It will put a trailing '\' even on the last line, and will use leading
|
||||
# spaces rather than leading tabs (at least since its commit 0394caf7
|
||||
# "Emit spaces for -MD").
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
|
||||
# We have to change lines of the first kind to '$object: \'.
|
||||
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
|
||||
# And for each line of the second kind, we have to emit a 'dep.h:'
|
||||
# dummy dependency, to avoid the deleted-header problem.
|
||||
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
## The order of this option in the case statement is important, since the
|
||||
## shell code in configure will try each of these formats in the order
|
||||
## listed in this file. A plain '-MD' option would be understood by many
|
||||
## compilers, so we must ensure this comes after the gcc and icc options.
|
||||
pgcc)
|
||||
# Portland's C compiler understands '-MD'.
|
||||
# Will always output deps to 'file.d' where file is the root name of the
|
||||
# source file under compilation, even if file resides in a subdirectory.
|
||||
# The object file name does not affect the name of the '.d' file.
|
||||
# pgcc 10.2 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using '\' :
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
set_dir_from "$object"
|
||||
# Use the source, not the object, to determine the base name, since
|
||||
# that's sadly what pgcc will do too.
|
||||
set_base_from "$source"
|
||||
tmpdepfile=$base.d
|
||||
|
||||
# For projects that build the same source file twice into different object
|
||||
# files, the pgcc approach of using the *source* file root name can cause
|
||||
# problems in parallel builds. Use a locking strategy to avoid stomping on
|
||||
# the same $tmpdepfile.
|
||||
lockdir=$base.d-lock
|
||||
trap "
|
||||
echo '$0: caught signal, cleaning up...' >&2
|
||||
rmdir '$lockdir'
|
||||
exit 1
|
||||
" 1 2 13 15
|
||||
numtries=100
|
||||
i=$numtries
|
||||
while test $i -gt 0; do
|
||||
# mkdir is a portable test-and-set.
|
||||
if mkdir "$lockdir" 2>/dev/null; then
|
||||
# This process acquired the lock.
|
||||
"$@" -MD
|
||||
stat=$?
|
||||
# Release the lock.
|
||||
rmdir "$lockdir"
|
||||
break
|
||||
else
|
||||
# If the lock is being held by a different process, wait
|
||||
# until the winning process is done or we timeout.
|
||||
while test -d "$lockdir" && test $i -gt 0; do
|
||||
sleep 1
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
fi
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
trap - 1 2 13 15
|
||||
if test $i -le 0; then
|
||||
echo "$0: failed to acquire lock after $numtries attempts" >&2
|
||||
echo "$0: check lockdir '$lockdir'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form `foo.o: dependent.h',
|
||||
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp2)
|
||||
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||
# compilers, which have integrated preprocessors. The correct option
|
||||
# to use with these is +Maked; it writes dependencies to a file named
|
||||
# 'foo.d', which lands next to the object file, wherever that
|
||||
# happens to be.
|
||||
# Much of this is similar to the tru64 case; see comments there.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir.libs/$base.d
|
||||
"$@" -Wc,+Maked
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
"$@" +Maked
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add 'dependent.h:' lines.
|
||||
sed -ne '2,${
|
||||
s/^ *//
|
||||
s/ \\*$//
|
||||
s/$/:/
|
||||
p
|
||||
}' "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in 'foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# Libtool generates 2 separate objects for the 2 libraries. These
|
||||
# two compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
|
||||
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
# Same post-processing that is required for AIX mode.
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
msvc7)
|
||||
if test "$libtool" = yes; then
|
||||
showIncludes=-Wc,-showIncludes
|
||||
else
|
||||
showIncludes=-showIncludes
|
||||
fi
|
||||
"$@" $showIncludes > "$tmpdepfile"
|
||||
stat=$?
|
||||
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The first sed program below extracts the file names and escapes
|
||||
# backslashes for cygpath. The second sed program outputs the file
|
||||
# name when reading, but also accumulates all include files in the
|
||||
# hold buffer in order to output them again at the end. This only
|
||||
# works with sed implementations that can handle large buffers.
|
||||
sed < "$tmpdepfile" -n '
|
||||
/^Note: including file: *\(.*\)/ {
|
||||
s//\1/
|
||||
s/\\/\\\\/g
|
||||
p
|
||||
}' | $cygpath_u | sort -u | sed -n '
|
||||
s/ /\\ /g
|
||||
s/\(.*\)/'"$tab"'\1 \\/p
|
||||
s/.\(.*\) \\/\1:/
|
||||
H
|
||||
$ {
|
||||
s/.*/'"$tab"'/
|
||||
G
|
||||
p
|
||||
}' >> "$depfile"
|
||||
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7msys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for ':'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this sed invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no eat=no
|
||||
for arg
|
||||
do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
if test $eat = yes; then
|
||||
eat=no
|
||||
continue
|
||||
fi
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-arch)
|
||||
eat=yes ;;
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
# makedepend may prepend the VPATH from the source file name to the object.
|
||||
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process the last invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed '1,2d' "$tmpdepfile" \
|
||||
| tr ' ' "$nl" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E \
|
||||
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
| sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E 2>/dev/null |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||
echo "$tab" >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvcmsys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
|
@ -0,0 +1,2 @@
|
|||
Makefile
|
||||
Makefile.in
|
|
@ -0,0 +1,5 @@
|
|||
/.cvsignore/1.1/Sun Feb 4 22:55:23 2001//
|
||||
/Makefile.am/1.2/Mon Feb 19 01:10:46 2001//
|
||||
/ic35mgr.txt/1.10/Sat Feb 3 18:39:07 2001//
|
||||
/ic35sync.txt/1.10/Sun Dec 3 21:10:00 2000//
|
||||
D
|
|
@ -0,0 +1 @@
|
|||
ic35link/doc
|
|
@ -0,0 +1 @@
|
|||
:pserver:anonymous@ic35link.cvs.sourceforge.net:/cvsroot/ic35link
|
|
@ -0,0 +1,17 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
## $Id: Makefile.am,v 1.2 2001/02/19 01:10:46 tsch Rel $
|
||||
## Copyright (C) 2001 Thomas Schulz
|
||||
##
|
||||
## automakefile for ic35link/doc
|
||||
|
||||
pkgdata_DATA = \
|
||||
ic35sync.txt \
|
||||
ic35mgr.txt
|
||||
|
||||
EXTRA_DIST = $(pkgdata_DATA)
|
||||
|
||||
if MAINTAINER_MODE
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
else
|
||||
MAINTAINERCLEANFILES =
|
||||
endif
|
|
@ -0,0 +1,783 @@
|
|||
$Id: ic35mgr.txt,v 1.10 2001/02/03 18:39:07 tsch Rel $
|
||||
IC35 Manager Protokoll
|
||||
======================
|
||||
|
||||
Inhalt
|
||||
------
|
||||
IC35-Manager Operationen
|
||||
IC35-Manager Protokoll
|
||||
Basiskommandos
|
||||
Datenblock senden PC->IC35
|
||||
Datenblock empfangen PC<-IC35
|
||||
Verbindungsaufbau
|
||||
Verbindungsabbau
|
||||
IC35 Datensicherung
|
||||
IC35 Datenwiederherstellung
|
||||
Protokoll MMCard-Operationen
|
||||
MMCard Operationen
|
||||
MMCard Status
|
||||
MMCard Label
|
||||
MMCard Directory Operationen
|
||||
MMCard Directory Open
|
||||
MMCard Directory Length
|
||||
MMCard Directory Entry
|
||||
MMCard Directory Close
|
||||
MMCard File Operationen
|
||||
MMCard File Open
|
||||
MMCard File Status
|
||||
MMCard File Read
|
||||
MMCard File Write
|
||||
MMCard File Close
|
||||
MMCard File Delete
|
||||
Anhang: Logfiles der Protokoll-Analyse
|
||||
|
||||
|
||||
??? Unklarheiten ueber das IC35 Manager Protokoll sind wie hier mit ???
|
||||
??? am Zeilenanfang markiert.
|
||||
|
||||
|
||||
IC35-Manager Operationen
|
||||
------------------------
|
||||
- Verbindungsaufbau mit IC35
|
||||
- Welcome
|
||||
- Identifikation und Status IC35
|
||||
- Verbindung zum IC35 trennen
|
||||
- Sichern, Wiederherstellen
|
||||
- IC35 Datensicherung nach database.org
|
||||
- IC35 Datenwiederhestellung aus database.org
|
||||
- MMCard Operationen
|
||||
- Status, Inhalt IC35 MMCard
|
||||
- Datei Transfer nach IC35 MMCard
|
||||
- Datei Transfer von IC35 MMCard
|
||||
- Datei loeschen in IC35 MMCard
|
||||
(noch) nicht analysiert wurden:
|
||||
??? - Transfer Applikationsprogramm ins IC35
|
||||
??? - Applikationsprogramm im IC35 loeschen
|
||||
??? - Transfer einer Grafik-Bitmapdatei ins IC35
|
||||
??? - Transfer einer MIDI-Datei ins IC35
|
||||
|
||||
Fortschrittsanzeigen des IC35 Manager unter Windows:
|
||||
- Zugriff auf IC35 Info ..
|
||||
- Zugriff erfolgreich
|
||||
- MMCard1 wird getestet
|
||||
- ..\IC35
|
||||
- ..\APP
|
||||
- ..\<*.APP ..>
|
||||
- ..\<2000 ..>
|
||||
- MMCard2 wird getested
|
||||
- keine MMCard2 vorhanden
|
||||
Standardablauf IC35 Manager unter Windows
|
||||
- Verbindungsaufbau mit IC35
|
||||
ausgeloest durch MouseClick "connect" am IC35 Manager
|
||||
fordert Knopfdruck an SyncStation
|
||||
- Status, Inhalt IC35 MMCard
|
||||
- Verbindung zum IC35 trennen
|
||||
ausgeloest durch MouseClick "disconnect" am IC35 Manager
|
||||
|
||||
|
||||
IC35-Manager Protokoll
|
||||
----------------------
|
||||
Die Leitungsparameter fuer die Kommunikation zwischen PC und
|
||||
IC35 sind Baudrate 115200, No parity, 8 databits, 2 stopbits.
|
||||
Die Basisoperationen des IC35-Manager Protokolls sind
|
||||
- Basiskommando mit Bestaetigung
|
||||
- Datenblock senden und Verifikation mit Pruefsumme
|
||||
- Datenblock emfangen und Verifikation mit Pruefsumme
|
||||
|
||||
Basiskommandos
|
||||
Einige Basiskommandos des IC35-Manager Protokolls bestehen
|
||||
jeweils aus einem 1byte-Kommando vom PC an den IC35, gefolgt
|
||||
von einer 1byte-Antwort vom IC35 an den PC. Wenn die Antwort
|
||||
vom IC35 ausbleibt, wird das Kommando wiederholt.
|
||||
Kommunikation PC -> IC35, PC <- IC35:
|
||||
-> command
|
||||
timeout 0.5 sec
|
||||
-> command
|
||||
<- response
|
||||
Die beobachteten Basiskommandos sind:
|
||||
Verbindungsabbau
|
||||
-> 01
|
||||
<- 90
|
||||
Reset Manager-Protokoll
|
||||
-> 09
|
||||
<- 90
|
||||
Identifikation
|
||||
-> 10
|
||||
<- 90
|
||||
<- "DCS_SDK" 00
|
||||
IC35 Datensicherung
|
||||
-> 13
|
||||
<- 90
|
||||
IC35 Datenwiederherstellung
|
||||
-> 14
|
||||
<- 90
|
||||
-> 70
|
||||
<- C0
|
||||
Einleitung MMCard-Operation
|
||||
-> 15
|
||||
<- 90
|
||||
Info Datensicherung
|
||||
-> 18
|
||||
<- 90
|
||||
<- 30 31 32 38
|
||||
Start des Verbindungsaufbaus
|
||||
-> 40
|
||||
<- 80
|
||||
Positive Quittung
|
||||
-> 60
|
||||
<- A0
|
||||
Negative Quittung
|
||||
-> 62
|
||||
<- A0
|
||||
Dieser Protokollablauf der Basiskommandos ist mit Mcmdrsp()
|
||||
in mgrproto.c implementiert.
|
||||
|
||||
Datenblock senden PC->IC35
|
||||
Bei IC35-Datenwiederherstellung und MMCard-Operationen werden
|
||||
Datenbloecke vom PC an den IC35 gesendet und die Uebertragung
|
||||
mit einer Pruefsumme verifiziert und ggf. wiederholt.
|
||||
Bei den MMCard-Operationen wird die Laenge des Datenblocks an
|
||||
den IC35 gesendet und vom IC35 bestaetigt. Vor dem Senden der
|
||||
Laenge muss 10 Millisekunden gewartet werden.
|
||||
Bei IC35-Datenwiederherstellung unterbleibt dies, weil die
|
||||
Laenge (136 oder 16384 Bytes) a priori feststeht.
|
||||
Beim Senden des Datenblocks muss erfahrungsgemaess mindestens
|
||||
alle 29 Bytes jeweils 10 Millisekunden gewartet werden. Offenbar
|
||||
ist der IC35 nicht faehig, den Datenblock bei 115200 Baud ohne
|
||||
diese Verzoegerungen korrekt zu empfangen.
|
||||
Auf die Pruefsumme muss bis zu 10.0 Sekunden gewartet werden.
|
||||
Kommunikation PC -> IC35, PC <- IC35:
|
||||
-> nn_nn Laenge des Datenblocks, niederwertiges Byte zuerst
|
||||
<- E0 Empgangsbestaetigung der Laenge
|
||||
-> (Datenblock von nn_nn Bytes)
|
||||
<- cc_cc Pruefsumme des Datenblocks, niederwertiges Byte zuerst
|
||||
Die Pruefsumme ist die arithmetische Summe aller Bytes des
|
||||
Datenblocks abgeschnitten auf 16 Bit. Wenn Datenblock-Bytes
|
||||
verloren gehen (Overrun error im IC35) oder verfaelscht werden,
|
||||
trifft die Pruefsumme vom IC35 erst ca. 8.2 Sekunden nach dem
|
||||
Versand des Datenblocks ein.
|
||||
Bei unstimmiger Pruefsumme 'cc_cc' wird negativ quittiert:
|
||||
-> 62 negative Quittung
|
||||
<- A0 Empfangsbestaetigung der Quittung
|
||||
und der Datenblock erneut an IC35 gesendet.
|
||||
Bei uebereinstimmender Pruefsumme 'cc_cc' wird positiv quittiert:
|
||||
-> 60 positive Quittung
|
||||
<- A0 Empfangsbestaetigung der Quittung
|
||||
Wenn die Empfangsbestaetigung der Quittung vom IC35 ausbleibt, wird
|
||||
die positive oder negative Quittung wiederholt.
|
||||
Dieser Protokollablauf ist mit Msendblk() in mgrproto.c implementiert.
|
||||
|
||||
Datenblock empfangen PC<-IC35
|
||||
Bei IC35-Datensicherung und MMCard-Operationen werden Datenbloecke
|
||||
vom IC35 am PC empfangen und die Uebertragung mit einer Pruefsumme
|
||||
verifiziert und ggf. wiederholt.
|
||||
Bei den MMCard-Operationen wird die Laenge des Datenblocks vom
|
||||
IC35 empfangen und bestaetigt. Auf die Laenge muss 3.5 Sekunden
|
||||
gewartet werden.
|
||||
Bei IC35-Datensicherung unterbleibt dies, weil die Laenge (136 oder
|
||||
16384 Bytes) a priori feststeht.
|
||||
Kommunikation PC -> IC35, PC <- IC35:
|
||||
<- nn_nn Laenge des Datenblocks, niederwertiges Byte zuerst
|
||||
-> E0 Empgangsbestaetigung der Laenge
|
||||
<- (Datenblock von nn_nn Bytes)
|
||||
<- cc_cc Pruefsumme des Datenblocks, niederwertiges Byte zuerst
|
||||
Bei unstimmiger Pruefsumme 'cc_cc' oder kuerzerer Laenge als
|
||||
angekuendigt wird negativ quittiert:
|
||||
-> 62 negative Quittung
|
||||
<- A0 Empfangsbestaetigung der Quittung
|
||||
und der Datenblock wird erneut vom IC35 empfangen.
|
||||
Bei uebereinstimmender Pruefsumme 'cc_cc' wird positiv quittiert:
|
||||
-> 60 positive Quittung
|
||||
<- A0 Empfangsbestaetigung der Quittung
|
||||
Wenn die Empfangsbestaetigung der Quittung vom IC35 ausbleibt,
|
||||
wird die positive oder negative Quittung wiederholt.
|
||||
Dieser Protokollablauf ist mit Mrecvblk() in mgrproto.c implementiert.
|
||||
|
||||
|
||||
Verbindungsaufbau
|
||||
-----------------
|
||||
1. Welcome Phase
|
||||
- Der PC sendet wiederholt einzelne Zeichen "@" (hex 40) bis vom
|
||||
IC35 "WELCOME" (hex 57 45 4C 43 4F 4D 45) empfangen wird.
|
||||
Dies passiert durch Druecken des Sync-Station Knopfs.
|
||||
- Der PC sendet noch einmal ein Zeichen "@" (hex 40), der IC35
|
||||
antwortet mit einem Byte hex 80.
|
||||
Kommunikation PC -> IC35, PC <- IC35
|
||||
-> 40
|
||||
timeout 1.15 sec
|
||||
-> 40
|
||||
sync-station button
|
||||
<- 57 45 4C 43 4F 4D 45
|
||||
W E L C O M E
|
||||
2. Basiskommando "Start Verbindungsaufbau"
|
||||
-> 40
|
||||
<- 80
|
||||
3. Basiskommando "Reset"
|
||||
-> 09
|
||||
<- 90
|
||||
4. Basiskommando "Identifikation"
|
||||
-> 10
|
||||
<- 90
|
||||
<- 44 43 53 5F 53 44 4B 00
|
||||
D C S _ S D K .
|
||||
5. optional Empfang des Statusblocks vom IC35
|
||||
-> FF
|
||||
<- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...
|
||||
... FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
|
||||
Block von 16400 Bytes
|
||||
enthaelt u.a. Applikationsnamen, Email,SMS config, ..
|
||||
6. Initialisierung
|
||||
-> 50
|
||||
<- 90 or timeout 0.1 sec
|
||||
??? Beim Initialisierunskommando wurde keine Antwort beobachtet.
|
||||
??? Es wird 100 Millisekunden auf etwaige Antwort vom IC35 gewartet
|
||||
??? und diese verworfen, um sie nicht irrtuemlich fuer eine Antwort
|
||||
??? auf ein nachfolgendes Basiskommando zu halten.
|
||||
Der IC35 braucht mindestens 10 Millisekunden Ruhe, bis er zu
|
||||
weiteren Aktionen bereit ist. (Ansonsten muss das nachfolgende
|
||||
erste Basiskommando wiederholt werden.)
|
||||
|
||||
|
||||
Verbindungsabbau
|
||||
----------------
|
||||
1. Basiskommando "Reset"
|
||||
-> 09
|
||||
timeout 1.0 sec
|
||||
-> 09
|
||||
<- 90
|
||||
2. Basiskommando "Verbindungsabbau"
|
||||
-> 01
|
||||
timeout 1.0 sec
|
||||
-> 01
|
||||
<- 90
|
||||
|
||||
|
||||
IC35 Datensicherung
|
||||
-------------------
|
||||
Der Ablauf der Datensicherung mit den Protokoll-Basisoperationen
|
||||
(s.o "IC35-Manager Protokoll") ist:
|
||||
1. Basiskommmando "IC35 Datensicherung"
|
||||
-> 13
|
||||
<- 90
|
||||
2. Empfang des Kopfblocks (136 Bytes) vom IC35
|
||||
<- B5 03 00 A2 01 00 F1 .. headblock 136 bytes
|
||||
<- 98 0D checksum
|
||||
-> 60 positive acknowledge
|
||||
<- A0 got ack
|
||||
Hier und unten ist jeweils nur die positive Quittung erwaehnt,
|
||||
bei falscher Pruefsumme oder Blocklaenge wird jeweils negativ
|
||||
quittiert und der Kopf- oder Daten-Block wiederholt.
|
||||
3. Empfang von 26 Datenblocks (je 16384 Bytes) vom IC35
|
||||
<- A0 09 00 40 01 00 00 .. datablock 16384 bytes
|
||||
<- C0 4C checksum
|
||||
-> 60 positive acknowledge
|
||||
<- A0 got ack
|
||||
4. Zweimal Basiskommando "Info Datensicherung"
|
||||
-> 18 command info-1
|
||||
timeout 1.0 sec
|
||||
-> 18 command info-1
|
||||
<- 90 response got command
|
||||
<- 30 31 32 38 info-1
|
||||
-> 18 command info-2
|
||||
timeout 0.5 sec
|
||||
-> 18 command info-2
|
||||
<- 90 response got command
|
||||
<- 30 31 32 38 info-1
|
||||
??? Der Inhalt der info response 30 31 32 38 = "0128" aehnelt sehr
|
||||
??? der Firmware-Version "1.28" des IC35, es ist jedoch noch unklar,
|
||||
??? ob diese Aehnlichkeit realen Gehalt hat.
|
||||
Alle Empfangsdaten der Datensicherung werden gespeichert in der
|
||||
Datei 'database.org', dies sind 426128 = 136 + 26*16384 + 4 +4
|
||||
Bytes insgesamt (headblock, 26 datablocks, 2 infoblocks).
|
||||
|
||||
|
||||
IC35 Datenwiederherstellung
|
||||
---------------------------
|
||||
Der Ablauf der Datenwiederherstellung mit den Protokoll-Basis-
|
||||
operationen (s.o "IC35-Manager Protokoll") ist:
|
||||
1. Zweimal Basiskommando "Info Datensicherung"
|
||||
-> 18 command info-1
|
||||
timeout 1.0 sec
|
||||
-> 18 command info-1
|
||||
<- 90 response got command
|
||||
<- 30 31 32 38 info-1
|
||||
-> 18 command info-2
|
||||
timeout 0.5 sec
|
||||
-> 18 command info-2
|
||||
<- 90 response got command
|
||||
<- 30 31 32 38 info-1
|
||||
Die beiden Antworten 30 31 32 38 werden mit den Eintraegen am
|
||||
Ende der Datei 'database.org' verglichen. Bei Uebereinstimmung
|
||||
wird die Datenwiederherstellung fortgesetzt, andernfalls wird
|
||||
sie abgebrochen.
|
||||
2. Basiskommmandos "IC35 Datenwiederherstellung"
|
||||
-> 14 command restore-1
|
||||
timeout 1.0 sec
|
||||
-> 14 command restore-1
|
||||
<- 90 response got command
|
||||
-> 70 command restore-2
|
||||
<- C0 response got restore-2
|
||||
3. Senden des Kopfblocks (136 Bytes) an IC35
|
||||
-> AD 03 00 9A 01 00 2B .. headblock 136 bytes
|
||||
<- 5B 0D checksum
|
||||
-> 60 positive acknowledge
|
||||
<- A0 response got ack
|
||||
4. Senden von 26 Datenblocks (je 16384 Bytes) vom IC35
|
||||
Auf die Pruefsumme muss bis zu 10.0 sec gewartet werden.
|
||||
-> A0 09 92 50 01 00 00 .. datablock 16384 bytes
|
||||
<- 4D F3 checksum
|
||||
-> 60 positive acknowledge
|
||||
<- A0 response got ack
|
||||
5. Basiskommando "Reset Manager-Protokoll"
|
||||
-> 09 command reset
|
||||
timeout 1.0 sec
|
||||
-> 09 command reset
|
||||
timeout 1.0 sec
|
||||
-> 09 command reset
|
||||
timeout 1.0 sec
|
||||
-> 09 command reset
|
||||
timeout 0.5 sec
|
||||
-> 09 command reset
|
||||
<- 90 response got command
|
||||
Wie oben sind die Inhalte von Kopf- und Daten-Blocks Beispiele
|
||||
und es ist jeweils nur die positive Quittung aufgefuehrt, bei
|
||||
falscher Pruefsumme wird jeweils negativ quittiert und der Kopf-
|
||||
oder Daten-Block wiederholt.
|
||||
Insgesamt werden 426120 = 136 + 26*16384 Bytes uebertragen, d.h.
|
||||
ein Kopfblock von 136 Bytes und 26 Datenblocks mit 16384 Bytes.
|
||||
Die 2 bei der Datensicherung empfangenen 'infoblocks' von je 4
|
||||
Bytes werden nicht an IC35 gesendet.
|
||||
??? Bei der Datenwiederherstellung werden Datum und Uhrzeit sowie
|
||||
??? Telefontyp auf Defaultwerte zurueckgesetzt! Sie muessen manuell
|
||||
??? korrigiert werden!
|
||||
|
||||
|
||||
Protokoll MMCard-Operationen
|
||||
----------------------------
|
||||
Der allgemeine Ablauf der MMCard-Operationen mit den Protokoll
|
||||
Basisoperationen (s.o "IC35-Manager Protokoll") ist:
|
||||
1. Basiskommando "MMCard-Operation"
|
||||
-> 15 command mmcard
|
||||
<- 90 got command
|
||||
Vor dem Senden der Blocklaenge des Kommandoblocks muss 10 msec
|
||||
gewartet werden.
|
||||
2. Senden des MMCard Kommandoblocks
|
||||
-> nn_nn block length
|
||||
<- E0 got length
|
||||
-> (cmdblock of nn_nn bytes)
|
||||
<- cc_cc got cmdblock, checksum is cc_cc (arithmetic, LSB first)
|
||||
Bei unstimmiger Pruefsumme 'cc_cc' wird negativ quittiert:
|
||||
-> 62 neg.ack
|
||||
<- A0 got neg.ack, send block again
|
||||
und der cmdblock erneut an IC35 gesendet.
|
||||
Bei uebereinstimmender Pruefsumme 'cc_cc' wird positiv quittiert:
|
||||
-> 60 pos.ack
|
||||
<- A0 got pos.ack
|
||||
3. Empfang des MMCard Antwortblocks
|
||||
<- nn_nn block length
|
||||
-> E0 got length
|
||||
<- (rspblock of nn_nn bytes)
|
||||
<- cc_cc checksum of rspblock is cc_cc (arithmetic, LSB first)
|
||||
Bei unstimmiger Pruefsumme 'cc_cc' wird negativ quittiert:
|
||||
-> 62 neg.ack
|
||||
<- A0 got neg.ack
|
||||
und der rspblock wird erneut vom IC35 empfangen.
|
||||
Bei uebereinstimmender Pruefsumme 'cc_cc' wird positiv quittiert:
|
||||
-> 60 pos.ack
|
||||
<- A0 got pos.ack
|
||||
|
||||
|
||||
MMCard Operationen
|
||||
------------------
|
||||
Im "IC35 Software Development Kit API Reference Guide" (ic35_api.pdf
|
||||
aus ic35_prog.zip) sind unter "13. Multi Media Card File Operations"
|
||||
beschrieben. Sie entsprechen weitgehend den MMCard PDUs der Protokoll
|
||||
Analyse. Zu den mit "???" markierten Funktionen wurden keine PDUs
|
||||
beobachtet, die PDU command codes sind reine Vermutung.
|
||||
|
||||
IC35 SDK API Funktion mgrtrans.c PDU command code
|
||||
+-----------------------+---------------------------------------------
|
||||
minitialCard mmc_status 20 "MMCard1" 00
|
||||
??? mFormat - 32 ???
|
||||
??? mSetCardLabel - 33 ???
|
||||
mGetCardLabel mmc_label 34 "MMCard1" 00
|
||||
??? mGetCardInfo - 35 ???
|
||||
mOpenFile mmc_openfile 22 mm mm "MMCard1\FILE.EXT" 00
|
||||
??? mSetFilePointer - 25 ???
|
||||
mWriteToFile mmc_writefile 23 ...
|
||||
mReadFromFile mmc_readfile 24 ...
|
||||
mGetFileInfo mmc_statfile 26 ...
|
||||
mCloseFile mmc_closefile 27 ...
|
||||
??? mRenFile - 21 ???
|
||||
mDeleteFile mmc_delfile 28 "MMCard1\FILE.EXT" 00
|
||||
mOpenDirectory mmc_opendir 2A mm mm "MMCard1\IC35" 00
|
||||
mGetDirectorySubItemNum mmc_opendir 2B ...
|
||||
mGetDirectorySubItem mmc_readdir 2C ...
|
||||
??? mGetDirectoryInfo - 2D ???
|
||||
mCloseDirectory mmc_closedir 2E ...
|
||||
??? mRenDirectory - 29 ???
|
||||
??? mDeleteDirectory - 2F ???
|
||||
|
||||
MMCard Status
|
||||
-> command status "MMCard1"
|
||||
20 4D 4D 43 61 72 64 31 00
|
||||
cmd M M C a r d 1 nul
|
||||
<- response MMCard OK
|
||||
01 00
|
||||
<- response MMCard not present
|
||||
FF FF
|
||||
|
||||
MMCard Label
|
||||
-> command label "MMCard1"
|
||||
34 4D 4D 43 61 72 64 31 00
|
||||
. M M C a r d 1 .
|
||||
cmd mcard-id____________ nul
|
||||
<- reponse MMCard label
|
||||
01 00 00 4D 4D 43 61 72 64 31 00 20 20 20 00 00 00 00 00 00 00 00 48
|
||||
. . . M M C a r d 1 . . . . . . . . . . . . H
|
||||
ok label___________________________ ??
|
||||
|
||||
MMCard Directory Operationen
|
||||
MMCard Directory Open empfaengt vom IC35 einen 'dirstat' Block,
|
||||
welcher in allen folgenden Operationen jeweils an den IC35
|
||||
gesendet und vom IC35 aktualisert wieder empfangen wird. Die
|
||||
Details ueber den 'dirstat' Block wurden "Mmc.h" aus dem IC35
|
||||
SoftwareDevelopmentKit entnommen, offenbar entsprechen sie
|
||||
dem uebertragenen 'dirstat' Block. Beispiele:
|
||||
Beispiel-1 "MMCard1" rootdir:
|
||||
5F 00 00 00 00 00 00 00 00 00 01 00 00 00
|
||||
sect_ clust sec_o dir_o sclst fileptr____
|
||||
00 00 00 00 FF 00 00 00 00 20 00 FE 01
|
||||
filesize___ cn cclst cclsn csecn rsrvd
|
||||
Beispiel-2 "MMCard1\IC35\APP"
|
||||
00 00 02 00 00 00 40 00 15 00 01 00 00 00
|
||||
sect_ clust sec_o dir_o sclst fileptr____
|
||||
00 00 00 00 FF 15 00 00 00 20 00 FE 01
|
||||
filesize___ cn cclst cclsn csecn rsrvd
|
||||
MMCard Directory Open
|
||||
Beispiel-1 "MMCard1" rootdir
|
||||
-> command opendir "MMCard1"
|
||||
2A 01 00 4D 4D 43 61 72 64 31 00
|
||||
. . . M M C a r d 1 .
|
||||
cmd dirpath="MMCard1"___ nul
|
||||
<- response
|
||||
01 00
|
||||
ok
|
||||
5F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
dirstat________________________________________
|
||||
00 00 00 00 00 00 00 00 00 FE 01
|
||||
_________________________dirstat
|
||||
Beispiel-2 "MMCard1\IC35\APP"
|
||||
-> command opendir "MMCard1
|
||||
2A 01 00 4D 4D 43 61 72 64 31 5C 49 43 33 35 5C 41 50 50 00
|
||||
. . . M M C a r d 1 \ I C 3 5 \ A P P .
|
||||
cmd dirpath="MMCard1\IC35\APP"_____________________ nul
|
||||
<- response
|
||||
01 00
|
||||
ok
|
||||
00 00 02 00 00 00 40 00 15 00 00 00 00 00 00 00
|
||||
dirstat________________________________________
|
||||
00 00 00 15 00 00 00 00 00 FE 01
|
||||
_________________________dirstat
|
||||
MMCard Directory Length
|
||||
Beispiel-1 "MMCard1" rootdir
|
||||
-> command dirlen
|
||||
2B
|
||||
cmd
|
||||
5F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
dirstat_from_opendir___________________________
|
||||
00 00 00 00 00 00 00 00 00 FE 01 00
|
||||
_________________________dirstat nul
|
||||
<- response dirlen
|
||||
5F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
dirstat________________________________________
|
||||
00 00 00 00 00 00 00 00 00 FE 01 01 00 04 00
|
||||
_________________________dirstat ? ? ndent
|
||||
Beispiel-2 "MMCard1\IC35\APP"
|
||||
-> command dirlen
|
||||
2B
|
||||
cmd
|
||||
00 00 02 00 00 00 40 00 15 00 00 00 00 00 00 00
|
||||
dirstat_from_opendir___________________________
|
||||
00 00 00 15 00 00 00 00 00 FE 01 00
|
||||
_________________________dirstat nul
|
||||
<- response dirlen
|
||||
00 00 02 00 00 00 40 00 15 00 00 00 00 00 00 00
|
||||
dirstat________________________________________
|
||||
00 00 00 15 00 00 00 00 00 FE 01 01 00 07 00
|
||||
_________________________dirstat ? ? ndent
|
||||
MMCard Directory Entry
|
||||
Beispiel-1 "MMCard1" rootdir
|
||||
-> command readdir index=0000
|
||||
2C
|
||||
cmd
|
||||
5F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
dirstat_from_opendir_or_previous_readdir_______
|
||||
00 00 00 00 00 00 00 00 00 FE 01 01 00 00
|
||||
_________________________dirstat idx+1 nul
|
||||
<- respnse readdir
|
||||
5F 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00
|
||||
dirstat______________________ nxidx ___________
|
||||
00 00 FF 00 00 00 00 20 00 FE 01 01 00
|
||||
_________________________dirstat ? ?
|
||||
49 43 33 35 00 20 20 20 00 00 20 20 00 10
|
||||
filename="IC35"___________ ext=""_____ ty
|
||||
2E B3 5E 29 00 00 00 00 00 00
|
||||
timestamp__ ? ? size_______
|
||||
-> command readdir index=0001
|
||||
2C
|
||||
cmd
|
||||
5F 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00
|
||||
dirstat_from_opendir_or_previous_readdir_______
|
||||
00 00 FF 00 00 00 00 20 00 FE 01 02 00 00
|
||||
_________________________dirstat idx+1 nul
|
||||
<- reponse readdir
|
||||
5F 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00
|
||||
dirstat______________________ nxidx ___________
|
||||
00 00 FF 00 00 00 00 40 00 FE 01 01 00
|
||||
_________________________dirstat ? ?
|
||||
32 30 30 30 31 31 30 34 00 49 33 35 00 20
|
||||
filename="20001104"_______ ext="I35"__ ty
|
||||
C1 14 65 29 00 00 FE 89 00 00
|
||||
timestamp__ ? ? size_______
|
||||
Beispiel-2 "MMCard1\IC35\APP"
|
||||
-> command readdir index=0000
|
||||
2C
|
||||
cmd
|
||||
00 00 02 00 00 00 40 00 15 00 00 00 00 00 00 00
|
||||
dirstat________________________________________
|
||||
00 00 00 15 00 00 00 00 00 FE 01 01 00 00
|
||||
_________________________dirstat idx+1 nul
|
||||
<- response readdir
|
||||
00 00 02 00 00 00 40 00 15 00 01 00 00 00 00 00
|
||||
dirstat______________________ nxidx ___________
|
||||
00 00 FF 15 00 00 00 20 00 FE 01 01 00
|
||||
_________________________dirstat ? ?
|
||||
2E 2E 00 20 20 20 20 20 00 00 20 20 00 10
|
||||
filename=".."_____________ ext=""_____ ty
|
||||
A1 B5 61 29 00 00 00 00 00 00
|
||||
timestamp__ ? ? size_______
|
||||
-> command readdir index=0001
|
||||
2C
|
||||
cmd
|
||||
00 00 02 00 00 00 40 00 15 00 01 00 00 00 00 00
|
||||
dirstat______________________ index ___________
|
||||
00 00 FF 15 00 00 00 20 00 FE 01 02 00 00
|
||||
_________________________dirstat idx+1 nul
|
||||
<- response readdir
|
||||
00 00 02 00 00 00 40 00 15 00 02 00 00 00 00 00
|
||||
dirstat______________________ nxidx ___________
|
||||
00 00 FF 15 00 00 00 40 00 FE 01 01 00
|
||||
_________________________dirstat ? ?
|
||||
42 52 4F 57 53 45 52 00 00 41 50 50 00 20
|
||||
filename="BROWSER"________ ext="APP"__ ty
|
||||
89 B6 61 29 00 00 44 C0 05 00
|
||||
timestamp__ ? ? size_______
|
||||
Fuer das Typfeld 'ty' wurden beobachtet
|
||||
10 Subdirectory
|
||||
20 File
|
||||
Die Kodierung des Zeitstempels 'timestamp' ist wie bei DOS.
|
||||
Die hoeherwertigen 16 Bits kodieren Jahr, Monat und Tag:
|
||||
yyyyyyy mmmm ddddd
|
||||
yyyyyyy Jahre seit 1980
|
||||
mmmm Monat 1-12
|
||||
ddddd Tag 1-31
|
||||
Die niederwertigen 16 Bits kodieren Stunde, Minute, Sekunde:
|
||||
hhhhh mmmmmm sssss
|
||||
hhhhh Stunde
|
||||
mmmmmm Minute
|
||||
sssss Sekunde / 2
|
||||
MMCard Directory Close
|
||||
Beispiel-1 "MMCard1" rootdir
|
||||
-> command closedir
|
||||
2E
|
||||
cmd
|
||||
5F 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00
|
||||
dirstat______________________ index ___________
|
||||
00 00 FF 00 00 00 00 80 00 FE 01 00
|
||||
_________________________dirstat nul
|
||||
<- response closedir
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00
|
||||
Beispiel-2 "MMCard1\IC35\APP"
|
||||
-> command closedir
|
||||
2E
|
||||
cmd
|
||||
00 00 02 00 00 00 40 00 15 00 07 00 00 00 00 00
|
||||
dirstat______________________ index ___________
|
||||
00 00 FF 15 00 00 00 E0 00 FE 01 00
|
||||
_________________________dirstat nul
|
||||
<- response closedir
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00
|
||||
|
||||
MMCard File Operationen
|
||||
MMCard File Open
|
||||
-> command openfile
|
||||
22 01 00 4D 4D 43 61 72 64 31 5C 49 43 33 35 5C 41 50 50
|
||||
mo_de filepath="MMCard1\IC35\APP\REVERSI.APP"________
|
||||
5C 52 45 56 45 52 53 49 2E 41 50 50 00
|
||||
___________________________filepath nul
|
||||
Der mo_de Parameter ist 01 00 (IC35 SDK: OPEN_EXISTING) zum Oeffnen
|
||||
einer existierended MMCard Datei (im Lesemodus).
|
||||
Der mo_de Parameter ist 00 00 (IC35 SDK: CREATE_ALWAYS) zum Erzeugen
|
||||
einer neuen MMCard Datei, eine existierende Datei wird auf Laenge 0
|
||||
gekuerzt.
|
||||
<- response openfile
|
||||
01 00
|
||||
ok
|
||||
00 00 15 00 00 00 C0 00 F9 00 00 00 00 00
|
||||
filestatus_______________________________
|
||||
44 40 00 00 00 F9 00 00 00 00 00 FE 01
|
||||
size=16452_ filestatus________________
|
||||
MMCard File Status
|
||||
-> command filestat
|
||||
26
|
||||
00 00 15 00 00 00 C0 00 F9 00 00 00 00 00
|
||||
filestatus_______________________________
|
||||
44 40 00 00 00 F9 00 00 00 00 00 FE 01 00
|
||||
size=16452_ filestatus________________ nul
|
||||
<- response filestat
|
||||
00 00 15 00 00 00 C0 00 F9 00 00 00 00 00
|
||||
44 40 00 00 00 F9 00 00 00 00 00 FE 01 01 00
|
||||
52 45 56 45 52 53 49 00 00 41 50 50 00 20
|
||||
filename="REVERSI"________ ext="APP"__ ty
|
||||
DD B6 61 29 00 00 44 40 00 00
|
||||
timestamp__ ? ? size_______
|
||||
MMCard File Read
|
||||
-> command fileread
|
||||
24
|
||||
cmd
|
||||
00 00 15 00 00 00 C0 00 F9 00 00 00 00 00
|
||||
filestatus_______________________________
|
||||
44 40 00 00 00 F9 00 00 00 00 00 FE 01 01 18 00
|
||||
size=16452_ filestatus________________ rdlen nul
|
||||
<- response fileread
|
||||
00 00 15 00 00 00 C0 00 F9 00 01 18 00 00
|
||||
filestatus_______________________________
|
||||
44 40 00 00 00 FC 00 03 00 00 00 FE 01 01 00 01 18
|
||||
size=16452_ filestatus________________ ? ? rdlen
|
||||
80 F6 00 40 00 00 00 40 00 00 FF FF 1E 00 52 ..
|
||||
filedata_____________________________________..
|
||||
-> command fileread
|
||||
24
|
||||
cmd
|
||||
00 00 15 00 00 00 C0 00 F9 00 01 18 00 00
|
||||
filestatus_______________________________
|
||||
44 40 00 00 00 FC 00 03 00 00 00 FE 01 01 18 00
|
||||
size=16452_ filestatus________________ rdlen nul
|
||||
<- response fileread
|
||||
00 00 15 00 00 00 C0 00 F9 00 02 30 00 00
|
||||
filestatus___________________ noffs _____
|
||||
44 40 00 00 00 FF 00 06 00 00 00 FE 01 01 00 01 18
|
||||
size=16452_ filestatus________________ ? ? rdlen
|
||||
36 01 23 36 00 21 0E 00 39 5E 23 56 EB 29 29 ..
|
||||
filedata_____________________________________..
|
||||
-> command fileread
|
||||
24
|
||||
cmd
|
||||
00 00 15 00 00 00 C0 00 F9 00 02 30 00 00
|
||||
filestatus_______________________________
|
||||
44 40 00 00 00 FF 00 06 00 00 00 FE 01 42 10 00
|
||||
size=16452_ filestatus________________ rdlen nul
|
||||
<- response fileread
|
||||
00 00 15 00 00 00 C0 00 F9 00 44 40 00 00
|
||||
filestatus___________________ noffs _____
|
||||
44 40 00 00 00 01 01 08 00 00 00 FE 01 01 00 42 10
|
||||
size=16452_ filestatus________________ ? ? rdlen
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..
|
||||
filedata_____________________________________..
|
||||
MMCard File Write
|
||||
-> command filewrite
|
||||
23
|
||||
cmd
|
||||
00 00 15 00 00 00 00 01 2F 01 00 00 00 00
|
||||
filestatus_______________________________
|
||||
00 00 00 00 00 2F 01 00 00 00 00 FE 01 01 18
|
||||
size=0_____ filestatus________________ wrlen
|
||||
80 F6 00 40 00 00 00 40 00 00 FF FF 1E 00 52 ..
|
||||
filedata_____________________________________..
|
||||
<- response filewrite
|
||||
00 00 15 00 00 00 00 01 2F 01 01 18 00 00
|
||||
filestatus___________________ noffs______
|
||||
01 18 00 00 00 32 01 03 00 00 00 FE 01 01 00
|
||||
size=6145__ filestatus________________ ok___
|
||||
-> command filewrite
|
||||
23
|
||||
cmd
|
||||
00 00 15 00 00 00 00 01 2F 01 01 18 00 00
|
||||
filestatus___________________ noffs______
|
||||
01 18 00 00 00 32 01 03 00 00 00 FE 01 01 18
|
||||
size=6145__ filestatus________________ wrlen
|
||||
36 01 23 36 00 21 0E 00 39 5E 23 56 EB 29 29 ..
|
||||
filedata_____________________________________..
|
||||
<- response filewrite
|
||||
00 00 15 00 00 00 00 01 2F 01 02 30 00 00
|
||||
filestatus___________________ noffs______
|
||||
02 30 00 00 00 35 01 06 00 00 00 FE 01 01 00
|
||||
size=12290_ filestatus________________ ok___
|
||||
MMCard File Close
|
||||
-> command fileclose
|
||||
27
|
||||
cmd
|
||||
00 00 15 00 00 00 C0 00 F9 00 44 40 00 00
|
||||
filestatus___________________ noffs _____
|
||||
44 40 00 00 00 01 01 08 00 00 00 FE 01 00
|
||||
size=16452_ filestatus________________ nul
|
||||
<- response fileclose
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
MMCard File Delete
|
||||
-> command filedel
|
||||
28 4D 4D 43 61 72 64 31 5C 49 43 33 35 5C 41 50 50
|
||||
cmd filepath="MMCard1\IC35\APP\REVERSI2.APP"_______
|
||||
5C 52 45 56 45 52 53 49 32 2E 41 50 50 00
|
||||
______________________________filepath nul
|
||||
<- response filedel
|
||||
01 00
|
||||
ok___
|
||||
|
||||
|
||||
Anhang: Logfiles der Protokoll-Analyse
|
||||
--------------------------------------
|
||||
- Manager.tar.gz 2000-10-26 Michael Bruennert
|
||||
Windows-NT einzeiliges Format, keine MMCard
|
||||
- Manager_Login.LOG
|
||||
connect mit IC35mgr
|
||||
- Manager_Backup.LOG
|
||||
IC35 Datensicherung nach database.org
|
||||
- database.org
|
||||
die Daten vom IC35 backup
|
||||
the data backuped from IC35
|
||||
- Manager_Logout.LOG
|
||||
disconnect vom IC35mgr
|
||||
- Manager_Reversi.LOG
|
||||
Uebertragung des Reversi.app Programms ins IC35
|
||||
- Reversi.app
|
||||
das uebertragene Programm
|
||||
- BackupRestore.tar.gz 2000-10-30 Michael Bruennert
|
||||
Windows-NT einzeiliges Format, keine MMCard
|
||||
- Manager_Backup1.log
|
||||
IC35 Datensicherung nach database.org
|
||||
- Manager_Logout1.log
|
||||
disconnect vom IC35mgr
|
||||
- Manager_Restore1.log
|
||||
IC35 Daten-Wiederherstellung von database.org
|
||||
- mgr_conn_disc.log.gz 2000-10-26 Thomas Schulz
|
||||
Windows-98, keine MMCard
|
||||
connect, disconnect
|
||||
- mgr_conn_disc_mmc.log.gz 2000-10-30 Thomas Schulz
|
||||
Windows-98, mit MMCard1
|
||||
connect, disconnect
|
||||
- mgr_rwd-file_20001107.tar.gz Thomas Schulz
|
||||
Windows-98, mit MMCard1
|
||||
- mgr_rd-reversi_20001107.log
|
||||
connect, Lesen von MMCard1\IC35\APP\REVERSI.APP, disconnect
|
||||
- mgr_wr-reversi2_20001107.log
|
||||
connect, Schreiben von MMCard1\IC35\APP\REVERSI2.APP, disconnect
|
||||
connect, Schreiben von
|
||||
- mgr_del-reversi2_20001107.log
|
||||
connect, Loeschen von MMCard1\IC35\APP\REVERSI2.APP, disconnect
|
||||
- REVERSI.APP
|
||||
das Reversi Programm, REVERSI2.APP ist Kopie davon
|
||||
|
|
@ -0,0 +1,846 @@
|
|||
$Id: ic35sync.txt,v 1.10 2000/12/03 21:10:00 tsch Rel $
|
||||
IC35-sync Protokoll
|
||||
===================
|
||||
|
||||
Inhalt
|
||||
------
|
||||
Ueberblick
|
||||
Level-1 Protokoll
|
||||
Level-2 Protokoll
|
||||
Level-3 Protokoll
|
||||
Kommunikations-Ablauf
|
||||
identification
|
||||
power
|
||||
authentication
|
||||
date+time
|
||||
category
|
||||
read,write file
|
||||
disconnect
|
||||
Zusammenfassung der PDUs
|
||||
IC35 Record Felder
|
||||
IC35Comm.dll Export Funktionen
|
||||
Anhang: Logfiles der Protokoll-Analyse
|
||||
|
||||
|
||||
Ueberblick
|
||||
----------
|
||||
??? Unklarheiten ueber das IC35-sync Protokoll sind wie hier mit ???
|
||||
??? am Zeilenanfang markiert.
|
||||
|
||||
Die IC35-sync Protokoll-"Suite" folgt offenbar dem ISO Schichten-
|
||||
modell: Untere Protokoll-"Level" kapseln Daten hoeherer Protokoll-
|
||||
Level ein und transportieren sie.
|
||||
|
||||
Generell werden in allen Protokoll-Schichten Datenbloecke (oft,
|
||||
aber nicht immer) kodiert nach dem Schema:
|
||||
ii ll ll <data>
|
||||
Dabei bedeuten
|
||||
ii Identifikations des Datenblocks
|
||||
ll ll Laenge: Anzahl Bytes ueber alles, d.h. incl. ii ll ll
|
||||
Kodierung mit niederwertigem Byte zuerst, gefolgt vom
|
||||
hoeherwertigen Byte.
|
||||
<data> Datenblock Inhalt
|
||||
|
||||
Level-1 Protokoll
|
||||
-----------------
|
||||
Level-1 PDU Kodierung allgemein:
|
||||
- ii ll ll <L2data> cc cc
|
||||
ii Identifikations der PDU
|
||||
ll ll Laenge: Anzahl der Bytes in der PDU, LSB zuerst MSB zuletzt
|
||||
L2data transportierte Level-2 PDU Daten
|
||||
cc cc Checksum: 16bit arithmetische Summe der PDU Bytes, LSB,MSB
|
||||
- ii
|
||||
kurze PDUs (nur Id) erscheinen nur von IC35 an PC.
|
||||
Level-1 PDUs PC an IC35:
|
||||
01 03 00 init initiate data exchange
|
||||
02 ll ll <L2data> cc cc datasel select which data to send
|
||||
04 03 00 datareq request to send selected data
|
||||
05 03 00 exit terminate data exchange
|
||||
Level-1 PDUs IC35 an PC:
|
||||
F0 ack0 acknowledge to init PDU
|
||||
F1 ack1 acknowledge to datasel,exit PDUs
|
||||
F2 ll ll <L2data> cc cc datarsp response to datareq PDU
|
||||
Level-1 Kommunikation PC->IC35, PC<-IC35:
|
||||
-> command init
|
||||
01 03 00
|
||||
<- response ack0
|
||||
F0
|
||||
-> command select data
|
||||
02 ll ll <L2data> cc cc
|
||||
<- reponse ack1
|
||||
F1
|
||||
-> command request data
|
||||
04 03 00
|
||||
<- reponse data
|
||||
F2 ll ll <L2data> cc cc
|
||||
-> command exit
|
||||
05 03 00
|
||||
<- reponse ack1
|
||||
F1
|
||||
Dieses Schema wird generell fuer den Transport der Level-2 Daten
|
||||
benutzt.
|
||||
|
||||
Level-2 Protokoll
|
||||
-----------------
|
||||
ll ll Laenge: Anzahl der Bytes in der Level-2 PDU (LSB,MSB)
|
||||
L3data transportierte Level-3 PDU Daten
|
||||
Level-2 PDUs PC an IC35:
|
||||
80 ll ll <L3data> identify
|
||||
02 ll ll <L3data> command write (more)
|
||||
82 ll ll <L3data> command write (last)
|
||||
83 ll ll <L3data> command read
|
||||
81 03 00 disconnect
|
||||
Level-2 PDUs IC35 an PC:
|
||||
20 ll ll <L3data> response (more)
|
||||
A0 ll ll <L3data> response (last)
|
||||
A0 03 00 response done
|
||||
90 03 00 response write more
|
||||
Transaktionen in hoeheren Schichten brauchen ggf. mehrere Blocks.
|
||||
Soweit noch ein Block folgt werden die "(more)" PDUs benutzt,
|
||||
fuer den letzten (oder einzigen) Block die "(last)" PDUs.
|
||||
|
||||
Level-3 Protokoll
|
||||
-----------------
|
||||
ll ll Laenge: Anzahl der Bytes in der Level-2 PDU (LSB,MSB)
|
||||
L3data transportierte Level-3 PDU Daten
|
||||
Level-3 PDUs PC an IC35:
|
||||
10 00 64 00 4A ll ll <L4data> identify request
|
||||
48 ll ll <L4data> command1 (more)
|
||||
49 ll ll <L4data> command2 (last)
|
||||
Level-3 PDUs IC35 an PC:
|
||||
10 00 D0 07 4A ll ll <L4data> identify response
|
||||
48 ll ll <L4data> response1 (more)
|
||||
49 ll ll <L4data> response2 (last)
|
||||
Transaktionen in hoeheren Schichten brauchen ggf. mehrere Blocks.
|
||||
Soweit noch ein Block folgt werden die "(more)" PDUs benutzt,
|
||||
fuer den letzten (oder einzigen) Block die "(last)" PDUs.
|
||||
|
||||
Kommunikations-Ablauf
|
||||
---------------------
|
||||
Die Kommunikation zwischen PC und IC35 geschieht in zwei Phasen:
|
||||
- Welcome
|
||||
- Die Leitungsparameter fuer die Kommunikation zwischen PC und
|
||||
IC35 sind Baudrate 115200, No parity, 8 databits, 2 stopbits.
|
||||
- Der PC sendet wiederholt einzelne Zeichen "A" (hex 41) bis vom
|
||||
IC35 "WELCOME" (hex 57 45 4C 43 4F 4D 45) empfangen wird.
|
||||
- Der PC sendet noch einmal ein Zeichen "A", der IC35 antwortet
|
||||
mit einem Byte hex 80.
|
||||
- Unter Windows-98/-NT setzt der PC das DTR-Signal auf "AUS"
|
||||
und schliesst den COM-Port. Nach ca. 0.015 sec oeffnet der
|
||||
PC den COM-Port erneut mit Baudrate 115200, setzt das RTS-
|
||||
Signal auf "AUS" und DTR-Signal auf "EIN", und stellt die
|
||||
Leitungsparameter: No parity, 8 databits, 2 stopbits.
|
||||
Dieses Verhalten scheint unnoetig, unter Linux ist es fuer
|
||||
die Kommunikation nicht notwendig.
|
||||
- PC setzt Timeouts: RC:500 und WC:500, vermutlich bedeutet das
|
||||
Read Character und Write Character Timeout jeweils 500 ms.
|
||||
Kommunikation der Welcome Phase:
|
||||
-> 41
|
||||
timeout 1.15 sec
|
||||
-> 41
|
||||
<- "WELCOME"
|
||||
-> 41
|
||||
<- 80
|
||||
- Datenaustausch
|
||||
In dieser Phase geschieht der Datenaustausch generell gemaess
|
||||
dem Level-1 Protokoll.
|
||||
Die Datenaustausch-Phase besteht aus folgenden Abschnitten:
|
||||
- identification
|
||||
- power
|
||||
- authentication
|
||||
- date+time
|
||||
- category
|
||||
- read,write "Addresses", "Memo", "Schedule", "To Do List"
|
||||
- disconnect
|
||||
|
||||
Im Folgenden ist nur die Level-2 Kommunikation notiert, die Uebertragung
|
||||
der Level-2 Daten geschieht wie oben beschrieben mit dem Level-1 Protokoll.
|
||||
Soweit die Level-2,-3 Header der generellen Form entsprechen, sind sie
|
||||
in Kurzform L2id,L3id notiert, andernfalls explizit
|
||||
|
||||
identification
|
||||
--------------
|
||||
Kommunikation PC->IC35, PC<-IC35:
|
||||
-> identify request
|
||||
80 26 00 # L2-header
|
||||
10 00 64 00 4A 1F 00 # L3-header
|
||||
"INVENTEC CORPORATION PRODUCT" # L4-data
|
||||
<- identify response
|
||||
A0 29 00 # L2-header
|
||||
10 00 D0 07 4A 22 00 # L3-header
|
||||
"INVENTEC CORPORATION DCS15 1.28" # L4-data
|
||||
Der L2-header entspricht der generellen Form (80 ll ll).
|
||||
??? Dem L3-header der "identify" PDUs in der generellen Form (4A ll ll)
|
||||
??? gehen jeweils 4 Bytes Daten mit unklarer Bedeutung voraus.
|
||||
|
||||
power
|
||||
-----
|
||||
Kommunikation PC->IC35, PC<-IC35:
|
||||
-> power request
|
||||
82,49 03 01 "Power" 00 00 00
|
||||
<- power response
|
||||
A0,49 03 01
|
||||
|
||||
authentication
|
||||
--------------
|
||||
Kommunikation PC->IC35, PC<-IC35:
|
||||
-> authenticate request
|
||||
82,49 03 00 [password]
|
||||
<- authenticate response right password
|
||||
A0,49 01 01
|
||||
oder
|
||||
<- authenticate response wrong password
|
||||
A0,49 00 01
|
||||
[password] ist das IC35 Kennwort als ASCII Klartext.
|
||||
IC35 sendet "response wrong password" nur dann, wenn auf dem IC35
|
||||
die Kennwort-Abfrage beim Einschalten aktiviert ist.
|
||||
|
||||
date+time
|
||||
---------
|
||||
Kommunikation PC->IC35, PC<-IC35:
|
||||
-> command get date+time
|
||||
83,49 02 00 00
|
||||
<- response date+time
|
||||
A0,49 [mmddyyyyhhmmss] 00 00
|
||||
-> command set date+time
|
||||
82,49 02 01 00 [mmddyyyyhhmmss] 00 00
|
||||
<- response done
|
||||
A0
|
||||
[mmddyyyyhhmmss] sind Monat(mm), Tag(dd), Jahr(yyyy), Stunde(hh),
|
||||
Minute(mm), Sekunde(ss) jeweils in ASCII Ziffern (hex 30..39).
|
||||
"set date+time" passiert offenbar nicht immer, es taucht nur auf
|
||||
in Simple_hex.log, Portmon_export.log, Portmon_neukat2.log, aber
|
||||
nicht in Import1.log.
|
||||
??? Wenn "set date+time" passiert, dann nach "open file Addresses"
|
||||
??? vor "get filelength Addresses". Ob das so noetig ist, ist unklar,
|
||||
??? einfacher zu implementieren ist es vor der "read,write file"
|
||||
??? Phase.
|
||||
"get date+time" liefert 00-Bytes fuer [mmddyyyyhhmmss], wenn noch
|
||||
nie ein "set date+time" zum IC35 geschehen ist.
|
||||
Laut Experimenten laesst IC35 beliebigen Text bis 16 Zeichen zu.
|
||||
Vermutlich sind die "get,set date+time" Kommandos gedacht fuer
|
||||
die Hinterlegung eines Sync/Import Stempels vom PC im IC35 (auch
|
||||
die Namen "AdsReadSysInfo" und "AdsWriteSysInfo" der IC35Comm.dll
|
||||
Funktionen stuetzen diese Vermutung), IC35sync/Windows benutzt
|
||||
dafuer offenbar einen Zeitstempel.
|
||||
|
||||
category
|
||||
--------
|
||||
Kommunikation PC->IC35, PC<-IC35:
|
||||
-> command set category
|
||||
82,49 03 02 [category]
|
||||
[category] wird mit 00 Bytes bis zur Laenge 8 Bytes aufgefuellt.
|
||||
??? <- response category ok
|
||||
??? A0,49 xx 01
|
||||
??? Die Bedeutung des Feldes xx ist unklar, es nimmt die Werte 01
|
||||
??? (Portmon_export.log) und 00 (Import.log aus Import.tar.gz) an.
|
||||
Wenn die "category" Phase vorkommt, findet sie nach "set date+time"
|
||||
statt, d.h. auch innerhalb des Filezugriffs auf Addresses.
|
||||
??? Die Semantik der "category" Phase unklar.
|
||||
|
||||
read,write file
|
||||
---------------
|
||||
Der Zugriff auf die Files "Addresses", "Memo", "Schedule" und
|
||||
"To Do List" ist beispielhaft fuer "Addresses" notiert.
|
||||
Der Filezugriff besteht aus den Phasen:
|
||||
- open file
|
||||
liefert filedescriptor, der fuer die uebrigen Phasen benutzt wird
|
||||
- get filelength (2 Varianten)
|
||||
liefert die Anzahl der zu lesenden records
|
||||
- read file record(s)
|
||||
liefert record daten, ggf. in mehreren Bloecken
|
||||
- write file record(s)
|
||||
optional, ggf. in mehreren Bloecken
|
||||
- optional delete file record(s)
|
||||
- optional reset change flag(s)
|
||||
- close file
|
||||
|
||||
open file
|
||||
-> command open file
|
||||
82,49 00 02 00 00 00 00 00 00 00 0B 00 00 00 09 "Addresses" 02
|
||||
cmd__ l1 l2 filename_
|
||||
l2 ist Laenge des filename, l1 = l2 + 2
|
||||
<- response fd=0001
|
||||
A0,49 01 00
|
||||
fd___
|
||||
Der filedescriptor fd wird anschliessend fuer den Zugriff benutzt.
|
||||
Der Filename ist ziemlich egal, es wird nur der erste Buchstabe
|
||||
unabhaengig von Gross- oder Kleinschreibung verglichen, d.h. es
|
||||
wird fuer 'A','a' "Addresses", 'M','m' "Memo", 'T','t' "To Do List"
|
||||
und fuer alle anderen Zeichen das File "Schedule" geoeffnet.
|
||||
|
||||
get filelength 03: total number of records
|
||||
Variante-1 aus Import1.log (command 01 03)
|
||||
-> command get filelength fd=0001
|
||||
83,49 01 03 01 00 00 00 00 00
|
||||
cmd__ fd___
|
||||
<- response filelength n=000B records
|
||||
A0,49 0B 00
|
||||
n____
|
||||
Diese Variante wird bei "import" und "export" benutzt.
|
||||
get filelength 04: number of modified records
|
||||
-> command get filelength fd=0001
|
||||
83,49 01 04 01 00 00 00 00 00
|
||||
cmd__ fd___
|
||||
<- response n=0000 records
|
||||
A0,49 00 00
|
||||
n____
|
||||
Diese Variante wird bei "sync" benutzt. Sie liefert die Anzahl
|
||||
der manuell auf dem IC35 modifizierten Records, d.h. veraenderte,
|
||||
neu hinzugefuegte und insbesondere auch geloeschte.
|
||||
|
||||
read file record by index
|
||||
-> command read record fd=0001 idx=0000
|
||||
83,49 01 06 01 00 00 00 00 00
|
||||
cmd__ fd___ idx__
|
||||
<- response record data (more)
|
||||
20,48 01 00 00 05 80 <flengths> <fdata>
|
||||
ri___ fi ch
|
||||
-> command read more
|
||||
83
|
||||
<- response record data (more)
|
||||
20,48 <fdata>
|
||||
-> command read more
|
||||
83
|
||||
<- response record data (last)
|
||||
A0,49 <fdata>
|
||||
Die Records werden index-orientiert gelesen, der Index idx nimmt
|
||||
Werte 0 bis n - 1 (filelength n).
|
||||
read next modified record
|
||||
(Beispiele aus Delete.tar.gz:NeueDatenSync_171100.log File "Memo")
|
||||
-> command read next modified record
|
||||
83,49 01 07 03 00 00 00 00 00
|
||||
cmd__ fd___
|
||||
<- response record data (last) Beispiel geloeschter Record
|
||||
A0,49 03 00 00 06 20
|
||||
ri___ fi ch
|
||||
-> command read next modified record
|
||||
83,49 01 07 03 00 00 00 00 00
|
||||
cmd__ fd___
|
||||
<- response record data (last) Beispiel veraenderter Record
|
||||
A0,49 05 00 00 06 80 <flengths> <fdata>
|
||||
ri___ fi ch
|
||||
read file record by record-ID
|
||||
(Beispiele aus Experimenten mit File "Memo")
|
||||
-> command read record by record-ID
|
||||
83,49 01 05 03 00 05 00 00 06
|
||||
cmd__ fd___ ri___ fi
|
||||
<- response record data (last) Beispiel vorhandener Record
|
||||
A0,49 05 00 00 06 80 <flengths> <fdata>
|
||||
ri___ fi ch
|
||||
Im Erfolgsfall enthaelt die Antwort die angeforderte RecordId
|
||||
und gueltige Feldlaengen und Daten.
|
||||
-> command read record by record-ID
|
||||
83,49 01 05 03 00 EE 78 00 06
|
||||
cmd__ fd___ ri___ fi
|
||||
<- response record data (last) Bsp. nicht vorhandener Record
|
||||
A0,49 3E 81 D3 0D 60 <flengths>
|
||||
ri___ fi ch
|
||||
Ist der Record mit der spezifizierten RecordId im IC35 nicht
|
||||
vorhanden, so enthaelt die Antwort eine ungueltige RecordId,
|
||||
ungueltige Feldlaengen und keine Felddaten.
|
||||
Im "response record data" ist fi die FileId und ri die RecordId
|
||||
auf dem IC35. Beide zusammen ergeben identifizieren den Record
|
||||
im IC35 global eindeutig.
|
||||
??? Ob die RecordId ri sich auf 3 Bytes erstreckt wurde mangels
|
||||
??? Geduld (es waeren >65536 Records zu erzeugen) nicht geklaert,
|
||||
??? die Implementation unter Linux nimmt dies an.
|
||||
Das Feld ch ist ein Aenderungskennzeichen (CHangeflag):
|
||||
80 Record im IC35 neu erzeugt oder von anderem kopiert
|
||||
40 Record im IC35 veraendert
|
||||
20 Record im IC35 geloescht (ohne <flengths>,<fdata>)
|
||||
00 keine Aenderung in diesem Record
|
||||
Das Aenderungskennzeichen wird nur durch manuelle Aenderungen
|
||||
im IC35 auf ch!=00 gesetzt, mit "write file record" neu erzeugte
|
||||
haben ch=00, mit "delete file record" geloeschte verschwinden
|
||||
vollstaendig.
|
||||
Nur von "read next modified record" werden Records mit ch=20
|
||||
geliefert, bei "read record by index" tauchen sie nicht auf.
|
||||
Der gelesene Record wird falls noetig in mehreren Bloecken
|
||||
uebertragen, vom IC35 haben alle Bloecke bis auf den letzten
|
||||
L2id=20 und L3id=48, der letzte Block hat L2id=A0 und L3id=49.
|
||||
Ein Record besteht aus einer Tabelle <flengths> von Feldlaengen
|
||||
(Bytes) gefolgt von den Felddaten <fdata>. Die Inhalte der Felder
|
||||
ergeben sich entsprechend den Feldlaengen aus den Felddaten.
|
||||
Filename Feldanzahl fi
|
||||
Addresses 21 05
|
||||
Memo 4 06
|
||||
Schedule 10 08
|
||||
To Do List 8 07
|
||||
Zumindest fuer "read next modified record" muessen erst soviel
|
||||
Leseoperationen, wie "get number of modified record" lieferte,
|
||||
durchgefuehrt werden, bevor "write record", "delete record" oder
|
||||
"reset change flag" ausgefuehrt wird. Andernfalls geschieht
|
||||
Undefiniertes, z.B. wurde ein read response ohne Record-Daten
|
||||
mit ri=01 07 03 fi=00 ch=00 beobachtet.
|
||||
|
||||
write file record
|
||||
-> command write record (more) fd=0001
|
||||
02,48 01 08 01 00 00 00 00 00 51 00 00 00 00 96 00 00 00 <flengths> <fdata>
|
||||
cmd__ fd___ w1 w2 w3 lr
|
||||
01 08 01 00 00 00 00 00 51 00 00 00 00 96 00 00 00 Addresses
|
||||
01 08 03 00 00 00 00 00 58 48 99 00 00 16 00 00 00 Memo
|
||||
01 08 03 00 00 00 00 00 60 16 99 00 00 16 00 00 00 Memo
|
||||
01 08 00 00 00 00 00 00 10 00 00 00 00 32 00 00 00 Schedule
|
||||
01 08 02 00 00 00 00 00 10 00 00 00 00 46 00 00 00 To Do List
|
||||
lr ist Gesamtlaenge des Record, d.h. Anzahl der Feldlaengen
|
||||
(Bytes in <flengths>) plus Summe der Feldlaengen (Bytes in
|
||||
<fdata>).
|
||||
??? Die Bedeutung der "write record" PDU-Felder w1, w2, w3 ist unklar.
|
||||
<- reponse write more
|
||||
90
|
||||
-> command write record (last)
|
||||
82,49 <fdata>
|
||||
<- response write ok
|
||||
A0,49 12 00 00 05
|
||||
ri___ fi
|
||||
12 00 00 05 Addresses
|
||||
03 00 00 06 Memo
|
||||
1B 00 00 08 Schedule
|
||||
02 00 00 07 To Do List
|
||||
Im "response write ok" sind fi die FileId und ri die RecordId,
|
||||
die der neue Record im IC35 erhalten hat. Es wird dabei immer ein
|
||||
neuer Record mit neuer RecordId erzeugt. Das Modifizieren unter
|
||||
Beibehaltung der RecordId ist mit "update file record" moeglich.
|
||||
Der neu erzeugte Record erhaelt Aenderungskennzeichen ch=00 (s.o.).
|
||||
Der geschriebene Record wird falls noetig in mehreren Bloecken
|
||||
uebertragen, alle bis auf den letzten Block habe L2id=02 und
|
||||
und L3id=48, der letzte Block hat L2id=82 und L3id=49.
|
||||
update file record
|
||||
-> command update record (last) fd=0003 recid=06000005
|
||||
82,49 01 09 03 00 05 00 00 06 60 19 99 00 00 46 00 00 00 <flengths> <fdata>
|
||||
cmd__ fd___ ri___ fi w1 w2 w3 lr
|
||||
ri ist die RecordId und fi die FileId auf dem IC35.
|
||||
??? w1,w2,w3 sind in der "update record" PDU die gleichen Felder
|
||||
??? wie in der "write record" PDU mit ebenso unklarer Bedeutung.
|
||||
lr ist Gesamtlaenge des Record, d.h. Anzahl der Feldlaengen
|
||||
(Bytes in <flengths>) plus Summe der Feldlaengen (Bytes in
|
||||
<fdata>).
|
||||
<- response write ok
|
||||
A0,49 05 00 00 06
|
||||
ri___ fi
|
||||
Im Unterschied zu "write record" wird die RecordId auf dem IC35
|
||||
hier beibehalten. Ansonsten verhaelt sich "update record" genauso
|
||||
wie "write record" (Fragmentierung, Aenderungskennzeichen etc.).
|
||||
|
||||
delete record
|
||||
(Beispiele aus Delete.tar.gz:NeueDatenSync_171100.log File "Memo")
|
||||
-> command delete record
|
||||
83,49 01 02 03 00 05 00 00 06
|
||||
cmd__ fd___ ri___ fi
|
||||
<- response done
|
||||
A0
|
||||
Der Record wird im IC35 direkt geloescht, d.h. er wird nicht mit
|
||||
Aenderungskennzeichen ch=20 (s.o.) auftauchen. Im Gegensatz dazu
|
||||
bleiben im IC35 manuell geloeschte Records mit ch=20 erhalten,
|
||||
bis sie mit "reset record change flag" bestaetigt werden und dann
|
||||
tatsaechlich verschwinden.
|
||||
|
||||
reset record change flag
|
||||
-> command reset record change flag
|
||||
82,49 01 0A 01 00 11 00 00 05
|
||||
cmd__ fd___ ri___ fi
|
||||
<- response done
|
||||
A0
|
||||
Das Aenderungskennzeichen des Record wird im IC35 zurueckgesetzt
|
||||
auf ch=00, d.h. Record unveraendert.
|
||||
Records mit ch=20 (ohne Daten, Reste von manuellem Loeschen auf
|
||||
dem IC35) werden endgueltig entfernt.
|
||||
|
||||
close file
|
||||
-> command close file fd=0001
|
||||
82,49 00 03 01 00 00 00 00 00
|
||||
cmd__ fd___
|
||||
<- response done
|
||||
A0
|
||||
|
||||
disconnect
|
||||
----------
|
||||
Kommunikation PC->IC35, PC<-IC35:
|
||||
-> command disconnect
|
||||
81 03 00 # L2-header
|
||||
<- response done
|
||||
A0 03 00 # L2-header
|
||||
Beim Verbindungsabbau werden nur Level-2 Header ohne Daten
|
||||
uebertragen, d.h. Level-3 wird nicht benutzt.
|
||||
|
||||
Zusammenfassung der PDUs
|
||||
------------------------
|
||||
Level-4 commands
|
||||
00 file commands
|
||||
00 02 open file
|
||||
00 03 close file
|
||||
01 record commands
|
||||
01 02 delete record
|
||||
01 03 get filelength: total number of records
|
||||
01 04 get filelength: number of modified records
|
||||
01 05 read file record by record-ID
|
||||
01 06 read file record by index
|
||||
01 07 read next modified record
|
||||
01 08 write file record
|
||||
01 09 update file record
|
||||
01 0A reset file record change-flag
|
||||
02 date+time
|
||||
02 00 get date+time
|
||||
02 01 set date+time
|
||||
03 power,passwd,category
|
||||
03 00 passwd
|
||||
03 01 power
|
||||
03 02 category
|
||||
|
||||
commands
|
||||
- identify
|
||||
80, 10 00 64 00 ,4A "INVENTEC CORPORATION PRODUCT"
|
||||
- disconnect
|
||||
81
|
||||
- power
|
||||
82,49 03 01 "Power" 00 00 00
|
||||
- authenticate
|
||||
82,49 03 00 [password]
|
||||
- get date+time
|
||||
83,49 02 00 00
|
||||
- set date+time
|
||||
82,49 02 01 00 [mmddyyyyhhmmss] 00 00
|
||||
- category
|
||||
82,49 03 02 [category] 00
|
||||
- open file
|
||||
82,49 00 02 00 00 00 00 00 00 00 lf+2 00 00 00 lf [filename] 02
|
||||
- close file
|
||||
82,49 00 03 fd_.. 00 00 00 00
|
||||
- get filelength: total number of records
|
||||
83,49 01 03 fd_.. 00 00 00 00
|
||||
- get filelength: number of modified records
|
||||
83,49 01 04 fd_.. 00 00 00 00
|
||||
- read filerecord by record-ID
|
||||
83,49 01 05 fd_.. ri_.. 00 fi
|
||||
- read filerecord by index
|
||||
83,49 01 06 fd_.. in_dx 00 00
|
||||
- read next modified filerecord
|
||||
83,49 01 07 fd_.. 00 00 00 00
|
||||
- read more
|
||||
83
|
||||
- write filerecord (more)
|
||||
02,48 01 08 fd_.. 00 00 00 00 w1 w2 w3 00 00 lr 00 00 00 <flens> <fdata>
|
||||
- update filerecord (more)
|
||||
02,48 01 09 fd_.. ri_.. 00 fi w1 w2 w3 00 00 lr 00 00 00 <flens> <fdata>
|
||||
write filerecord (last)
|
||||
82,49 <fdata>
|
||||
- delete record
|
||||
83,49 01 02 fd_.. ri_.. 00 fi
|
||||
- reset filerecord change-flag
|
||||
82,49 01 0A fd_.. ri_.. 00 fi
|
||||
|
||||
responses
|
||||
- identify
|
||||
A0, 10 00 D0 07 ,4A "INVENTEC CORPORATION DCS15 1.28"
|
||||
- disconnect
|
||||
A0
|
||||
- power
|
||||
A0,49 03 01
|
||||
- authenticate ok
|
||||
A0,49 01 01
|
||||
- get date+time
|
||||
A0,49 [mmddyyyyhhmmss] 00 00
|
||||
- set date+time
|
||||
A0
|
||||
- category
|
||||
A0,49 xx 01
|
||||
record fields:
|
||||
- xx unknown meaning, values: 00, 01
|
||||
- open file
|
||||
A0,49 fd_..
|
||||
- close file
|
||||
A0
|
||||
- get filelength
|
||||
A0,49 n._..
|
||||
- read filerecord (more)
|
||||
20,48 ri_.. 00 fi ch <flens> <fdata>
|
||||
read filerecord (last)
|
||||
A0,49 <fdata>
|
||||
record fields:
|
||||
- ri_.. record-id on IC35
|
||||
- fi file-id on IC35
|
||||
- ch change-flag: 00, 80, 40 or 20
|
||||
- write/update filerecord
|
||||
A0,49 ri_.. 00 fi
|
||||
- write more
|
||||
90
|
||||
- delete record
|
||||
A0
|
||||
- reset record changeflag
|
||||
A0
|
||||
|
||||
|
||||
IC35 Record Felder
|
||||
-----------------
|
||||
Die nachfolgenden Tabellen zu den IC35 Files (Addresses, Memo,
|
||||
Schedule, ToDoList) enthalten jeweils den 0-relativen Feld-
|
||||
Index, die Feld-Bedeutung, die maximale Feld-Laenge und ggf.
|
||||
Erlaeuterung zum Format.
|
||||
Die maximalen Feld-Laengen sind dokumentiert bei Siemens unter
|
||||
http://www.ic.siemens.com/mySiemens/lowres/content/
|
||||
ap_content_moreinfocontainer_lr/1,1908,2_IC35_4_0_61_0_2183,00.html
|
||||
??? Der Zweck der "category-id"s ist unklar, jede neu angelegte
|
||||
??? Kategorie erhaelt eine neue "category-id".
|
||||
|
||||
Addresses (21 Felder)
|
||||
0 Vorname 50
|
||||
1 Nachname 50
|
||||
2 Firma 128
|
||||
3 Tel.Privat 48
|
||||
4 Tel.Buero 48
|
||||
5 Handy 48
|
||||
6 Fax 48
|
||||
7 Strasse 128
|
||||
8 Ort 60
|
||||
9 PLZ 10
|
||||
10 Bundesland 40
|
||||
11 Land 15
|
||||
12 E-Mail1 80
|
||||
13 E-Mail2 80
|
||||
14 URL 128
|
||||
15 Geburtstag 10
|
||||
16 Notizen 255
|
||||
17 category-id 1 bin
|
||||
18 (def.)1 128
|
||||
19 (def.)2 128
|
||||
20 category 8
|
||||
category-id, -name
|
||||
02 Address (owner data)
|
||||
06 Business
|
||||
0B Personal
|
||||
0C Unfiled
|
||||
13 S35telb
|
||||
14 S35SIM.1
|
||||
15 S35SIM.2
|
||||
16 newcateg
|
||||
|
||||
Memo (4 Felder)
|
||||
0 Betreff 60
|
||||
1 Notizen 255
|
||||
2 category-id 1 bin
|
||||
3 category 8
|
||||
category-id, -name
|
||||
0D Business
|
||||
0E Personal
|
||||
0F Unfiled
|
||||
17 n.memcat
|
||||
|
||||
Schedule (10 Felder)
|
||||
Schedule Records enthalten weder category-id noch category Text.
|
||||
0 Betreff 60
|
||||
1 Start(Datum) 8 ? [yyyymmdd]
|
||||
2 Start(Zeit) 6 ? [hhmm]":1"
|
||||
3 Ende(Zeit) 6 ? [hhmm]"<1"
|
||||
4 AlrmBef 1 bin
|
||||
00=no 01=now 02=1min 03=5min 04=10min 05=30min
|
||||
06=1hour 07=2hour 08=10hour 09=1day 0A=2day
|
||||
5 Notizen 255
|
||||
6 AlrmRep(Byte) 1 bin lb00-0iii
|
||||
l: 0=LED 1=noLED, b: 0=beep 1=nobeep
|
||||
iii: 0=norepeat 1=day 2=week 3=monwday 4=year 5=monmday
|
||||
7 Ende(Datum) 8 ? [yyyymmdd]
|
||||
8 EndRepeat 8 ? [yyyymmdd]
|
||||
9 RepAlln(Byte) 1 bin nn
|
||||
repeat all nn days/weeks/mwdays/years/mmdays
|
||||
Alarm/Repeat-Flags
|
||||
f4 f6 f9 repeat alarm bef LED beep
|
||||
0A C0 01 no 2 day no no
|
||||
07 C0 01 no 2 hour no no
|
||||
06 C4 01 1 year 1 hour no no
|
||||
05 C5 02 2 mon md 30 min no no
|
||||
04 C3 01 1 mon wd 10 min no no
|
||||
03 82 03 3 week 5 min no yes
|
||||
02 41 02 2 day 1 min yes no
|
||||
01 01 01 1 day now yes yes
|
||||
00 C2 01 1 week none no no
|
||||
|
||||
ToDoList (8 Felder)
|
||||
0 Start 8 ? [yyyymmdd]
|
||||
1 Ende 8 ? [yyyymmdd]
|
||||
2 Erledigt 1 bin 00=N 01=J
|
||||
3 Prioritaet 1 bin 00=low 01=normal 02=high
|
||||
4 Betreff 60
|
||||
5 Notizen 255
|
||||
6 category-id 1 bin
|
||||
7 category 8
|
||||
category-id, -name
|
||||
10 Business
|
||||
11 Personal
|
||||
12 Unfiled
|
||||
|
||||
category-ids
|
||||
02 Address Address (owner data)
|
||||
06 Business Address
|
||||
0B Personal Address
|
||||
0C Unfiled Address
|
||||
0D Business Memo
|
||||
0E Personal Memo
|
||||
0F Unfiled Memo
|
||||
10 Business ToDoList
|
||||
11 Personal ToDoList
|
||||
12 Unfiled ToDoList
|
||||
13 S35telb Address
|
||||
14 S35SIM.1 Address
|
||||
15 S35SIM.2 Address
|
||||
16 newcateg Address
|
||||
17 n.memcat Memo
|
||||
|
||||
|
||||
IC35Comm.dll Export Funktionen
|
||||
------------------------------
|
||||
Addr IC35Comm.dll Export Funktion Aequivalent in ic35sync/Linux
|
||||
+-------+-------------------------------+----------------------------
|
||||
3859 AdsBeginSession welcome
|
||||
3BEB AdsCancelEndSession
|
||||
11AE AdsCloseDatabase close_file ?
|
||||
3FAD AdsCloseHandle close_file ?
|
||||
1B87 AdsCommitRecord commit_frec
|
||||
1341 AdsDeleteAllRecords
|
||||
14CE AdsDeleteRecord delete_frec
|
||||
3B89 AdsEndSession disconnect
|
||||
1629 AdsGetModifiedRecordCount get_mod_flen
|
||||
1585 AdsGetRecordCount get_flen
|
||||
1D84 AdsLocalDeleteRecord
|
||||
1D00 AdsLocalModifyRecord
|
||||
1C3E AdsLocalNewRecord
|
||||
1000 AdsOpenDatabase open_file ?
|
||||
13FA AdsPurgeDeleteRecords
|
||||
126D AdsReadCatagoryData category ?
|
||||
189B AdsReadNextModifiedRecord read_mod_frec
|
||||
16CD AdsReadRecordByID read_id_frec
|
||||
1701 AdsReadRecordByIndex read_frec
|
||||
1E3B AdsReadSysInfo get_date_time
|
||||
1F7F AdsSendCommand sendcmd,recvrsp
|
||||
37D0 AdsSetCancelHandle
|
||||
1B03 AdsUpdateRecord update_frec
|
||||
1A0C AdsWriteRecord write_frec
|
||||
1ED5 AdsWriteSysInfo set_date_time ?
|
||||
37EB AdsDeviceVersion identify
|
||||
3804 AdsOpenComPort com_open
|
||||
|
||||
|
||||
Anhang: Logfiles der Protokoll-Analyse
|
||||
--------------------------------------
|
||||
- Simple_hex.log +setdt -cat modrec -write -del -res
|
||||
get date+time 2000-08-20 21:28:10
|
||||
set date+time 2000-08-20 21:31:49
|
||||
no category
|
||||
get modified record count (01 04), all files return 0 records
|
||||
no writerec
|
||||
no reset changeflag
|
||||
- Portmon_export.log +setdt +cat allrec -write -del -res
|
||||
get date+time 2000-09-10 18:28:42
|
||||
set date+time 2000-09-10 18:30:35
|
||||
category Addresses (rsp 01 01)
|
||||
get record count (01 03)
|
||||
no writerec
|
||||
no reset changeflag
|
||||
- Import.tar.gz:Import1.log -setdt -cat allrec +write -del -res
|
||||
get date+time 2000-10-24 21:44:48
|
||||
no set date+time
|
||||
get record count (01 03)
|
||||
no category
|
||||
no reset changeflag
|
||||
writerec Addresses(1x),Memo(1x),Schedule(1x),ToDoList(1x)
|
||||
- Import.tar.gz:Import.log +setdt +cat allrec +write -del +res
|
||||
get date+time 2000-10-30 20:32:31
|
||||
set date+time 2000-10-30 20:59:13
|
||||
category Addresses(rsp 00 01), Memo(rsp 01 01), ToDoList(rsp 01 01)
|
||||
get record count (01 03)
|
||||
reset changeflag Addresses, Memo, Schedule, ToDoList
|
||||
writerec Addresses(1x), Schedule(2x)
|
||||
- Delete.tar.gz:Export_171100.log -setdt -cat allrec -write -del -res
|
||||
Ich habe in Outlook die Daten komplett geloescht und die
|
||||
IC35-Sync-Software zurueckgesetzt.
|
||||
Dann habe ich die Daten des IC35 nach Outlook importiert.
|
||||
get date+time 2000-11-01 17:42:13
|
||||
no set date+time
|
||||
no category
|
||||
get record count (01 03)
|
||||
no writerec
|
||||
no reset changeflag
|
||||
- Delete.tar.gz:InitSync_171100.log +setdt +cat allrec -write -del +res
|
||||
[Dann habe die Daten des IC35 nach Outlook importiert] und
|
||||
anschliessend noch einmal einen normalen Sync durchgefuehrt.
|
||||
get date+time 2000-11-01 17:42:13
|
||||
set date+time 2000-11-17 23:10:51
|
||||
category Addressses(rsp 00 01, 01 01), Memo(rsp 01 01), ToDoList(rsp 01 01)
|
||||
get record count (01 03)
|
||||
no writerec
|
||||
reset changeflag Memo,Schedule,ToDoList
|
||||
- Delete.tar.gz:NeueDatenSync_171100.log +setdt +cat modrec +write +del +res
|
||||
Anschliessendhabe ich fuer jede Kategorie je 4 Testdatensaetze
|
||||
angelegt: Je zwei in Outlook und je zwei im IC35.
|
||||
Im Betreff des Datensatzes steht dieser Erzeugungsort an erster Stelle
|
||||
(z.B Testadresse Outlook-IC35).
|
||||
An zweiter Stelle steht das Teil, mit dem der Datensatz geloescht wird.
|
||||
Anschliessend habe ich einen Sync durchgefuehrt, damit hatten der
|
||||
IC35 und Outlook jeweils alle 4 Datensaetze.
|
||||
addr 0018 IC35-IC35
|
||||
addr 0017 IC35-Outl
|
||||
addr 0019 Outl-Outl
|
||||
addr 001A Outl-IC35
|
||||
memo 0005 IC35-IC35
|
||||
memo 0004 IC35-Outl
|
||||
memo 0006 Outl-IC35
|
||||
memo 0007 Outl-Outl
|
||||
sched 0025 IC35-IC35
|
||||
sched 0024 IC35-Outl
|
||||
sched 0026 Outl-Outl
|
||||
sched 0027 Outl-IC35
|
||||
todo 000E IC35-IC35
|
||||
todo 000D IC35-Outl
|
||||
todo 000F Outl-Outl
|
||||
todo 0010 Outl-IC35
|
||||
get date+time 2000-11-17 23:22:45
|
||||
set date+time 2000-11-17 23:23:34
|
||||
category Addressses, Memo, ToDoList
|
||||
get record count Addresses(01 03) Memo(01 04) Schedule(01 04) ToDoList(01 04)
|
||||
reset changeflag Addresses, Memo, Schedule, ToDoList
|
||||
writerec Addresses(3x), Memo(2x), Schedule(2x), ToDoList(2x)
|
||||
readrec Addresses, readrecmod Memo, Schedule, ToDoList
|
||||
deleterec Memo, Schedule
|
||||
- Delete.tar.gz:DeleteSync_171100.log +setdt +cat modrec -write +del +res
|
||||
Anschliessend habe ich auf jedem Teil pro Kategorie wieder je zwei
|
||||
Datensaetze geloescht und zwar die, die durch den hinteren Namensteil
|
||||
gekennzeichnet waren (Nur bei Testadresse IC35-* ist mir ein Fehler
|
||||
passiert, dort ist es genau umgekehrt -Outlook wurde auf dem IC35
|
||||
geloescht und umgekehrt). Dann folgt wieder ein Sync (DeleteSync), bei
|
||||
dem tatsaechlich aus beiden Teilen alle Datensaetze verschwunden sind.
|
||||
addr 0018 IC35-IC35 0102-1
|
||||
addr 0017 IC35-Outl 0107-1 0102-3
|
||||
addr 0019 Outl-Outl 0102-2
|
||||
addr 001A Outl-IC35 0107-2 0102-4
|
||||
0002 0107-3 0102-5 Verwenden Sie ...
|
||||
0012 0107-4 0102-6 Testnachname, Testvorname
|
||||
0011 0107-5 0102-7 Haid, Beppo
|
||||
memo 0005 IC35-IC35 0107-2 0102-4
|
||||
memo 0004 IC35-Outl 0102-1
|
||||
memo 0006 Outl-IC35 0107-1 0102-3
|
||||
memo 0007 Outl-Outl 0102-2
|
||||
sched 0025 IC35-IC35 0107-2 0102-4
|
||||
sched 0024 IC35-Outl 0102-2
|
||||
sched 0026 Outl-Outl 0102-1
|
||||
sched 0027 Outl-IC35 0107-1 0102-3
|
||||
todo 000E IC35-IC35 0107-1 0102-3
|
||||
todo 000D IC35-Outl 0102-1
|
||||
todo 000F Outl-Outl 0102-2
|
||||
todo 0010 Outl-IC35 0107-2 0102-4
|
||||
get date+time 2000-11-17 23:23:34
|
||||
set date+time 2000-11-17 23:30:28
|
||||
category Addresses, Memo, ToDoList
|
||||
get modified record count (01 04)
|
||||
readrecmod
|
||||
deleterec Addresses, Memo, Schedule, ToDoList
|
||||
no writerec
|
||||
reset changeflag
|
||||
- Delete.tar.gz:Import_171100.log +setdt +cat allrec -write -del +res
|
||||
Anschliessend habe ich wie gewuenscht noch einen Export der
|
||||
Outlook-Daten in den IC35 durchgefuehrt.
|
||||
get date+time 2000-11-17 23:30:28
|
||||
set date+time 2000-11-17 23:48:36
|
||||
category
|
||||
reset changeflag
|
||||
no writerec
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
vcc.c
|
||||
versinfo.c
|
||||
ic35sync
|
||||
ic35mgr
|
||||
ic35log
|
||||
vcaconv
|
||||
.deps
|
|
@ -0,0 +1,35 @@
|
|||
/.cvsignore/1.2/Mon Feb 19 01:09:14 2001//
|
||||
/Makefile.am/1.3/Mon Feb 19 01:09:43 2001//
|
||||
/comio.c/1.13/Sat Mar 3 16:30:45 2001//
|
||||
/comio.h/1.7/Sat Mar 3 16:30:45 2001//
|
||||
/databin.c/1.35/Fri Mar 2 02:09:59 2001//
|
||||
/dataio.c/1.33/Fri Mar 2 02:09:59 2001//
|
||||
/dataio.h/1.12/Tue Dec 26 01:25:22 2000//
|
||||
/datatxt.c/1.32/Tue Dec 26 01:36:32 2000//
|
||||
/datavca.c/1.46/Fri Mar 2 02:09:59 2001//
|
||||
/genproto.c/1.2/Sun Jan 21 19:54:52 2001//
|
||||
/genproto.h/1.2/Sun Jan 21 23:38:37 2001//
|
||||
/ic35frec.c/1.8/Fri Mar 2 02:09:59 2001//
|
||||
/ic35frec.h/1.5/Sat Dec 23 01:09:26 2000//
|
||||
/ic35log.sh/1.6/Sun Jan 14 00:09:46 2001//
|
||||
/ic35mgr.c/1.20/Tue Nov 20 23:08:35 2001//
|
||||
/ic35sync.c/1.19/Fri Mar 2 02:10:42 2001//
|
||||
/mgrproto.c/1.17/Tue Nov 20 23:08:35 2001//
|
||||
/mgrproto.h/1.8/Tue Nov 20 23:08:35 2001//
|
||||
/mgrtrans.c/1.17/Tue Nov 20 23:08:35 2001//
|
||||
/mgrtrans.h/1.7/Tue Nov 20 23:08:35 2001//
|
||||
/port.h/1.3/Sat Feb 10 03:08:41 2001//
|
||||
/synproto.c/1.11/Sun Jun 17 23:37:36 2001//
|
||||
/synproto.h/1.3/Sun Dec 3 07:50:44 2000//
|
||||
/syntrans.c/1.19/Fri Mar 2 02:09:59 2001//
|
||||
/syntrans.h/1.10/Thu Dec 21 11:05:52 2000//
|
||||
/util.c/1.9/Mon Jun 11 09:14:59 2001//
|
||||
/util.h/1.9/Fri Mar 2 02:08:32 2001//
|
||||
/vcaconv.c/1.17/Sat Feb 17 20:56:49 2001//
|
||||
/vcc.h/1.2/Sun Nov 19 18:14:45 2000//
|
||||
/vcc.y/1.7/Sat Feb 10 03:09:24 2001//
|
||||
/vcutil.c/1.44/Thu Dec 28 02:26:31 2000//
|
||||
/vcutil.h/1.44/Wed Dec 27 22:26:52 2000//
|
||||
/vobject.c/1.9/Wed Feb 7 01:44:42 2001//
|
||||
/vobject.h/1.6/Thu Dec 21 23:01:45 2000//
|
||||
D
|
|
@ -0,0 +1 @@
|
|||
ic35link/src
|
|
@ -0,0 +1 @@
|
|||
:pserver:anonymous@ic35link.cvs.sourceforge.net:/cvsroot/ic35link
|
|
@ -0,0 +1,64 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
## $Id: Makefile.am,v 1.3 2001/02/19 01:09:43 tsch Rel $
|
||||
## Copyright (C) 2001 Thomas Schulz
|
||||
##
|
||||
## automakefile for ic35link/src
|
||||
|
||||
versinfo.c: Makefile
|
||||
-@echo "Creating versinfo.c"
|
||||
-@rm -f versinfo.c
|
||||
-@echo '/* versinfo.c */' > versinfo.c
|
||||
-@echo '/* automatically made by Makefile */' >> versinfo.c
|
||||
-@echo '/* DO NOT EDIT! */' >> versinfo.c
|
||||
-@echo '#include "../config.h"' >> versinfo.c
|
||||
-@echo 'char * pkgvers = VERSION;' >> versinfo.c
|
||||
-@echo 'char * pkgdate = ISODATE;' >> versinfo.c
|
||||
-@echo 'char * bldinfo = "compiled '`date '+%Y-%m-%d %T'` \
|
||||
'by '`whoami`'@'`hostname`'";' >> versinfo.c
|
||||
|
||||
bin_PROGRAMS = ic35sync ic35mgr vcaconv
|
||||
ic35sync_SOURCES = \
|
||||
ic35sync.c \
|
||||
syntrans.c syntrans.h \
|
||||
synproto.c synproto.h \
|
||||
genproto.c genproto.h \
|
||||
dataio.c dataio.h datatxt.c databin.c datavca.c \
|
||||
ic35frec.c ic35frec.h \
|
||||
vcutil.c vcutil.h \
|
||||
vcc.y vcc.h vobject.c vobject.h port.h \
|
||||
comio.c comio.h \
|
||||
util.c util.h \
|
||||
versinfo.c
|
||||
ic35mgr_SOURCES = \
|
||||
ic35mgr.c \
|
||||
mgrtrans.c mgrtrans.h \
|
||||
mgrproto.c mgrproto.h \
|
||||
genproto.c genproto.h \
|
||||
comio.c comio.h \
|
||||
util.c util.h \
|
||||
versinfo.c
|
||||
vcaconv_SOURCES = \
|
||||
vcaconv.c \
|
||||
dataio.c dataio.h datatxt.c databin.c datavca.c \
|
||||
ic35frec.c ic35frec.h \
|
||||
vcutil.c vcutil.h \
|
||||
vcc.y vcc.h vobject.c vobject.h port.h \
|
||||
util.c util.h \
|
||||
versinfo.c
|
||||
|
||||
bin_SCRIPTS = ic35log
|
||||
ic35log:
|
||||
cat $@.sh >$@
|
||||
chmod a+x $@
|
||||
|
||||
EXTRA_DIST = ic35log.sh
|
||||
|
||||
# tell automake to not strip scripts:
|
||||
INSTALL_SCRIPT = $(INSTALL)
|
||||
|
||||
CLEANFILES = ic35log .deps/* versinfo.c
|
||||
if MAINTAINER_MODE
|
||||
MAINTAINERCLEANFILES = vcc.c Makefile.in
|
||||
else
|
||||
MAINTAINERCLEANFILES =
|
||||
endif
|
|
@ -0,0 +1,484 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* */
|
||||
static char rcsid[] =
|
||||
"$Id: comio.c,v 1.13 2001/03/03 16:30:45 tsch Rel $"; /*
|
||||
* *
|
||||
* IC35 serial communication
|
||||
* *
|
||||
*************************************************************************
|
||||
* *
|
||||
* conditional compile on NO_LOGSIM: if #defined, the simulated *
|
||||
* communication is NOT supported, default WITH com-simulation. *
|
||||
* conditional compile on __STRICT_ANSI__: if #defined, substitute *
|
||||
* functions, which are not available with the ANSI C standard. *
|
||||
* (compilation with 'gcc -ansi ..' does #define __STRICT_ANSI__) *
|
||||
* *
|
||||
* simulated communication #ifndef NO_LOGSIM *
|
||||
* com_siminit initialize communications with simulation file *
|
||||
* com_simexit local: leave simulated communication *
|
||||
* com_simul local: report if simulation active *
|
||||
* com_simrecv local: simulate receive from simulation file *
|
||||
* real communication
|
||||
* com_setsigs local: set RS232 output signals *
|
||||
* com_settimeout set receive timeout, return previous *
|
||||
* com_init initialize serial communication device *
|
||||
* com_waitnice lower process priority when using com_sendw() *
|
||||
* com_sendw send datablock to comm.device with waiting *
|
||||
* com_send send datablock to comm.device *
|
||||
* com_recv receive datablock from comm.device *
|
||||
* com_exit close serial communication device *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include <stdio.h> /* FILE*, fopen(), .. */
|
||||
#include <string.h> /* strncmp(), .. */
|
||||
#include <unistd.h> /* read(), write(), .. */
|
||||
#include <termios.h> /* tcgetattr(), .. */
|
||||
#include <fcntl.h> /* F_GETFL, .. */
|
||||
#include <sys/ioctl.h> /* ioctl(), .. */
|
||||
#include <sys/types.h> /* size_t, .. */
|
||||
#include <sys/time.h> /* struct timeval */
|
||||
#include <signal.h> /* sigaction(), .. */
|
||||
|
||||
#include "util.h" /* LPRINTF(), .. */
|
||||
#include "comio.h"
|
||||
NOTUSED(rcsid)
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* simulated communication */
|
||||
/* ==================================== */
|
||||
/*
|
||||
* uses post-processed log of real communication with IC35:
|
||||
* WR nn xx xx xx ...
|
||||
* RD nn xx xx xx ...
|
||||
* and "receives" data using the "RD nn" lines.
|
||||
*/
|
||||
#ifndef NO_LOGSIM
|
||||
static FILE * simfp = NULL;
|
||||
|
||||
static int
|
||||
_com_siminit( char * s_fname ) /* init simulated comm */
|
||||
{
|
||||
if ( s_fname && *s_fname ) {
|
||||
simfp = fopen( s_fname, "r" );
|
||||
if ( simfp == NULL )
|
||||
return ERR;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
void
|
||||
com_siminit( char * s_fname )
|
||||
{
|
||||
if ( _com_siminit( s_fname ) != OK )
|
||||
fatal( "cannot open simulation file: %s", s_fname );
|
||||
}
|
||||
static void
|
||||
com_simexit( void ) /* leave simulated comm */
|
||||
{
|
||||
if ( simfp ) {
|
||||
fclose( simfp );
|
||||
simfp = NULL;
|
||||
}
|
||||
}
|
||||
static bool
|
||||
com_simul( void ) /* report if simul active */
|
||||
{
|
||||
return (bool)( simfp != NULL );
|
||||
}
|
||||
static int
|
||||
com_simrecv( uchar * buff, size_t blen ) /* receive from simul.file */
|
||||
{
|
||||
static int simrlen = 0;
|
||||
static int simridx = 0;
|
||||
bool do_check;
|
||||
uchar * bptr;
|
||||
int chr, n, rbyte;
|
||||
char xdir[8];
|
||||
|
||||
if ( buff == NULL || blen == 0 ) /* sanity */
|
||||
return 0;
|
||||
|
||||
memset( buff, 0, blen); /* clear buffer sets dummy bytes */
|
||||
bptr = buff; do_check = FALSE;
|
||||
while ( bptr < buff + blen ) {
|
||||
/* forward to or check next "RD nn" line */
|
||||
if ( simridx >= simrlen ) {
|
||||
for ( ; ; ) {
|
||||
while ( (chr = fgetc( simfp )) != '\n' )
|
||||
if ( chr < 0 )
|
||||
return ERR;
|
||||
if ( fscanf( simfp, "%s %d", xdir, &simrlen ) == 2
|
||||
&& strncmp( xdir, "RD", 2 ) == 0 )
|
||||
break;
|
||||
if ( do_check )
|
||||
return bptr - buff;
|
||||
}
|
||||
do_check = TRUE;
|
||||
simridx = 0;
|
||||
}
|
||||
/* read bytes from "RD nn" line */
|
||||
for ( ; simridx < simrlen; ++simridx ) {
|
||||
if ( bptr >= buff + blen )
|
||||
return blen;
|
||||
ungetc( chr = fgetc( simfp ), simfp ); /* avoid fscanf() eat \n */
|
||||
if ( chr == '\n'
|
||||
|| fscanf( simfp, "%x", &rbyte ) != 1 )
|
||||
break;
|
||||
*bptr++ = (uchar)rbyte;
|
||||
}
|
||||
/* dummy non-logged recv bytes */
|
||||
n = min( blen - (bptr - buff), simrlen - simridx);
|
||||
simridx += n;
|
||||
bptr += n;
|
||||
}
|
||||
return bptr - buff;
|
||||
}
|
||||
#endif /*NO_LOGSIM*/
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* real communication */
|
||||
/* ==================================== */
|
||||
|
||||
static int com_fd = -1;
|
||||
static int com_tmo = 500; /* timeout 500 ms */
|
||||
|
||||
/* local: set RS232 output signals
|
||||
* -------------------------------
|
||||
*/
|
||||
static void
|
||||
com_setsigs( int sigs )
|
||||
{
|
||||
int flags;
|
||||
|
||||
if ( com_fd >= 0
|
||||
&& ioctl( com_fd, TIOCMGET, &flags ) == 0 ) {
|
||||
flags &= ~(TIOCM_DTR|TIOCM_RTS);
|
||||
flags |= (TIOCM_DTR|TIOCM_RTS) & sigs;
|
||||
ioctl( com_fd, TIOCMSET, &flags );
|
||||
LPRINTF(( L_NOISE, "com_setsigs(%08X) DTR %s RTS %s",
|
||||
sigs, sigs & TIOCM_DTR ? "ON " : "off",
|
||||
sigs & TIOCM_RTS ? "ON " : "off" ));
|
||||
}
|
||||
}
|
||||
|
||||
/* local: log state of RS232 signals
|
||||
* ---------------------------------
|
||||
*/
|
||||
static void
|
||||
_com_sigchg( void )
|
||||
{
|
||||
static int oflags = -1;
|
||||
static struct {
|
||||
char * name;
|
||||
int sig;
|
||||
} sigtab[] = {
|
||||
{ "CTS", TIOCM_CTS },
|
||||
{ "DCD", TIOCM_CAR },
|
||||
{ "DSR", TIOCM_DSR },
|
||||
{ "RI", TIOCM_RNG },
|
||||
{ NULL, 0 }
|
||||
}, *psig;
|
||||
int flags;
|
||||
char sigtext[48];
|
||||
|
||||
if ( com_fd >= 0
|
||||
&& ioctl( com_fd, TIOCMGET, &flags ) == 0
|
||||
&& ( ((oflags ^ flags) & (TIOCM_CTS|TIOCM_CAR|TIOCM_DSR|TIOCM_RNG)) != 0
|
||||
|| oflags == -1 ) ) {
|
||||
strcpy( sigtext, "" );
|
||||
for ( psig = sigtab; psig->name; ++psig )
|
||||
sprintf( sigtext+strlen(sigtext), " %s %s%s",
|
||||
psig->name,
|
||||
flags & psig->sig ? "ON" : "off",
|
||||
((oflags ^ flags) & psig->sig) && oflags != -1 ? "*" : "" );
|
||||
LPRINTF(( L_NOISE, "com signals:%s", sigtext ));
|
||||
oflags = flags;
|
||||
}
|
||||
}
|
||||
|
||||
/* set,get receive timeout
|
||||
* -----------------------
|
||||
* return previous timeout. zero or negative timeout argument 'msec'
|
||||
* will not be set and can be used to enquire current timeout.
|
||||
*/
|
||||
int
|
||||
com_settimeout( int msec )
|
||||
{
|
||||
int old_tmo = com_tmo;
|
||||
|
||||
old_tmo = com_tmo;
|
||||
if ( msec > 0 )
|
||||
com_tmo = msec;
|
||||
if ( old_tmo != com_tmo )
|
||||
LPRINTF(( L_NOISE, "com_settimeout %d -> %d", old_tmo, com_tmo ));
|
||||
return old_tmo;
|
||||
}
|
||||
|
||||
/* initialize comm.device
|
||||
* ----------------------
|
||||
* open in O_NONBLOCK mode to avoid hanging on inactice DCD signal,
|
||||
* finally set back to blocking mode.
|
||||
* set line parameters to 115200,N,8,2 and raw mode, 2 stopbits are
|
||||
* needed to avoid IC35 receive errors with MMCard operations.
|
||||
* raise DTR and RTS signals.
|
||||
*/
|
||||
#ifdef __STRICT_ANSI__
|
||||
#define cfmakeraw(tiop) \
|
||||
(tiop)->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); \
|
||||
(tiop)->c_oflag &= ~(OPOST); \
|
||||
(tiop)->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); \
|
||||
(tiop)->c_cflag &= ~(CSIZE|PARENB); \
|
||||
(tiop)->c_cflag |= CS8;
|
||||
#endif
|
||||
|
||||
int
|
||||
com_init( char * devname )
|
||||
{
|
||||
int i, flags;
|
||||
struct termios tio;
|
||||
|
||||
#ifndef NO_LOGSIM
|
||||
if ( com_simul() ) {
|
||||
com_fd = -1;
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
/* open serial communication device */
|
||||
if ( (com_fd = open( devname, O_RDWR|O_NONBLOCK|O_NOCTTY )) == -1 ) {
|
||||
return ERR;
|
||||
}
|
||||
if ( !isatty( com_fd ) ) {
|
||||
close( com_fd );
|
||||
com_fd = -1;
|
||||
return ERR;
|
||||
}
|
||||
/* set linepars 11500,N,8,2 and raw mode */
|
||||
/* HUPCL to clear DTR,RTS on last close */
|
||||
tcgetattr( com_fd, &tio );
|
||||
tio.c_oflag = 0;
|
||||
tio.c_iflag = IGNBRK | IGNPAR;
|
||||
tio.c_cflag = CREAD | CLOCAL | CS8 | HUPCL | CSTOPB;
|
||||
cfsetispeed( &tio, B115200 );
|
||||
cfsetospeed( &tio, B115200 );
|
||||
tio.c_lflag = NOFLSH;
|
||||
cfmakeraw( &tio );
|
||||
for ( i = 0; i <= NCCS; ++i ) tio.c_cc[i] = 0;
|
||||
tio.c_cc[VMIN] = 1;
|
||||
tio.c_cc[VTIME] = 0;
|
||||
tcsetattr( com_fd, TCSANOW, &tio );
|
||||
/* set line signals DTR on, RTS off */
|
||||
com_setsigs( TIOCM_DTR|TIOCM_RTS );
|
||||
/* back to blocking mode for timeout */
|
||||
if ( (flags = fcntl( com_fd, F_GETFL, 0 )) != -1 ) {
|
||||
flags &= ~O_NONBLOCK;
|
||||
fcntl( com_fd, F_SETFL, flags );
|
||||
}
|
||||
_com_sigchg();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* send datablock with waiting
|
||||
* ---------------------------
|
||||
* IC35 gets receive receive errors if datablocks of more than 16 bytes
|
||||
* are sent at full speed of 115200 baud, using 2 stopbits increases
|
||||
* this size limit to 29 bytes.
|
||||
* the problem occurred only with IC35 MMCard operations, import and
|
||||
* synchronize PIM-data don't suffer this limitation.
|
||||
* as a workaround do delay some time after sent every couple of bytes.
|
||||
* the delay is done with busy waiting using gettimeofday(), because
|
||||
* interrupt controlled delays are either too long (at least 10 msec
|
||||
* with an "itimer" at Linux-2.x timer interrupt frequency of 100 Hz)
|
||||
* or require root privilege (nanosleep() or fast RTC interrupts).
|
||||
* other methods like usleep(), nanosleep(), select() yielded delays
|
||||
* of ca. 20..30 msec and were therefore also not chosen.
|
||||
* (see getitimer(2), sigaction(2), nanosleep(2), usleep(3), select(2)
|
||||
* for reference).
|
||||
* to avoid too much CPU hogging during busywait delays, the process
|
||||
* scheduling priority may be lowered using nice(2) when comsendw()
|
||||
* is called with a block of more than NICE_MINBLEN bytes.
|
||||
* com_waitnice() is used to enable the priority lowering: each call
|
||||
* of com_waitnice() causes one nice() systemcall.
|
||||
* the maximum throughput measured with write file to IC35 MMCard was
|
||||
* ca. 1740 b/s with 2kB buffersize (with "itimer" it was ca. 1350 b/s,
|
||||
* with usleep() delay it was only ca. 600 b/s).
|
||||
* measurements on a Pentium-I/133MHz showed that
|
||||
* for blocks of 1 8 16 24 28 bytes
|
||||
* the delay of 165 1570 3180 4795 5620 usec was needed at least.
|
||||
* measurements on a Pentium-III/500MHz (by Harald Becker) showed that
|
||||
* for blocks of 1 16 bytes
|
||||
* the delay of 187 3212 usec was needed at least.
|
||||
*/
|
||||
#define NICE_MINBLEN 32 /* min. block length for nice() */
|
||||
#define WAIT_BLKSIZE 16 /* number of bytes per write() */
|
||||
#define WAIT_USDELAY 3250 /* usec to wait before write() */
|
||||
|
||||
static int _waitnice_inc; /* increment to use for nice(2) */
|
||||
|
||||
static void /* busy wait some microseconds */
|
||||
_wait_usec( long usec ) /* contributed by Harald Becker */
|
||||
{
|
||||
long elapsed; /* elapsed delay in usec */
|
||||
struct timeval tbeg, tnow; /* start time and current time */
|
||||
|
||||
gettimeofday( &tbeg, NULL ); /* get start time of delay loop */
|
||||
do { /* loop .. */
|
||||
gettimeofday( &tnow, NULL ); /* get current time */
|
||||
if ( (elapsed = tnow.tv_sec - tbeg.tv_sec) ) /* seconds diff */
|
||||
elapsed *= 1000000; /* to usec if nonzero */
|
||||
elapsed += tnow.tv_usec - tbeg.tv_usec; /* add microsecs diff */
|
||||
} while( elapsed < usec ); /* .. until specified usec over */
|
||||
}
|
||||
|
||||
void /* export interface to store increment */
|
||||
com_waitnice( int inc ) /* 'inc' for lowering process priority */
|
||||
{
|
||||
_waitnice_inc = inc;
|
||||
}
|
||||
|
||||
int /* send data to communication device */
|
||||
com_sendw( uchar * data, size_t dlen ) /* with busywait delays */
|
||||
{
|
||||
uchar * dptr;
|
||||
int slen;
|
||||
|
||||
#ifndef NO_LOGSIM
|
||||
if ( com_simul() )
|
||||
slen = dlen;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if ( com_fd < 0 )
|
||||
return ERR;
|
||||
LPRINTF(( L_DEBUG, "com_sendw(%p,%u) ..", data, dlen ));
|
||||
if ( dlen >= NICE_MINBLEN && _waitnice_inc != 0 ) {
|
||||
nice( _waitnice_inc ); /* lower own process priority */
|
||||
_waitnice_inc = 0; /* no more nice() before next */
|
||||
} /* com_waitnice() tells again */
|
||||
dptr = data;
|
||||
while ( (slen = data+dlen - dptr) > 0 ) {
|
||||
if ( slen > WAIT_BLKSIZE ) slen = WAIT_BLKSIZE;
|
||||
_wait_usec( WAIT_USDELAY );
|
||||
if ( write( com_fd, dptr, slen ) != slen )
|
||||
break;
|
||||
dptr += slen;
|
||||
}
|
||||
slen = dptr - data;
|
||||
}
|
||||
LDUMP(( L_NOISE, data, dlen,
|
||||
"com_sendw(%p,%u) = %d", data, dlen, slen ));
|
||||
return slen;
|
||||
}
|
||||
|
||||
/* send datablock to comm.device
|
||||
* -----------------------------
|
||||
*/
|
||||
int
|
||||
com_send( uchar * data, size_t dlen )
|
||||
{
|
||||
int slen;
|
||||
|
||||
#ifndef NO_LOGSIM
|
||||
if ( com_simul() )
|
||||
slen = dlen;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if ( com_fd < 0 )
|
||||
return ERR;
|
||||
LPRINTF(( L_DEBUG, "com_send(%p,%u) ..", data, dlen ));
|
||||
slen = write( com_fd, data, dlen );
|
||||
}
|
||||
LDUMP(( L_NOISE, data, dlen,
|
||||
"com_send(%p,%u) = %d", data, dlen, slen ));
|
||||
return slen;
|
||||
}
|
||||
|
||||
/* receive datablock from comm.device
|
||||
* ----------------------------------
|
||||
* use select() to wait for data, accumulate data with read()
|
||||
* until buffer 'buff' gets full or receive timeout occurs.
|
||||
*/
|
||||
int
|
||||
com_recv( uchar * buff, size_t blen )
|
||||
{
|
||||
fd_set rfds;
|
||||
struct timeval tmo;
|
||||
uchar *rptr, *rend;
|
||||
int rlen;
|
||||
|
||||
#ifndef NO_LOGSIM
|
||||
if ( com_simul() )
|
||||
rlen = com_simrecv( buff, blen );
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if ( com_fd < 0 )
|
||||
return ERR;
|
||||
rend = (rptr = buff) + blen;
|
||||
do {
|
||||
FD_ZERO( &rfds );
|
||||
FD_SET( com_fd, &rfds );
|
||||
tmo.tv_sec = com_tmo / 1000;
|
||||
tmo.tv_usec = (com_tmo % 1000) * 1000;
|
||||
if ( select( com_fd+1, &rfds, NULL, NULL, &tmo ) > 0
|
||||
&& FD_ISSET( com_fd, &rfds ) ) {
|
||||
_com_sigchg();
|
||||
rlen = read( com_fd, rptr, rend - rptr );
|
||||
LPRINTF(( L_DEBUG, "com_recv: read(com,rptr,%d) = %d",
|
||||
rend-rptr, rlen ));
|
||||
if ( rlen > 0 )
|
||||
rptr += rlen;
|
||||
} else {
|
||||
rlen = 0;
|
||||
}
|
||||
} while ( rlen > 0 && rptr < rend );
|
||||
rlen = rptr - buff;
|
||||
}
|
||||
if ( rlen > 0 )
|
||||
LDUMP(( L_NOISE, buff, rlen,
|
||||
"com_recv(%p,%u) = %d", buff, blen, rlen ));
|
||||
else
|
||||
LPRINTF(( L_NOISE, "com_recv(%p,%u) = %d", buff, blen, rlen ));
|
||||
|
||||
return rlen;
|
||||
}
|
||||
|
||||
/* close comm.device
|
||||
* -----------------
|
||||
* leave simulated communication if active.
|
||||
* clear RS232 signals DTR and RTS and close comm.device.
|
||||
*/
|
||||
void
|
||||
com_exit( void )
|
||||
{
|
||||
#ifndef NO_LOGSIM
|
||||
com_simexit();
|
||||
#endif
|
||||
if ( com_fd < 0 )
|
||||
return;
|
||||
com_setsigs( 0 ); /* DTR off, RTS off */
|
||||
_com_sigchg();
|
||||
close( com_fd );
|
||||
com_fd = -1;
|
||||
}
|
||||
|
||||
/* substitute for usleep()
|
||||
* -----------------------
|
||||
* the usleep() function is unavailable on compilation with "-ansi",
|
||||
* which #defines __STRICT_ANSI__
|
||||
*/
|
||||
#ifdef __STRICT_ANSI__
|
||||
void
|
||||
usleep( unsigned long usec )
|
||||
{
|
||||
struct timeval tmo;
|
||||
|
||||
tmo.tv_sec = usec / 1000000;
|
||||
tmo.tv_usec = usec % 1000000;
|
||||
select( 0, NULL, NULL, NULL, &tmo );
|
||||
}
|
||||
#endif /*__STRICT_ANSI__*/
|
|
@ -0,0 +1,37 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* *
|
||||
* $Id: comio.h,v 1.7 2001/03/03 16:30:45 tsch Rel $ *
|
||||
* *
|
||||
* header for IC35 serial communication *
|
||||
* *
|
||||
************************************************************************/
|
||||
#ifndef _COMIO_H
|
||||
#define _COMIO_H 1
|
||||
|
||||
#include <sys/types.h> /* size_t */
|
||||
|
||||
#include "util.h" /* uchar, NO_LOGSIM */
|
||||
|
||||
|
||||
#ifdef NO_LOGSIM
|
||||
#define COM_SIMINIT(arg)
|
||||
#else
|
||||
#define COM_SIMINIT(arg) com_siminit arg
|
||||
#endif
|
||||
|
||||
|
||||
void com_siminit( char * s_fname ); /* init comm.simulation */
|
||||
int com_settimeout( int msec ); /* set timeout [msec] */
|
||||
int com_init( char * devname ); /* initialize comm.device */
|
||||
void com_waitnice( int inc ); /* for nice() in com_sendw*/
|
||||
int com_sendw( uchar * data, size_t dlen ); /* send data with waiting */
|
||||
int com_send( uchar * data, size_t dlen ); /* send data to comm.dev */
|
||||
int com_recv( uchar * buff, size_t blen ); /* receive from comm.dev */
|
||||
void com_exit( void ); /* close comm.device */
|
||||
|
||||
#ifdef __STRICT_ANSI__
|
||||
void usleep( unsigned long usec );
|
||||
#endif
|
||||
|
||||
#endif /*_COMIO_H*/
|
|
@ -0,0 +1,362 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* */
|
||||
static char rcsid[] =
|
||||
"$Id: databin.c,v 1.35 2001/03/02 02:09:59 tsch Rel $"; /*
|
||||
* *
|
||||
* IC35 synchronize data import/export: binary IC35 record format *
|
||||
* *
|
||||
*************************************************************************
|
||||
* *
|
||||
* ??? is "fixme" mark: sections of code needing fixes *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include <stdio.h> /* fprintf(), .. */
|
||||
#include <string.h> /* strcpy(), .. */
|
||||
#include <ctype.h> /* isprint(), .. */
|
||||
#include <unistd.h> /* access() */
|
||||
#include <sys/types.h> /* size_t, .. */
|
||||
#include <time.h> /* struct tm, time() .. */
|
||||
|
||||
#include "vcc.h" /* VObject, .. */
|
||||
#include "util.h" /* ERR, uchar, .. */
|
||||
#include "ic35frec.h" /* IC35 record fields.. */
|
||||
#include "dataio.h"
|
||||
NOTUSED(rcsid);
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
struct binrec { /* IC35 binary record data */
|
||||
size_t len; /* length of this record */
|
||||
ulong rid; /* record id on IC35 */
|
||||
uchar chg; /* changeflag on IC35 */
|
||||
}; /* flengths,fdata (dyn.length) */
|
||||
#pragma pack()
|
||||
struct binelmt { /* IC35 binrec list element */
|
||||
struct binelmt * next; /* next element in list */
|
||||
IC35REC * rec; /* IC35 record */
|
||||
};
|
||||
|
||||
static struct binelmt * binlist;
|
||||
static struct binelmt * binget;
|
||||
|
||||
/* internal: write IC35 binary record to file
|
||||
* ------------------------------------------
|
||||
*/
|
||||
static int
|
||||
_bin_writerec( FILE * outfp, IC35REC * rec )
|
||||
{
|
||||
uchar * recdata;
|
||||
size_t reclen;
|
||||
struct binrec brec;
|
||||
|
||||
get_ic35recdata( rec, &recdata, &reclen );
|
||||
brec.len = sizeof(brec) + reclen;
|
||||
brec.rid = ic35recid( rec );
|
||||
brec.chg = ic35recchg( rec );
|
||||
if ( fwrite( &brec, sizeof(brec), 1, outfp ) != 1
|
||||
|| fwrite( recdata, reclen, 1, outfp ) != 1 )
|
||||
return ERR;
|
||||
return OK;
|
||||
}
|
||||
/* internal: read IC35 binary record from file
|
||||
* -------------------------------------------
|
||||
*/
|
||||
static int
|
||||
_bin_readrec( FILE * infp, IC35REC * rec )
|
||||
{
|
||||
struct binrec brec;
|
||||
uchar * rbuff;
|
||||
size_t rlen, i;
|
||||
|
||||
if ( fread( &brec, sizeof(brec), 1, infp ) != 1 )
|
||||
return -1;
|
||||
set_ic35recid( rec, brec.rid );
|
||||
set_ic35recchg( rec, brec.chg );
|
||||
rlen = brec.len - sizeof(brec);
|
||||
if ( rlen > 0
|
||||
&& (rbuff = malloc( rlen )) != NULL ) {
|
||||
if ( fread( rbuff, rlen, 1, infp ) == 1 )
|
||||
set_ic35recdata( rec, rbuff, rlen );
|
||||
else
|
||||
rlen = ERR;
|
||||
free( rbuff );
|
||||
} else {
|
||||
for ( i = 0; i < rlen; ++i )
|
||||
(void)fgetc( infp );
|
||||
}
|
||||
return rlen;
|
||||
}
|
||||
|
||||
/* open IC35 binary record file
|
||||
* ----------------------------
|
||||
* read input file into internal record list
|
||||
*/
|
||||
static char * iomode;
|
||||
static char * addr_fname;
|
||||
|
||||
static int
|
||||
bin_open( char * mode, char * addrfname, char * vcalfname, char * memofname )
|
||||
{
|
||||
FILE * infp;
|
||||
IC35REC * ic35rec;
|
||||
struct binelmt * newelmt;
|
||||
struct binelmt * pelmt;
|
||||
|
||||
LPRINTF(( L_INFO, "bin_open(%s,%s,%s)",
|
||||
addrfname ? addrfname : "NULL",
|
||||
vcalfname ? vcalfname : "NULL",
|
||||
memofname ? memofname : "NULL" ));
|
||||
iomode = mode; /* note input/output for close */
|
||||
addr_fname = addrfname; /* note filename for close */
|
||||
binlist = binget = NULL; /* reset record list */
|
||||
if ( !( addrfname && *addrfname )
|
||||
|| iomode[0] != 'r' ) /* open for output only */
|
||||
return OK;
|
||||
if ( strcmp( addrfname, "-" ) == 0 )
|
||||
infp = stdin;
|
||||
else if ( (infp = fopen( addrfname, "r" )) == NULL )
|
||||
return access( addrfname, F_OK ) == 0 ? ERR : OK;
|
||||
LPRINTF(( L_INFO, "bin_open: read %s ..", addrfname ));
|
||||
pelmt = NULL;
|
||||
for ( ; ; ) {
|
||||
if ( (ic35rec = new_ic35rec()) == NULL
|
||||
|| _bin_readrec( infp, ic35rec ) < 0 )
|
||||
break;
|
||||
if ( (newelmt = malloc( sizeof(*newelmt) )) != NULL ) {
|
||||
newelmt->next = NULL;
|
||||
newelmt->rec = ic35rec;
|
||||
if ( pelmt == NULL )
|
||||
binlist = pelmt = newelmt;
|
||||
else
|
||||
pelmt = pelmt->next = newelmt;
|
||||
}
|
||||
}
|
||||
if ( infp != stdin )
|
||||
fclose( infp );
|
||||
del_ic35rec( ic35rec );
|
||||
LPRINTF(( L_INFO, "bin_open: read %s done", addrfname ));
|
||||
return OK;
|
||||
}
|
||||
/* close IC35 binary record file
|
||||
* -----------------------------
|
||||
* write internal record list to output file
|
||||
* if closing input file only release record list
|
||||
*/
|
||||
static void
|
||||
bin_close( void )
|
||||
{
|
||||
FILE * outfp = NULL;
|
||||
struct binelmt * delelmt;
|
||||
|
||||
if ( addr_fname && *addr_fname
|
||||
&& (iomode[0] == 'w' || iomode[1] == '+')
|
||||
&& (outfp = backup_and_openwr( addr_fname )) == NULL )
|
||||
return;
|
||||
LPRINTF(( L_INFO, "bin_close: %s",
|
||||
outfp && binlist ? "write .." : "no output" ));
|
||||
LPRINTF(( L_INFO, "bin_close: write %s ..", addr_fname ));
|
||||
while ( binlist ) {
|
||||
if ( outfp )
|
||||
_bin_writerec( outfp, binlist->rec );
|
||||
delelmt = binlist;
|
||||
binlist = binlist->next;
|
||||
del_ic35rec( delelmt->rec );
|
||||
free( delelmt );
|
||||
}
|
||||
binget = NULL; /* sanity for bin_getrec() */
|
||||
if ( outfp && outfp != stdout )
|
||||
fclose( outfp );
|
||||
LPRINTF(( L_INFO, "bin_close: done" ));
|
||||
}
|
||||
|
||||
/* rewind list of binary records
|
||||
* -----------------------------
|
||||
*/
|
||||
static void
|
||||
bin_rewind( void )
|
||||
{
|
||||
binget = NULL;
|
||||
}
|
||||
|
||||
/* get binary record for fileid
|
||||
* ----------------------------
|
||||
*/
|
||||
static IC35REC *
|
||||
bin_getrec( int fileid )
|
||||
{
|
||||
if ( binget == NULL )
|
||||
binget = binlist;
|
||||
else
|
||||
binget = binget->next;
|
||||
while ( binget ) {
|
||||
if ( fileid == FILE_ANY /* next record with any fileid */
|
||||
|| FileId( ic35recid( binget->rec ) ) == fileid )
|
||||
return binget->rec;
|
||||
binget = binget->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/* get binary record by record-ID
|
||||
* ------------------------------
|
||||
*/
|
||||
static IC35REC *
|
||||
bin_getrec_byID( ulong recid )
|
||||
{
|
||||
struct binelmt * pelmt;
|
||||
|
||||
if ( RecId( recid ) == 0 )
|
||||
return NULL;
|
||||
for ( pelmt = binlist; pelmt; pelmt = pelmt->next )
|
||||
if ( ic35recid( pelmt->rec ) == recid )
|
||||
return pelmt->rec;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* compare IC35 record with binary record
|
||||
* --------------------------------------
|
||||
*/
|
||||
static int
|
||||
bin_cmpic35rec( IC35REC * ic35rec, IC35REC * binrec )
|
||||
{
|
||||
return cmp_ic35rec( ic35rec, binrec );
|
||||
}
|
||||
|
||||
/* update IC35 record with binary record
|
||||
* -------------------------------------
|
||||
*/
|
||||
static IC35REC *
|
||||
bin_updic35rec( IC35REC * ic35rec, IC35REC * rec )
|
||||
{
|
||||
uchar * data;
|
||||
size_t dlen;
|
||||
|
||||
if ( ic35rec == NULL
|
||||
&& (ic35rec = new_ic35rec()) == NULL )
|
||||
return NULL;
|
||||
set_ic35recid( ic35rec, ic35recid( rec ) );
|
||||
get_ic35recdata( rec, &data, &dlen );
|
||||
set_ic35recdata( ic35rec, data, dlen );
|
||||
return ic35rec;
|
||||
}
|
||||
|
||||
/* put IC35 record to (new) binary record
|
||||
* --------------------------------------
|
||||
*/
|
||||
static IC35REC *
|
||||
bin_putic35rec( IC35REC * ic35rec )
|
||||
{
|
||||
struct binelmt * pelmt;
|
||||
struct binelmt * newelmt;
|
||||
struct binelmt * lastinfile;
|
||||
struct binelmt * last;
|
||||
IC35REC * rec;
|
||||
uchar * data;
|
||||
size_t dlen;
|
||||
|
||||
if ( (rec = bin_getrec_byID( ic35recid( ic35rec ) )) == NULL ) {
|
||||
if ( (newelmt = malloc( sizeof(*newelmt) )) == NULL
|
||||
|| (rec = newelmt->rec = new_ic35rec()) == NULL ) {
|
||||
free( newelmt );
|
||||
return NULL;
|
||||
}
|
||||
last = lastinfile = NULL;
|
||||
for ( pelmt = binlist; pelmt; pelmt = pelmt->next ) {
|
||||
if ( FileId( ic35recid( pelmt->rec ) )
|
||||
== FileId( ic35recid( ic35rec ) ) )
|
||||
lastinfile = pelmt;
|
||||
last = pelmt;
|
||||
}
|
||||
if ( lastinfile ) last = lastinfile;
|
||||
if ( last == NULL ) {
|
||||
binlist = newelmt;
|
||||
newelmt->next = NULL;
|
||||
} else {
|
||||
newelmt->next = last->next;
|
||||
last->next = newelmt;
|
||||
}
|
||||
}
|
||||
set_ic35recid( rec, ic35recid( ic35rec ) );
|
||||
get_ic35recdata( ic35rec, &data, &dlen );
|
||||
set_ic35recdata( rec, data, dlen );
|
||||
return rec;
|
||||
}
|
||||
|
||||
/* delete binary record
|
||||
* --------------------
|
||||
*/
|
||||
static void
|
||||
bin_delrec( IC35REC * delrec )
|
||||
{
|
||||
struct binelmt ** pnext;
|
||||
struct binelmt * pelmt;
|
||||
|
||||
for ( pnext = &binlist, pelmt = *pnext; pelmt != NULL;
|
||||
pnext = &pelmt->next, pelmt = *pnext )
|
||||
if ( pelmt->rec == delrec ) {
|
||||
*pnext = pelmt->next;
|
||||
del_ic35rec( pelmt->rec );
|
||||
free( pelmt );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* get,set binary record-ID
|
||||
* ------------------------
|
||||
*/
|
||||
static ulong
|
||||
bin_recid( IC35REC * rec )
|
||||
{
|
||||
return ic35recid( rec );
|
||||
}
|
||||
static void
|
||||
bin_set_recid( IC35REC * rec, ulong recid )
|
||||
{
|
||||
set_ic35recid( rec, recid );
|
||||
}
|
||||
|
||||
/* get,set binary record status
|
||||
* ----------------------------
|
||||
*/
|
||||
static int
|
||||
bin_recstat( IC35REC * rec )
|
||||
{
|
||||
switch ( ic35recchg( rec ) ) {
|
||||
case IC35_CLEAN: return PIM_CLEAN;
|
||||
case IC35_NEW:
|
||||
case IC35_MOD: return PIM_DIRTY;
|
||||
case IC35_DEL: return PIM_DEL;
|
||||
}
|
||||
return PIM_DIRTY;
|
||||
}
|
||||
static void
|
||||
bin_set_recstat( IC35REC * rec, int stat )
|
||||
{
|
||||
switch ( stat ) {
|
||||
case PIM_CLEAN: set_ic35recchg( rec, IC35_CLEAN ); break;
|
||||
case PIM_DIRTY: set_ic35recchg( rec, IC35_NEW ); break;
|
||||
case PIM_DEL: set_ic35recchg( rec, IC35_DEL ); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* binary format operations
|
||||
* ------------------------
|
||||
*/
|
||||
struct pim_oper bin_oper = {
|
||||
bin_open,
|
||||
bin_close,
|
||||
bin_rewind,
|
||||
(void*(*)(int))bin_getrec,
|
||||
(void*(*)(ulong))bin_getrec_byID,
|
||||
(int(*)(IC35REC*,void*))bin_cmpic35rec,
|
||||
(IC35REC*(*)(IC35REC*,void*))bin_updic35rec,
|
||||
(void*(*)(IC35REC*))bin_putic35rec,
|
||||
(void(*)(void*))bin_delrec,
|
||||
(ulong(*)(void*))bin_recid,
|
||||
(void(*)(void*,ulong))bin_set_recid,
|
||||
(int(*)(void*))bin_recstat,
|
||||
(void(*)(void*,int))bin_set_recstat,
|
||||
};
|
||||
|
|
@ -0,0 +1,428 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* */
|
||||
static char rcsid[] =
|
||||
"$Id: dataio.c,v 1.33 2001/03/02 02:09:59 tsch Rel $"; /*
|
||||
* *
|
||||
* IC35 synchronize data import/export *
|
||||
* *
|
||||
*************************************************************************
|
||||
* *
|
||||
* ??? is "fixme" mark: sections of code needing fixes *
|
||||
* *
|
||||
* backup_and_openwr backup and open output file for write *
|
||||
* revised date+time on IC35 *
|
||||
* clr_newic35dt clear new IC35 revised to get it fresh *
|
||||
* get_newic35dt new revised date+time to IC35 string *
|
||||
* set_oldic35dt IC35 string to old revised date+time *
|
||||
* *
|
||||
* PIM format
|
||||
* pimfmt2bin local: PIM format text to binary
|
||||
* set_pim_format set PIM format
|
||||
* pim_format report current PIM format
|
||||
* pimop[] functions table of format-specific ops
|
||||
* PIM file access
|
||||
* pim_open open PIMfile(s) and read if present
|
||||
* pim_openinp open PIMfile(s) for input and read
|
||||
* pim_openout note PIMfile(s) for output
|
||||
* pim_close close and flush to PIMfile(s)
|
||||
* PIM record operations
|
||||
* pim_rewind rewind PIM record list
|
||||
* pim_getrec get next PIM record for fileid
|
||||
* pim_getrec_byID get PIM record by rec-ID (and fileid)
|
||||
* pim_updic35rec update IC35 record with PIM record
|
||||
* pim_cmpic35rec compare IC35 record with PIM record
|
||||
* pim_putic35rec put IC35 record to (new) PIM record
|
||||
* pim_putrec output (new) PIM record
|
||||
* pim_delrec delete PIM record
|
||||
* PIM record IC35-recID and status
|
||||
* pim_recid report IC35 record-ID from PIM record
|
||||
* pim_set_recid set IC35 record-ID to PIM record
|
||||
* pim_recstat report PIM record changeflag
|
||||
* pim_set_recstat set PIM record changeflag
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include <stdio.h> /* fprintf(), .. */
|
||||
#include <string.h> /* strcpy(), .. */
|
||||
#include <ctype.h> /* isprint(), .. */
|
||||
#include <unistd.h> /* access() */
|
||||
#include <sys/types.h> /* size_t, .. */
|
||||
#include <time.h> /* struct tm, time() .. */
|
||||
|
||||
#include "vcc.h" /* VObject, .. */
|
||||
#include "util.h" /* ERR, uchar, .. */
|
||||
#include "ic35frec.h" /* IC35 record fields.. */
|
||||
#include "dataio.h"
|
||||
NOTUSED(rcsid);
|
||||
|
||||
|
||||
/* backup and open output file for write
|
||||
* -------------------------------------
|
||||
*/
|
||||
FILE *
|
||||
backup_and_openwr( char * fname )
|
||||
{
|
||||
char * bkpfname;
|
||||
FILE * fp;
|
||||
|
||||
if ( !( fname && *fname ) )
|
||||
return NULL;
|
||||
if ( strcmp( fname, "-" ) == 0 )
|
||||
return stdout;
|
||||
if ( (bkpfname = malloc( strlen( fname ) + 2 )) != NULL ) {
|
||||
strcat( strcpy( bkpfname, fname ), "~" );
|
||||
remove( bkpfname );
|
||||
rename( fname, bkpfname );
|
||||
free( bkpfname );
|
||||
}
|
||||
if ( (fp = fopen( fname, "w" )) == NULL )
|
||||
error( "cannot open outfile: %s", fname );
|
||||
return fp;
|
||||
}
|
||||
|
||||
|
||||
/* ============================================ */
|
||||
/* revised date+time on IC35 */
|
||||
/* ============================================ */
|
||||
|
||||
/*
|
||||
* IC35 does not maintain last modified date+time per record
|
||||
* instead there is a command to write date+time to IC35,
|
||||
* which is used for synchronization.
|
||||
* this timestamp is also used for "last modified" VObject property
|
||||
*/
|
||||
|
||||
/* revised date+time for vCard,vCal records
|
||||
* ----------------------------------------
|
||||
*/
|
||||
static time_t _new_ic35dtime; /* to vCard,vCal records and IC35 */
|
||||
|
||||
void
|
||||
clr_newic35dt( void )
|
||||
{
|
||||
_new_ic35dtime = 0;
|
||||
}
|
||||
time_t
|
||||
newic35dt( void )
|
||||
{
|
||||
if ( _new_ic35dtime == 0 )
|
||||
_new_ic35dtime = time( NULL );
|
||||
return _new_ic35dtime;
|
||||
}
|
||||
|
||||
/* new revised date+time to string for IC35
|
||||
* ----------------------------------------
|
||||
*/
|
||||
void
|
||||
get_newic35dt( char * dtbuf )
|
||||
{
|
||||
time_t ic35dt;
|
||||
struct tm * ptm;
|
||||
|
||||
ic35dt = newic35dt();
|
||||
ptm = localtime( &ic35dt );
|
||||
strftime( dtbuf, 2+2+4+2+2+2+1, "%m%d%Y%H%M%S", ptm );
|
||||
}
|
||||
|
||||
/* string from IC35 to old revised date+time
|
||||
* -----------------------------------------
|
||||
* the ugly format [mmddyyyyhhmmss] (instead of pretty [yyyymmddhhmmss])
|
||||
* is used for reasons of compatibility with IC35sync/Windows.
|
||||
* if sysinfo string from IC35 lacks plausible year,month,day, assume
|
||||
* sysinfo was never written to IC35 and use old reference date+time
|
||||
* far in the past.
|
||||
*/
|
||||
static time_t _old_ic35dtime; /* from IC35, reference for vCard */
|
||||
|
||||
void
|
||||
set_oldic35dt( char * dtime )
|
||||
{
|
||||
struct tm ic35tm;
|
||||
|
||||
if ( dtime == NULL )
|
||||
return;
|
||||
memset( &ic35tm, 0, sizeof(ic35tm) );
|
||||
sscanf( dtime, "%2d%2d%4d%2d%2d%2d",
|
||||
&ic35tm.tm_mon, &ic35tm.tm_mday, &ic35tm.tm_year,
|
||||
&ic35tm.tm_hour, &ic35tm.tm_min, &ic35tm.tm_sec );
|
||||
if ( 1970 <= ic35tm.tm_year
|
||||
&& 1 <= ic35tm.tm_mon && ic35tm.tm_mon <= 12
|
||||
&& 1 <= ic35tm.tm_mday && ic35tm.tm_mday <= 31 ) {
|
||||
ic35tm.tm_year -= 1900;
|
||||
ic35tm.tm_mon -= 1;
|
||||
ic35tm.tm_isdst = -1;
|
||||
_old_ic35dtime = mktime( &ic35tm );
|
||||
} else
|
||||
_old_ic35dtime = 1;
|
||||
}
|
||||
time_t
|
||||
oldic35dt( void )
|
||||
{
|
||||
return _old_ic35dtime;
|
||||
}
|
||||
|
||||
|
||||
/* ============================================ */
|
||||
/* generic PIM access */
|
||||
/* ============================================ */
|
||||
|
||||
/* set, get format of input/output file(s)
|
||||
* ---------------------------------------
|
||||
*/
|
||||
static int pimfmt;
|
||||
static int inpfmt;
|
||||
|
||||
static int
|
||||
pimfmt2bin( char * format )
|
||||
{
|
||||
if ( format ) {
|
||||
if ( strcmp( format, "txt" ) == 0 ) return PIM_TXT;
|
||||
else if ( strcmp( format, "bin" ) == 0 ) return PIM_BIN;
|
||||
else if ( strcmp( format, "vca" ) == 0 ) return PIM_VCA;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
set_pim_format( char * format )
|
||||
{
|
||||
int newfmt;
|
||||
|
||||
if ( (newfmt = pimfmt2bin( format )) <= 0 )
|
||||
return ERR; /* unknown format */
|
||||
pimfmt = inpfmt = newfmt;
|
||||
return OK;
|
||||
}
|
||||
int
|
||||
pim_format( void )
|
||||
{
|
||||
return pimfmt;
|
||||
}
|
||||
|
||||
/*
|
||||
* pim_open()
|
||||
* pim_close()
|
||||
* pim_rewind()
|
||||
*
|
||||
* pim_getrec( int fileid ) -> void* / NULL
|
||||
* pim_getrec_byID( ulong recid ) -> void* / NULL
|
||||
* pim_cmpic35rec( IC35REC*, void* ) -> 0:same 1:differ
|
||||
* pim_putic35rec( IC35REC* ) IC35REC to PIMrec
|
||||
* pim_updic35rec( IC35REC*, void* ) PIMrec to IC35REC
|
||||
* pim_delrec( void* )
|
||||
*
|
||||
* pim_recid( void* )
|
||||
* pim_set_recid( void*, ulong )
|
||||
* pim_recstat( void* )
|
||||
* pim_set_recstat( void*, int )
|
||||
*/
|
||||
|
||||
/* dummy null operations
|
||||
* ---------------------
|
||||
*/
|
||||
static struct pim_oper nul_oper = {
|
||||
NULL, /* NO open */
|
||||
NULL, /* NO close */
|
||||
NULL, /* NO rewind */
|
||||
NULL, /* NO getrec */
|
||||
NULL, /* NO getrec_byID */
|
||||
NULL, /* NO cmpic35rec */
|
||||
NULL, /* NO updic35rec */
|
||||
NULL, /* NO putic35rec */
|
||||
NULL, /* NO delrec */
|
||||
NULL, /* NO recid */
|
||||
NULL, /* NO set_recid */
|
||||
NULL, /* NO recstat */
|
||||
NULL, /* NO set_recstat */
|
||||
};
|
||||
|
||||
/* table of supported PIM-formats
|
||||
* ------------------------------
|
||||
*/
|
||||
extern struct pim_oper txt_oper; /* text output IC35 record */
|
||||
extern struct pim_oper bin_oper; /* binary IC35 record format */
|
||||
extern struct pim_oper vca_oper; /* vCard,vCalendar format */
|
||||
|
||||
static struct pim_oper *pimop[] = {
|
||||
&nul_oper,
|
||||
&txt_oper,
|
||||
&bin_oper,
|
||||
&vca_oper
|
||||
};
|
||||
|
||||
/* open, close, rewind output file(s)
|
||||
* ----------------------------------
|
||||
*/
|
||||
int
|
||||
pim_open( char * addrfname, char * vcalfname, char * memofname )
|
||||
{
|
||||
LPRINTF(( L_INFO, "pim_open(%s,%s,%s) pimfmt=%d (%s)",
|
||||
addrfname ? addrfname : "NULL",
|
||||
vcalfname ? vcalfname : "NULL",
|
||||
memofname ? memofname : "NULL",
|
||||
pimfmt, pimfmt == PIM_TXT ? "txt" :
|
||||
pimfmt == PIM_BIN ? "bin" :
|
||||
pimfmt == PIM_VCA ? "vca" : "unknown" ));
|
||||
/*??? check file(s) creatable in dirname(a_xxxxfname) ???*/
|
||||
if ( pimop[pimfmt]->open )
|
||||
return (*pimop[pimfmt]->open)( "r+", addrfname, vcalfname, memofname );
|
||||
return ERR;
|
||||
}
|
||||
int
|
||||
pim_openinp( char * format, char * fname )
|
||||
{
|
||||
int ifmt;
|
||||
|
||||
if ( (ifmt = pimfmt2bin( format )) <= 0
|
||||
|| pimop[ifmt]->open == NULL )
|
||||
return ERR;
|
||||
inpfmt = ifmt;
|
||||
return (*pimop[inpfmt]->open)( "r", fname, NULL, NULL );
|
||||
}
|
||||
int
|
||||
pim_openout( char * format, char * fname )
|
||||
{
|
||||
int ofmt;
|
||||
|
||||
if ( (ofmt = pimfmt2bin( format )) <= 0
|
||||
|| pimop[ofmt]->open == NULL
|
||||
|| !( fname && *fname ) )
|
||||
return ERR;
|
||||
pimfmt = ofmt;
|
||||
/*??? check file creatable in dirname(fname) ???*/
|
||||
remove( fname );
|
||||
return (*pimop[pimfmt]->open)( "w", fname, NULL, NULL );
|
||||
}
|
||||
void
|
||||
pim_close( void )
|
||||
{
|
||||
LPRINTF(( L_INFO, "pim_close: pimfmt=%d (%s) inpfmt=%d (%s)",
|
||||
pimfmt, pimfmt == PIM_TXT ? "txt" :
|
||||
pimfmt == PIM_BIN ? "bin" :
|
||||
pimfmt == PIM_VCA ? "vca" : "unknown",
|
||||
inpfmt, inpfmt == PIM_TXT ? "txt" :
|
||||
inpfmt == PIM_BIN ? "bin" :
|
||||
inpfmt == PIM_VCA ? "vca" : "unknown" ));
|
||||
if ( pimop[pimfmt]->close ) /* write output file and .. */
|
||||
(*pimop[pimfmt]->close)(); /* release output record list */
|
||||
if ( inpfmt != pimfmt /* input format is different .. */
|
||||
&& *pimop[inpfmt]->close ) /* release input record list */
|
||||
(*pimop[inpfmt]->close)();
|
||||
}
|
||||
void
|
||||
pim_rewind( void )
|
||||
{
|
||||
if ( pimop[inpfmt]->rewind )
|
||||
(*pimop[inpfmt]->rewind)();
|
||||
}
|
||||
|
||||
/* get next PIM-record for fileid
|
||||
* ------------------------------
|
||||
*/
|
||||
void *
|
||||
pim_getrec( int fileid )
|
||||
{
|
||||
if ( pimop[inpfmt]->getrec )
|
||||
return (*pimop[inpfmt]->getrec)( fileid );
|
||||
return NULL;
|
||||
}
|
||||
/* get PIM-record by rec-ID for fileid
|
||||
* -----------------------------------
|
||||
*/
|
||||
void *
|
||||
pim_getrec_byID( ulong recid )
|
||||
{
|
||||
if ( pimop[inpfmt]->getrec_byID )
|
||||
return (*pimop[inpfmt]->getrec_byID)( recid );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* update IC35 record with PIM record
|
||||
* ----------------------------------
|
||||
*/
|
||||
IC35REC *
|
||||
pim_updic35rec( IC35REC * ic35rec, void * pimrec )
|
||||
{
|
||||
if ( pimop[inpfmt]->updic35rec )
|
||||
return (*pimop[inpfmt]->updic35rec)( ic35rec, pimrec );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* compare IC35 record with vCard,vCal record
|
||||
* ------------------------------------------
|
||||
*/
|
||||
int
|
||||
pim_cmpic35rec( IC35REC * ic35rec, void * pimrec )
|
||||
{
|
||||
if ( pimop[pimfmt]->cmpic35rec )
|
||||
return (*pimop[pimfmt]->cmpic35rec)( ic35rec, pimrec );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* put IC35-record to (new) PIM-record
|
||||
* -----------------------------------
|
||||
*/
|
||||
void *
|
||||
pim_putic35rec( IC35REC * ic35rec )
|
||||
{
|
||||
if ( pimop[pimfmt]->putic35rec )
|
||||
return (*pimop[pimfmt]->putic35rec)( ic35rec );
|
||||
return NULL;
|
||||
}
|
||||
void
|
||||
pim_putrec( void * pimrec )
|
||||
{
|
||||
IC35REC * ic35rec;
|
||||
|
||||
if ( pimop[inpfmt]->updic35rec != NULL
|
||||
&& pimop[pimfmt]->putic35rec != NULL
|
||||
&& (ic35rec = new_ic35rec()) != NULL ) {
|
||||
(*pimop[inpfmt]->updic35rec)( ic35rec, pimrec );
|
||||
(*pimop[pimfmt]->putic35rec)( ic35rec );
|
||||
del_ic35rec( ic35rec );
|
||||
}
|
||||
}
|
||||
|
||||
/* delete PIM-record
|
||||
* -----------------
|
||||
*/
|
||||
void
|
||||
pim_delrec( void * pimrec )
|
||||
{
|
||||
if ( pimop[pimfmt]->delrec )
|
||||
(*pimop[pimfmt]->delrec)( pimrec );
|
||||
}
|
||||
|
||||
/* get,set IC35-record-ID
|
||||
* ----------------------
|
||||
*/
|
||||
ulong
|
||||
pim_recid( void * pimrec )
|
||||
{
|
||||
if ( pimop[pimfmt]->recid )
|
||||
return (*pimop[pimfmt]->recid)( pimrec );
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
pim_set_recid( void * pimrec, ulong recid )
|
||||
{
|
||||
if ( pimop[pimfmt]->set_recid )
|
||||
(*pimop[pimfmt]->set_recid)( pimrec, recid );
|
||||
}
|
||||
|
||||
/* get,set record-changeflag
|
||||
* -------------------------
|
||||
*/
|
||||
int
|
||||
pim_recstat( void * pimrec )
|
||||
{
|
||||
if ( pimop[pimfmt]->recstat )
|
||||
return (*pimop[pimfmt]->recstat)( pimrec );
|
||||
return PIM_DIRTY;
|
||||
}
|
||||
void
|
||||
pim_set_recstat( void * pimrec, int stat )
|
||||
{
|
||||
if ( pimop[pimfmt]->set_recstat )
|
||||
(*pimop[pimfmt]->set_recstat)( pimrec, stat );
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* *
|
||||
* $Id: dataio.h,v 1.12 2000/12/26 01:25:22 tsch Rel $ *
|
||||
* *
|
||||
* header for IC35 data import/export *
|
||||
* *
|
||||
************************************************************************/
|
||||
#ifndef _DATAIO_H
|
||||
#define _DATAIO_H 1
|
||||
|
||||
#include <stdio.h> /* FILE */
|
||||
#include <sys/types.h> /* size_t */
|
||||
|
||||
#include "vcc.h" /* VObject, .. */
|
||||
#include "ic35frec.h" /* IC35REC */
|
||||
#include "util.h" /* uchar, .. */
|
||||
|
||||
|
||||
/* PIM file format ids */
|
||||
#define PIM_TXT 1 /* plain text */
|
||||
#define PIM_BIN 2 /* raw binary data */
|
||||
#define PIM_VCA 3 /* vCard,vCalendar,Memo */
|
||||
/* PIM record status */
|
||||
#define PIM_CLEAN 0
|
||||
#define PIM_DIRTY 1
|
||||
#define PIM_DEL 3
|
||||
|
||||
|
||||
struct pim_oper { /* table of record format specific functions */
|
||||
int (*open)( char *, char *, char *, char * );
|
||||
void (*close)( void );
|
||||
void (*rewind)( void );
|
||||
void * (*getrec)( int );
|
||||
void * (*getrec_byID)( ulong );
|
||||
int (*cmpic35rec)( IC35REC *, void * ); /* IC35 == PIM */
|
||||
IC35REC * (*updic35rec)( IC35REC *, void * ); /* IC35 <- PIM */
|
||||
void * (*putic35rec)( IC35REC * ); /* IC35 -> PIM */
|
||||
void (*delrec)( void * );
|
||||
ulong (*recid)( void * );
|
||||
void (*set_recid)( void *, ulong );
|
||||
int (*recstat)( void * );
|
||||
void (*set_recstat)( void *, int );
|
||||
};
|
||||
|
||||
|
||||
FILE * backup_and_openwr( char * fname );
|
||||
|
||||
int set_pim_format( char * format );
|
||||
int pim_format( void );
|
||||
|
||||
void clr_newic35dt( void );
|
||||
void get_newic35dt( char * dtbuf );
|
||||
time_t newic35dt( void );
|
||||
void set_oldic35dt( char * dtime );
|
||||
time_t oldic35dt( void );
|
||||
|
||||
int pim_open( char * addrfname, char * vcalfname, char * memofname );
|
||||
int pim_openinp( char * format, char * fname );
|
||||
int pim_openout( char * format, char * fname );
|
||||
void pim_close( void );
|
||||
void pim_rewind( void );
|
||||
|
||||
void * pim_getrec( int fileid );
|
||||
void * pim_getrec_byID( ulong recid );
|
||||
void * pim_putic35rec( IC35REC * ic35rec );
|
||||
IC35REC * pim_updic35rec( IC35REC * ic35rec, void * pimrec );
|
||||
int pim_cmpic35rec( IC35REC * ic35rec, void * pimrec );
|
||||
void pim_putrec( void * pimrec );
|
||||
void pim_delrec( void * pimrec );
|
||||
|
||||
ulong pim_recid( void * pimrec );
|
||||
void pim_set_recid( void * pimrec, ulong recid );
|
||||
int pim_recstat( void * pimrec );
|
||||
void pim_set_recstat( void * pimrec, int stat );
|
||||
|
||||
#endif /*_DATAIO_H*/
|
|
@ -0,0 +1,113 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* */
|
||||
static char rcsid[] =
|
||||
"$Id: datatxt.c,v 1.32 2000/12/26 01:36:32 tsch Rel $"; /*
|
||||
* *
|
||||
* IC35 synchronize data import/export: text format output *
|
||||
* *
|
||||
*************************************************************************
|
||||
* *
|
||||
* ??? is "fixme" mark: sections of code needing fixes *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include <stdio.h> /* fprintf(), .. */
|
||||
#include <ctype.h> /* isprint(), .. */
|
||||
#include <sys/types.h> /* size_t, .. */
|
||||
|
||||
#include "util.h" /* ERR, uchar, .. */
|
||||
#include "ic35frec.h" /* IC35 record fields.. */
|
||||
#include "dataio.h" /* struct pim_oper */
|
||||
NOTUSED(rcsid);
|
||||
|
||||
|
||||
/* open, close text file
|
||||
* ---------------------
|
||||
*/
|
||||
static FILE * outfp;
|
||||
|
||||
static int
|
||||
txt_open( char * mode, char * addrfname, char * vcalfname, char * memofname )
|
||||
{
|
||||
if ( !(mode[0] == 'w' || mode[1] == '+')
|
||||
|| (outfp = backup_and_openwr( addrfname )) == NULL )
|
||||
return ERR;
|
||||
return OK;
|
||||
}
|
||||
static void
|
||||
txt_close( void )
|
||||
{
|
||||
if ( outfp && outfp != stdout )
|
||||
fclose( outfp );
|
||||
outfp = NULL;
|
||||
}
|
||||
|
||||
/* output IC35 record as text
|
||||
* --------------------------
|
||||
*/
|
||||
static IC35REC *
|
||||
txt_putic35rec( IC35REC * rec )
|
||||
{
|
||||
static int lastfileid = -1;
|
||||
static int idx;
|
||||
int fileid;
|
||||
int fi, i;
|
||||
uchar * fld;
|
||||
size_t len;
|
||||
|
||||
fileid = FileId( ic35recid( rec ) );
|
||||
if ( ic35fname( fileid ) == NULL )
|
||||
return NULL; /* unknown file id */
|
||||
if ( fileid != lastfileid ) { /* first/next IC35 file */
|
||||
fprintf( outfp, "\nFile \"%s\"\n", ic35fname( fileid ) );
|
||||
lastfileid = fileid;
|
||||
idx = 0; /* reset record index */
|
||||
} else { /* same IC35 file */
|
||||
++idx; /* increment rec.index */
|
||||
}
|
||||
get_ic35recdata( rec, NULL, &len );
|
||||
fprintf(outfp,"File \"%s\" Record %3d IC35id=%08lX cflag=%02X length=%d\n",
|
||||
ic35fname(fileid), idx, ic35recid(rec), ic35recchg(rec), len);
|
||||
for ( fi = 0; fi < ic35fnflds( fileid ); ++fi ) {
|
||||
get_ic35recfld( rec, FILEfld(fileid,fi), &fld, &len );
|
||||
fprintf( outfp, "f%d(%d)\t", fi, len );
|
||||
if ( len != 0 ) {
|
||||
fprintf( outfp, "\"" );
|
||||
for ( i = 0; i < len; ++i ) {
|
||||
if ( isprint( fld[i] ) )
|
||||
fprintf( outfp, "%c", fld[i] );
|
||||
else
|
||||
fprintf( outfp, "\\x%02X", (uchar)fld[i] );
|
||||
if ( 0 < i && i < len - 1
|
||||
&& fld[i-1] == '\r' && fld[i] == '\n' )
|
||||
fprintf( outfp, "\"\n\t\"" );
|
||||
}
|
||||
fprintf( outfp, "\"\n" );
|
||||
} else {
|
||||
fprintf( outfp, "<EMPTY>\n" );
|
||||
}
|
||||
}
|
||||
return rec;
|
||||
}
|
||||
|
||||
|
||||
/* text format operations
|
||||
* ----------------------
|
||||
*/
|
||||
struct pim_oper txt_oper = {
|
||||
txt_open,
|
||||
txt_close,
|
||||
NULL, /* NO rewind */
|
||||
NULL, /* NO getrec */
|
||||
NULL, /* NO getrec_byID */
|
||||
NULL, /* NO cmpic35rec */
|
||||
NULL, /* NO updic35rec */
|
||||
(void*(*)(IC35REC*))txt_putic35rec,
|
||||
NULL, /* NO delrec */
|
||||
NULL, /* NO recid */
|
||||
NULL, /* NO set_recid */
|
||||
NULL, /* NO recstat */
|
||||
NULL, /* NO set_recstat */
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,199 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2001 Thomas Schulz *
|
||||
* */
|
||||
static char rcsid[] =
|
||||
"$Id: genproto.c,v 1.2 2001/01/21 19:54:52 tsch Rel $"; /*
|
||||
* *
|
||||
* general IC35 protocol support *
|
||||
* *
|
||||
*************************************************************************
|
||||
* *
|
||||
* ??? is "fixme" mark: sections of code needing fixes *
|
||||
* *
|
||||
* utilities for PDU encode/decode *
|
||||
* putbyte encode one byte *
|
||||
* putword encode 2byte-word *
|
||||
* putdword encode 4byte-doubleword *
|
||||
* putbtxt encode binary text *
|
||||
* puttext encode text string *
|
||||
* puttxt0 encode text string plus trailing NUL-byte *
|
||||
* getbyte decode one byte *
|
||||
* getword decode 2byte-word *
|
||||
* getdword decode 4byte-doubleword *
|
||||
* getbtxt decode binary text *
|
||||
* gettext decode text string *
|
||||
* chksum calculate arithmetic checksum *
|
||||
* general communication *
|
||||
* welcome initial welcome handshake *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include <string.h> /* memcpy(), .. */
|
||||
#include <unistd.h> /* usleep() */
|
||||
#include <signal.h> /* SIG_INT, signal() */
|
||||
|
||||
#include "util.h" /* ERR,OK, uchar, .. */
|
||||
#include "comio.h" /* com_send(), .. */
|
||||
#include "genproto.h"
|
||||
NOTUSED(rcsid)
|
||||
|
||||
|
||||
/* ============================================ */
|
||||
/* utilities for PDU encode/decode */
|
||||
/* ============================================ */
|
||||
|
||||
/* encode data items to PDU
|
||||
* ------------------------
|
||||
*/
|
||||
void
|
||||
putbyte( uchar * pduptr, uchar byte )
|
||||
{
|
||||
*pduptr = byte;
|
||||
}
|
||||
void
|
||||
putword( uchar * pduptr, ushort word )
|
||||
{
|
||||
putbyte( pduptr+0, word & 0x00FF ); /* LSB first .. */
|
||||
putbyte( pduptr+1, (word & 0xFF00) >> 8 ); /* .. then MSB */
|
||||
}
|
||||
void
|
||||
putdword( uchar * pduptr, ulong dword )
|
||||
{
|
||||
putword( pduptr+0, dword & 0x0000FFFF );
|
||||
putword( pduptr+2, (dword & 0xFFFF0000) >> 16 );
|
||||
}
|
||||
void
|
||||
putbtxt( uchar * pduptr, uchar * text, size_t tlen )
|
||||
{
|
||||
memcpy( pduptr, text, tlen );
|
||||
}
|
||||
void
|
||||
puttext( uchar * pduptr, char * text )
|
||||
{
|
||||
putbtxt( pduptr, text, strlen( text ) );
|
||||
}
|
||||
void
|
||||
puttxt0( uchar * pduptr, char * text )
|
||||
{
|
||||
size_t len;
|
||||
|
||||
putbtxt( pduptr, text, len = strlen( text ) );
|
||||
pduptr[len] = '\0';
|
||||
}
|
||||
|
||||
/* decode data items from PDU
|
||||
* --------------------------
|
||||
*/
|
||||
uchar
|
||||
getbyte( uchar * pduptr )
|
||||
{
|
||||
return *pduptr;
|
||||
}
|
||||
ushort
|
||||
getword( uchar * pduptr )
|
||||
{
|
||||
return (getbyte( pduptr+1 ) << 8) | getbyte( pduptr+0 );
|
||||
}
|
||||
ulong
|
||||
getdword( uchar * pduptr )
|
||||
{
|
||||
return (getword( pduptr+2 ) << 16) | getword( pduptr+0 );
|
||||
}
|
||||
void
|
||||
getbtxt( uchar * pduptr, uchar * text, size_t tlen )
|
||||
{
|
||||
memcpy( text, pduptr, tlen );
|
||||
}
|
||||
void
|
||||
gettext( uchar * pduptr, char * text, size_t tlen )
|
||||
{
|
||||
getbtxt( pduptr, text, tlen );
|
||||
text[tlen] = '\0';
|
||||
}
|
||||
|
||||
/* calculate arithmetic checksum
|
||||
* -----------------------------
|
||||
*/
|
||||
ushort
|
||||
chksum( uchar * data, size_t dlen )
|
||||
{
|
||||
ushort checksum;
|
||||
size_t i;
|
||||
|
||||
for ( checksum = 0x0000, i = 0; i < dlen; ++i )
|
||||
checksum += data[i];
|
||||
return checksum;
|
||||
}
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* general communication */
|
||||
/* ==================================== */
|
||||
|
||||
/* welcome handshake
|
||||
* -----------------
|
||||
* send 'cmd' every 1.15 sec until "WELCOME" received
|
||||
* send 'cmd', wait for '\x80'
|
||||
* command byte 'cmd' is for:
|
||||
* - synchronize protocol '\x41'='A'
|
||||
* - manager protocol '\x40'='@'
|
||||
*/
|
||||
#define WELCOME_TIMEOUT 1150
|
||||
#define WELCOME_RETRY 20
|
||||
|
||||
#define RSP_READY (uchar)0x80
|
||||
#define GOT_NONE 0
|
||||
#define GOT_WELCOME 1
|
||||
#define GOT_READY 2
|
||||
|
||||
static int hadsignal;
|
||||
|
||||
static void
|
||||
_sig_hdlr( int signum )
|
||||
{
|
||||
hadsignal = signum;
|
||||
}
|
||||
|
||||
int
|
||||
welcome( uchar cmd )
|
||||
{
|
||||
char * welcome = "WELCOME";
|
||||
int old_tmo;
|
||||
int retry, rlen;
|
||||
int state;
|
||||
uchar rbuff[7];
|
||||
|
||||
hadsignal = 0;
|
||||
signal( SIGINT, _sig_hdlr );
|
||||
old_tmo = com_settimeout( WELCOME_TIMEOUT );
|
||||
for ( retry = 0, state = GOT_NONE;
|
||||
retry < WELCOME_RETRY && state != GOT_READY && hadsignal == 0;
|
||||
++retry ) {
|
||||
com_send( &cmd, 1 );
|
||||
switch ( state ) {
|
||||
case GOT_NONE:
|
||||
rlen = com_recv( rbuff, sizeof(rbuff) );
|
||||
if ( rlen < strlen(welcome) /* receive error / timeout */
|
||||
|| memcmp( rbuff, welcome, strlen(welcome) ) != 0 )
|
||||
continue; /* not enough or miss "WELCOME" */
|
||||
state = GOT_WELCOME;
|
||||
continue;
|
||||
case GOT_WELCOME:
|
||||
rlen = com_recv( rbuff, 1 );
|
||||
if ( rlen < 1 /* receive error / timeout */
|
||||
|| rbuff[0] != RSP_READY )
|
||||
continue; /* missing RSP_READY */
|
||||
state = GOT_READY;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
signal( SIGINT, SIG_DFL );
|
||||
com_settimeout( old_tmo );
|
||||
if ( hadsignal )
|
||||
return ERR_intr;
|
||||
if ( state != GOT_READY )
|
||||
return ERR;
|
||||
usleep( 50000 ); /* give IC35 50ms to get ready */
|
||||
return OK;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2001 Thomas Schulz *
|
||||
* *
|
||||
* $Id: genproto.h,v 1.2 2001/01/21 23:38:37 tsch Rel $ *
|
||||
* *
|
||||
* header for general IC35 protocol support *
|
||||
* *
|
||||
************************************************************************/
|
||||
#ifndef _GENPROTO_H
|
||||
#define _GENPROTO_H 1
|
||||
|
||||
#include "util.h" /* ushort, .. */
|
||||
|
||||
|
||||
/* communication error codes */
|
||||
#define ERR_intr -2 /* user interrupt with Ctl-C */
|
||||
#define ERR_recv -3 /* receive error */
|
||||
#define ERR_chksum -4 /* block checksum mismatch */
|
||||
#define ERR_acknak -5 /* ack/nak handshake failed */
|
||||
|
||||
|
||||
void putbyte( uchar * pduptr, uchar byte );
|
||||
void putword( uchar * pduptr, ushort word );
|
||||
void putdword( uchar * pduptr, ulong dword );
|
||||
void putbtxt( uchar * pduptr, uchar * text, size_t tlen );
|
||||
void puttext( uchar * pduptr, char * text );
|
||||
void puttxt0( uchar * pduptr, char * text );
|
||||
|
||||
uchar getbyte( uchar * pduptr );
|
||||
ushort getword( uchar * pduptr );
|
||||
ulong getdword( uchar * pduptr );
|
||||
void getbtxt( uchar * pduptr, uchar * text, size_t tlen );
|
||||
void gettext( uchar * pduptr, char * text, size_t tlen );
|
||||
|
||||
ushort chksum( uchar * data, size_t dlen );
|
||||
|
||||
int welcome( uchar cmd );
|
||||
|
||||
#endif /*_GENPROTO_H*/
|
|
@ -0,0 +1,384 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* */
|
||||
static char rcsid[] =
|
||||
"$Id: ic35frec.c,v 1.8 2001/03/02 02:09:59 tsch Rel $"; /*
|
||||
* *
|
||||
* IC35 record access *
|
||||
* *
|
||||
*************************************************************************
|
||||
* *
|
||||
* ??? is "fixme" mark: sections of code needing fixes *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include <stdlib.h> /* calloc(), .. */
|
||||
#include <string.h> /* strcmp(), .. */
|
||||
|
||||
#include "util.h" /* ERR,OK, uchar, .. */
|
||||
#include "ic35frec.h"
|
||||
NOTUSED(rcsid);
|
||||
|
||||
|
||||
struct ic35file { /* IC35 file description */
|
||||
int id; /* id on IC35 */
|
||||
int nfld; /* number of fields in record */
|
||||
char * name; /* filename */
|
||||
};
|
||||
struct ic35rec { /* internal IC35 record for field access */
|
||||
ulong id; /* record-id on IC35: recid[3],fileid[1]*/
|
||||
uchar chg; /* change-flag on IC35 */
|
||||
size_t dlen; /* length of IC35 record data buffer */
|
||||
uchar * data; /* record data buffer: flens, fdata */
|
||||
int nflds; /* number of fields in record */
|
||||
struct {
|
||||
size_t len; /* length of field */
|
||||
uchar * ptr; /* pointer to field data */
|
||||
} flds[MAXFLDS]; /* vector of record fields */
|
||||
size_t fblen; /* length of field data buffer */
|
||||
uchar * fbuff; /* field data buffer */
|
||||
};
|
||||
|
||||
|
||||
/* lookup IC35 fileid
|
||||
* ------------------
|
||||
*/
|
||||
static struct ic35file ic35files[] = {
|
||||
{ FILEADDR, 21, "Addresses" },
|
||||
{ FILEMEMO, 4, "Memo" },
|
||||
{ FILESCHED, 10, "Schedule" },
|
||||
{ FILETODO, 8, "To Do List" },
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
static struct ic35file *
|
||||
_ic35fdesc( int fileid )
|
||||
{
|
||||
struct ic35file * pfile;
|
||||
|
||||
for ( pfile = ic35files; pfile->name != NULL; ++pfile )
|
||||
if ( pfile->id == fileid )
|
||||
return pfile;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get number of record fields acc.to file-id
|
||||
* ------------------------------------------
|
||||
*/
|
||||
int
|
||||
ic35fnflds( int fileid )
|
||||
{
|
||||
struct ic35file * pfile;
|
||||
|
||||
pfile = _ic35fdesc( fileid );
|
||||
if ( pfile == NULL ) /* unknown file id */
|
||||
return 0;
|
||||
return pfile->nfld;
|
||||
}
|
||||
static int
|
||||
_nrecflds( int fldid )
|
||||
{
|
||||
int nflds;
|
||||
|
||||
if ( (nflds = ic35fnflds( FldFile(fldid) )) == 0 /* unkwown file id */
|
||||
|| FldIdx(fldid) >= nflds /* bad field index */
|
||||
|| FldIdx(fldid) >= alenof(((IC35REC*)0)->flds) )
|
||||
return 0;
|
||||
return nflds;
|
||||
}
|
||||
|
||||
/* get filename acc.to file-id
|
||||
* ---------------------------
|
||||
*/
|
||||
char *
|
||||
ic35fname( int fileid )
|
||||
{
|
||||
struct ic35file * pfile;
|
||||
|
||||
pfile = _ic35fdesc( fileid );
|
||||
if ( pfile == NULL ) /* unknown file id */
|
||||
return NULL;
|
||||
return pfile->name;
|
||||
}
|
||||
|
||||
|
||||
/* constructur: create new IC35 record
|
||||
* -----------------------------------
|
||||
*/
|
||||
IC35REC *
|
||||
new_ic35rec( void )
|
||||
{
|
||||
return calloc( 1, sizeof(IC35REC) );
|
||||
}
|
||||
|
||||
/* destructor: delete IC35 record
|
||||
* ------------------------------
|
||||
*/
|
||||
static void
|
||||
_del_ic35recbuffs( IC35REC * rec )
|
||||
{
|
||||
int fi;
|
||||
|
||||
for ( fi = 0; fi < alenof(rec->flds); ++fi ) {
|
||||
if ( !( rec->fbuff <= rec->flds[fi].ptr
|
||||
&& rec->flds[fi].ptr < rec->fbuff+rec->fblen ) )
|
||||
free( rec->flds[fi].ptr );
|
||||
rec->flds[fi].ptr = NULL;
|
||||
rec->flds[fi].len = 0;
|
||||
}
|
||||
rec->nflds = 0;
|
||||
if ( rec->fbuff != NULL ) {
|
||||
free( rec->fbuff );
|
||||
rec->fbuff = NULL;
|
||||
rec->fblen = 0;
|
||||
}
|
||||
if ( rec->data != NULL ) {
|
||||
free( rec->data );
|
||||
rec->data = NULL;
|
||||
rec->dlen = 0;
|
||||
}
|
||||
}
|
||||
void
|
||||
del_ic35rec( IC35REC * rec )
|
||||
{
|
||||
_del_ic35recbuffs( rec );
|
||||
free( rec );
|
||||
}
|
||||
|
||||
/* set,get special field in IC35 record
|
||||
* ------------------------------------
|
||||
*/
|
||||
void
|
||||
set_ic35recid( IC35REC * rec, ulong recid )
|
||||
{
|
||||
int nflds;
|
||||
|
||||
rec->id = recid;
|
||||
if ( (nflds = ic35fnflds( FileId(recid) )) != 0 )
|
||||
rec->nflds = nflds;
|
||||
}
|
||||
ulong
|
||||
ic35recid( IC35REC * rec )
|
||||
{
|
||||
return rec->id;
|
||||
}
|
||||
void
|
||||
set_ic35recchg( IC35REC * rec, uchar chgflag )
|
||||
{
|
||||
rec->chg = chgflag;
|
||||
}
|
||||
uchar
|
||||
ic35recchg( IC35REC * rec )
|
||||
{
|
||||
return rec->chg;
|
||||
}
|
||||
|
||||
/* set,get IC35 record raw data
|
||||
* ----------------------------
|
||||
*/
|
||||
void
|
||||
set_ic35recdata( IC35REC * rec, uchar * data, size_t dlen )
|
||||
{
|
||||
uchar * fptr;
|
||||
uchar * fbptr;
|
||||
int fi;
|
||||
size_t nflds, flensum;
|
||||
|
||||
_del_ic35recbuffs( rec );
|
||||
if ( data == NULL || dlen == 0 )
|
||||
return;
|
||||
if ( (rec->data = malloc( dlen )) == NULL )
|
||||
return;
|
||||
memcpy( rec->data, data, rec->dlen = dlen );
|
||||
memset( rec->flds, 0, sizeof(rec->flds) );
|
||||
for ( nflds = flensum = 0; nflds < alenof(rec->flds); ++nflds ) {
|
||||
flensum += rec->data[nflds] + 1;
|
||||
if ( flensum > dlen )
|
||||
break;
|
||||
}
|
||||
if ( (rec->fbuff = malloc( dlen )) == NULL )
|
||||
return;
|
||||
rec->fblen = dlen;
|
||||
rec->nflds = nflds;
|
||||
fbptr = rec->fbuff;
|
||||
fptr = rec->data + nflds;
|
||||
for ( fi = 0; fi < nflds; ++fi ) {
|
||||
rec->flds[fi].len = rec->data[fi];
|
||||
rec->flds[fi].ptr = fbptr;
|
||||
memcpy( rec->flds[fi].ptr, fptr, rec->flds[fi].len );
|
||||
fbptr += rec->flds[fi].len;
|
||||
*fbptr++ = '\0'; /* append end-of-string */
|
||||
fptr += rec->data[fi];
|
||||
}
|
||||
}
|
||||
void
|
||||
get_ic35recdata( IC35REC * rec, uchar ** pdata, size_t * pdlen )
|
||||
{
|
||||
uchar * fptr;
|
||||
int fi;
|
||||
size_t dlen;
|
||||
|
||||
if ( rec->data == NULL ) { /* rebuild record data */
|
||||
for ( fi = 0, dlen = 0; fi < rec->nflds; ++fi )
|
||||
dlen += rec->flds[fi].len + 1;
|
||||
if ( (rec->data = malloc( dlen )) != NULL ) {
|
||||
rec->dlen = dlen;
|
||||
fptr = rec->data + rec->nflds;
|
||||
for ( fi = 0; fi < rec->nflds; ++fi ) {
|
||||
if ( rec->flds[fi].ptr != NULL )
|
||||
memcpy( fptr, rec->flds[fi].ptr, rec->flds[fi].len );
|
||||
else
|
||||
rec->flds[fi].len = 0;
|
||||
fptr += (rec->data[fi] = rec->flds[fi].len);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( pdata )
|
||||
*pdata = rec->data;
|
||||
if ( pdlen )
|
||||
*pdlen = rec->dlen;
|
||||
}
|
||||
|
||||
/* set,get string field from IC35 record
|
||||
* -------------------------------------
|
||||
*/
|
||||
void
|
||||
set_ic35recfld( IC35REC * rec, int fldid, char * data )
|
||||
{
|
||||
int fi, nflds;
|
||||
size_t flen;
|
||||
char * fbuff;
|
||||
|
||||
if ( (nflds = _nrecflds( fldid )) <= 0 )
|
||||
return; /* bad field id */
|
||||
if ( rec->nflds == 0 )
|
||||
rec->nflds = nflds;
|
||||
if ( (fi = FldIdx(fldid)) >= rec->nflds )
|
||||
return;
|
||||
if ( data == NULL )
|
||||
data = "";
|
||||
switch ( fldid ) {
|
||||
case A_CategoryID:
|
||||
case S_AlarmBefore:
|
||||
case S_Alarm_Repeat:
|
||||
case S_RepCount:
|
||||
case T_Completed:
|
||||
case T_Priority:
|
||||
case T_CategoryID:
|
||||
case M_CategoryID: /* 1-byte binary fields */
|
||||
flen = 1;
|
||||
break;
|
||||
default:
|
||||
flen = strlen( data );
|
||||
}
|
||||
if ( flen > 255 ) flen = 255; /* truncate to max.field length */
|
||||
if ( flen > rec->flds[fi].len ) { /* new field bigger old content */
|
||||
if ( (fbuff = malloc( flen + 1 )) == NULL )
|
||||
return; /* no memory */
|
||||
if ( !( rec->fbuff <= rec->flds[fi].ptr
|
||||
&& rec->flds[fi].ptr < rec->fbuff+rec->fblen ) )
|
||||
free( rec->flds[fi].ptr ); /* old field outside buffer */
|
||||
rec->flds[fi].ptr = fbuff;
|
||||
}
|
||||
if ( flen ) {
|
||||
memcpy( rec->flds[fi].ptr, data, flen );
|
||||
rec->flds[fi].ptr[flen] = '\0';
|
||||
}
|
||||
rec->flds[fi].len = flen;
|
||||
if ( rec->data != NULL ) {
|
||||
free( rec->data );
|
||||
rec->data = NULL; /* record data must be rebuilt */
|
||||
rec->dlen = 0;
|
||||
}
|
||||
}
|
||||
void
|
||||
get_ic35recfld( IC35REC * rec, int fldid, uchar ** pfld, size_t * plen )
|
||||
{
|
||||
if ( _nrecflds( fldid ) <= 0 /* bad field id */
|
||||
|| rec->flds[FldIdx(fldid)].ptr == NULL ) { /* empty field */
|
||||
if ( pfld ) *pfld = "";
|
||||
if ( plen ) *plen = 0;
|
||||
} else {
|
||||
if ( pfld ) *pfld = rec->flds[FldIdx(fldid)].ptr;
|
||||
if ( plen ) *plen = rec->flds[FldIdx(fldid)].len;
|
||||
}
|
||||
}
|
||||
char *
|
||||
ic35recfld( IC35REC * rec, int fldid )
|
||||
{
|
||||
uchar * fld;
|
||||
|
||||
get_ic35recfld( rec, fldid, &fld, NULL );
|
||||
return fld;
|
||||
}
|
||||
|
||||
/* compare 2 IC35 records
|
||||
* ----------------------
|
||||
* records are compared field by field, because some fields need
|
||||
* special handling, i.e. difference ignored.
|
||||
* returns
|
||||
* 0 both IC35 records are (regarded) same
|
||||
* 1 IC35 records differ
|
||||
* -1 IC35 records differ strangely:
|
||||
* either one is NULL or fileids mismatch
|
||||
*/
|
||||
int
|
||||
cmp_ic35rec( IC35REC * rec1, IC35REC * rec2 )
|
||||
{
|
||||
int fileid;
|
||||
int fi, nflds, fldid;
|
||||
uchar * ic35fld;
|
||||
uchar * binfld;
|
||||
char ic35tfld[6+1];
|
||||
|
||||
if ( rec1 == NULL && rec2 == NULL )
|
||||
return 0;
|
||||
if ( rec1 == NULL || rec2 == NULL )
|
||||
return -1;
|
||||
if ( (fileid = FileId( ic35recid( rec1 ) ))
|
||||
!= FileId( ic35recid( rec2 ) ) )
|
||||
return -1;
|
||||
|
||||
nflds = ic35fnflds( fileid );
|
||||
for ( fi = 0; fi < nflds; ++fi ) {
|
||||
fldid = FILEfld(fileid,fi);
|
||||
ic35fld = ic35recfld( rec1, fldid );
|
||||
binfld = ic35recfld( rec2, fldid );
|
||||
if ( strcmp( binfld, ic35fld ) == 0 )
|
||||
continue;
|
||||
switch ( fldid ) {
|
||||
case A_CategoryID:
|
||||
case M_CategoryID:
|
||||
case T_CategoryID:
|
||||
continue; /* ignore category-ID difference */
|
||||
case S_StartTime:
|
||||
case S_EndTime:
|
||||
ic35fld = strncat( strcpy( ic35tfld, "" ),
|
||||
ic35fld, sizeof(ic35tfld)-1 );
|
||||
if ( ( fldid == S_StartTime && ic35fld[4] == ':' )
|
||||
|| ( fldid == S_EndTime && ic35fld[4] == '<' ) )
|
||||
ic35fld[4] = ic35fld[5] = '0';
|
||||
if ( strcmp( ic35fld, binfld ) == 0 )
|
||||
continue; /* ignore strange IC35 Start/EndTime */
|
||||
break;
|
||||
case S_RepEndDate:
|
||||
case S_RepCount:
|
||||
if ( (*ic35recfld( rec2, S_Alarm_Repeat ) & RepeatMASK) == 0 )
|
||||
continue; /* ignore difference if not repeat */
|
||||
break;
|
||||
case S_Alarm_Repeat:
|
||||
if ( ((*binfld ^ *ic35fld) & ~(AlarmNoLED|AlarmNoBeep)) == 0
|
||||
&& *ic35recfld( rec2, S_AlarmBefore ) == AlarmBefNone )
|
||||
continue; /* ignore LED,Beep diff if no alarm */
|
||||
break;
|
||||
}
|
||||
LPRINTF(( L_DEBUG, "cmp_ic35rec: rid=%08lX fi=%d diff",
|
||||
ic35recid(rec1), fi ));
|
||||
LDUMP(( L_DEBUG, binfld, strlen(binfld),
|
||||
"cmp_ic35rec: rec2 len=%d", strlen(binfld) ));
|
||||
LDUMP(( L_DEBUG, ic35fld, strlen(ic35fld),
|
||||
"cmp_ic35rec: rec1 len=%d", strlen(ic35fld) ));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* *
|
||||
* $Id: ic35frec.h,v 1.5 2000/12/23 01:09:26 tsch Rel $ *
|
||||
* *
|
||||
* header for IC35 record access *
|
||||
* *
|
||||
************************************************************************/
|
||||
#ifndef _IC35REC_H
|
||||
#define _IC35REC_H 1
|
||||
|
||||
#include "util.h" /* uchar, .. */
|
||||
|
||||
|
||||
/* IC35 database files */
|
||||
#define FILEADDR 0x05
|
||||
#define FILEMEMO 0x06
|
||||
#define FILETODO 0x07
|
||||
#define FILESCHED 0x08
|
||||
#define FILE_ANY 0
|
||||
|
||||
#define MAXFLDS 21 /* max.number of fields in IC35 record */
|
||||
#define MAXRLEN (MAXFLDS * (1+255)) /* #fields [Addresses] * (len + fieldlen) */
|
||||
|
||||
/* record-ids consist of file-id and record-id */
|
||||
#define FileId(frid) ( ((ulong)(frid) & 0xFF000000) >> 24 )
|
||||
#define RecId(frid) ( ((ulong)(frid) & 0x00FFFFFF) )
|
||||
#define FileRecId(fid,rid) ( (((ulong)(fid) << 24) & 0xFF000000) \
|
||||
| ( (ulong)(rid) & 0x00FFFFFF) )
|
||||
/* field-ids consist of file-id and field-index */
|
||||
#define FldFile(fldid) ( ((fldid) & 0xFF00) >> 8 )
|
||||
#define FldIdx(fldid) ( (fldid) & 0x00FF )
|
||||
|
||||
/* IC35 record fields */
|
||||
#define FILEfld(fileid,index) ( (fileid)<<8 | (index) )
|
||||
/* record fields "Addresses" */
|
||||
#define ADDRfld(index) FILEfld( FILEADDR, index )
|
||||
#define A_LastName ADDRfld( 0 ) /* max. 50 chars */
|
||||
#define A_FirstName ADDRfld( 1 ) /* max. 50 chars */
|
||||
#define A_Company ADDRfld( 2 ) /* max. 128 chars */
|
||||
#define A_TelHome ADDRfld( 3 ) /* max. 48 chars */
|
||||
#define A_TelWork ADDRfld( 4 ) /* max. 48 chars */
|
||||
#define A_TelMobile ADDRfld( 5 ) /* max. 48 chars */
|
||||
#define A_TelFax ADDRfld( 6 ) /* max. 48 chars */
|
||||
#define A_Street ADDRfld( 7 ) /* max. 128 chars */
|
||||
#define A_City ADDRfld( 8 ) /* max. 60 chars */
|
||||
#define A_ZIP ADDRfld( 9 ) /* max. 10 chars */
|
||||
#define A_Region ADDRfld( 10 ) /* max. 40 chars */
|
||||
#define A_Country ADDRfld( 11 ) /* max. 15 chars */
|
||||
#define A_Email1 ADDRfld( 12 ) /* max. 80 chars */
|
||||
#define A_Email2 ADDRfld( 13 ) /* max. 80 chars */
|
||||
#define A_URL ADDRfld( 14 ) /* max. 128 chars */
|
||||
#define A_BirthDate ADDRfld( 15 ) /* max. 10 chars */
|
||||
#define A_Notes ADDRfld( 16 ) /* max. 255 chars */
|
||||
#define A_CategoryID ADDRfld( 17 ) /* 1 Byte */
|
||||
#define A_Def1 ADDRfld( 18 ) /* max. 128 chars */
|
||||
#define A_Def2 ADDRfld( 19 ) /* max. 128 chars */
|
||||
#define A_Category ADDRfld( 20 ) /* max. 8 chars */
|
||||
/* record fields "Schedule" */
|
||||
#define SCHEDfld(index) FILEfld( FILESCHED, index )
|
||||
#define S_Subject SCHEDfld( 0 ) /* max. 60 chars */
|
||||
#define S_StartDate SCHEDfld( 1 ) /* 8 yyyymmdd */
|
||||
#define S_StartTime SCHEDfld( 2 ) /* 6 hhmmss */
|
||||
#define S_EndTime SCHEDfld( 3 ) /* 6 hhmmss */
|
||||
#define S_AlarmBefore SCHEDfld( 4 ) /* 1 Byte */
|
||||
#define AlarmBefNone 0x00
|
||||
#define AlarmBefNow 0x01
|
||||
#define AlarmBef1min 0x02
|
||||
#define AlarmBef5min 0x03
|
||||
#define AlarmBef10min 0x04
|
||||
#define AlarmBef30min 0x05
|
||||
#define AlarmBef1hour 0x06
|
||||
#define AlarmBef2hour 0x07
|
||||
#define AlarmBef10hour 0x08
|
||||
#define AlarmBef1day 0x09
|
||||
#define AlarmBef2day 0x0A
|
||||
#define S_Notes SCHEDfld( 5 ) /* max. 255 chars */
|
||||
#define S_Alarm_Repeat SCHEDfld( 6 ) /* 1 Byte */
|
||||
#define AlarmNoLED 0x80
|
||||
#define AlarmNoBeep 0x40
|
||||
#define RepeatMASK 0x0F
|
||||
#define RepeatNone 0x00
|
||||
#define RepeatDay 0x01
|
||||
#define RepeatWeek 0x02
|
||||
#define RepeatMonWday 0x03
|
||||
#define RepeatYear 0x04
|
||||
#define RepeatMonMday 0x05
|
||||
#define S_EndDate SCHEDfld( 7 ) /* 8 yyyymmdd */
|
||||
#define S_RepEndDate SCHEDfld( 8 ) /* 6 hhmmss */
|
||||
#define S_RepCount SCHEDfld( 9 ) /* 1 Byte */
|
||||
/* record fields "To Do List" */
|
||||
#define TODOfld(index) FILEfld( FILETODO, index )
|
||||
#define T_StartDate TODOfld( 0 ) /* 8 yyyymmdd */
|
||||
#define T_EndDate TODOfld( 1 ) /* 8 yyyymmdd */
|
||||
#define T_Completed TODOfld( 2 ) /* 1 Byte */
|
||||
#define T_Priority TODOfld( 3 ) /* 1 Byte */
|
||||
#define T_Subject TODOfld( 4 ) /* max. 60 chars */
|
||||
#define T_Notes TODOfld( 5 ) /* max. 255 chars */
|
||||
#define T_CategoryID TODOfld( 6 ) /* 1 Byte */
|
||||
#define T_Category TODOfld( 7 ) /* max. 8 chars */
|
||||
/* record fields "Memo" */
|
||||
#define MEMOfld(index) FILEfld( FILEMEMO, index )
|
||||
#define M_Subject MEMOfld( 0 ) /* max. 60 chars */
|
||||
#define M_Notes MEMOfld( 1 ) /* max. 255 chars */
|
||||
#define M_CategoryID MEMOfld( 2 ) /* 1 Byte */
|
||||
#define M_Category MEMOfld( 3 ) /* max. 8 chars */
|
||||
|
||||
/* IC35 record change flags */
|
||||
#define IC35_NEW 0x80 /* new record */
|
||||
#define IC35_MOD 0x40 /* modified */
|
||||
#define IC35_DEL 0x20 /* deleted (no record data) */
|
||||
#define IC35_CLEAN 0x00 /* unchanged */
|
||||
|
||||
|
||||
typedef struct ic35rec IC35REC;
|
||||
|
||||
|
||||
char * ic35fname( int fileid );
|
||||
int ic35fnflds( int fileid );
|
||||
|
||||
IC35REC * new_ic35rec( void );
|
||||
void del_ic35rec( IC35REC * rec );
|
||||
|
||||
void set_ic35recid( IC35REC * rec, ulong recid );
|
||||
ulong ic35recid( IC35REC * rec );
|
||||
void set_ic35recchg( IC35REC * rec, uchar chgflag );
|
||||
uchar ic35recchg( IC35REC * rec );
|
||||
|
||||
void set_ic35recdata( IC35REC * rec, uchar * data, size_t dlen );
|
||||
void get_ic35recdata( IC35REC * rec, uchar ** pdata, size_t * pdlen );
|
||||
|
||||
void set_ic35recfld( IC35REC * rec, int fldid, char * data );
|
||||
void get_ic35recfld( IC35REC * rec, int fldid, uchar** pfld, size_t * plen );
|
||||
char * ic35recfld( IC35REC * rec, int fldid );
|
||||
|
||||
int cmp_ic35rec( IC35REC * rec1, IC35REC * rec2 );
|
||||
|
||||
#endif /*_IC35REC_H*/
|
|
@ -0,0 +1,807 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# $Id: ic35log.sh,v 1.6 2001/01/14 00:09:46 tsch Rel $
|
||||
#
|
||||
# process logs of IC35 communication
|
||||
#
|
||||
|
||||
# setup parameters and defaults
|
||||
PAGER="less -S"
|
||||
PROGNAME=`basename $0`
|
||||
TMPDIR=/tmp/dpkgmirr$$
|
||||
|
||||
usage()
|
||||
{
|
||||
echo "\
|
||||
usage: $PROGNAME [options] [tarfile] logfile
|
||||
process IC35 communication 'logfile', which may be gzip'd or contained
|
||||
in optionally gzip'd 'tarfile'. options:
|
||||
-l level level of output:
|
||||
all show all communication (default)
|
||||
syn2 suppress Level-1 of IC35sync protocol
|
||||
syn4 decode Level-4 of IC35sync protocol
|
||||
-s n prepend output with 1:linenumber 2:timestamp
|
||||
-a show communication also as ASCII characters
|
||||
-D debug/detail: output diagnostic data \
|
||||
"
|
||||
exit 2
|
||||
}
|
||||
|
||||
# add ASCII chars to hex_logfile
|
||||
#
|
||||
showascii() # <hex_logfile >hex_ascii_logfile
|
||||
{
|
||||
awk '
|
||||
BEGIN {
|
||||
# create table chr[] for hex to char conversion
|
||||
ascii = ascii " !\"#$%&\047()*+,-./"
|
||||
ascii = ascii "0123456789:;<=>?"
|
||||
ascii = ascii "@ABCDEFGHIJKLMNO"
|
||||
ascii = ascii "PQRSTUVWXYZ[\\]^_"
|
||||
ascii = ascii "`abcdefghijklmno"
|
||||
ascii = ascii "pqrstuvwxyz{|}~"
|
||||
for ( c = 0; c <= 255; ++c )
|
||||
if ( 32 <= c && c <= 126 ) # 32=space 126=tilda
|
||||
chr[ sprintf("%02X", c) ] = substr( ascii, c - 32+1, 1 )
|
||||
else
|
||||
chr[ sprintf("%02X", c) ] = "."
|
||||
}
|
||||
/WRx/ || /RDx/ {
|
||||
if ( $1 == "WRx" || $1 == "RDx" ) {
|
||||
if ( $1 == "WRx" ) dir = "WRa"
|
||||
else dir = "RDa"
|
||||
beghex = 3
|
||||
} else {
|
||||
if ( $2 == "WRx" ) dir = "WRa"
|
||||
else dir = "RDa"
|
||||
beghex = 4
|
||||
}
|
||||
ascblk = chr[$(beghex)]
|
||||
for ( i = beghex+1; i <= NF; ++i )
|
||||
ascblk = ascblk " " chr[$i]
|
||||
print
|
||||
if ( beghex == 3 )
|
||||
printf( "%s %2d\t %s\n", dir, $2, ascblk )
|
||||
else
|
||||
printf( "%s %s %2d\t %s\n", $1, dir, $3, ascblk )
|
||||
}' -
|
||||
}
|
||||
|
||||
# convert 'portmon' logfile
|
||||
# expects 'portmon' logfiles in Unix-format i.e. NL terminated lines
|
||||
# (DOS-format CRLF terminated lines may break the awk script)
|
||||
# for 'portmon' see http://www.sysinternals.com
|
||||
#
|
||||
ic35prot() # [-vskip=3] [-vDEBUG=1] <portmon_logfile >hex_logfile
|
||||
{
|
||||
awk $* '
|
||||
# parameters
|
||||
# skip number of leading bytes to skip from transmitted blocks
|
||||
# blocks up to this much bytes are not printed, default 0
|
||||
# stamp if non-zero/non-empty stamp transmit blocks with id (first
|
||||
# field) from portmon log, to ease finding portmon log lines
|
||||
# default: 0 / "" (disabled)
|
||||
# MAXBPL maximum number of bytes to print per output line
|
||||
# default: 128
|
||||
# DEBUG if non-zero/non-empty print verbose debugging output
|
||||
# default: 0 / "" (disabled)
|
||||
|
||||
# extract transmitted data bytes
|
||||
# returns:
|
||||
# -1 no data bytes: miss "Length" field
|
||||
# 0 no data bytes: length value == 0
|
||||
# > 0 length value
|
||||
# xdlen number of logged bytes, maybe < length value
|
||||
# xdata logged transmitted data bytes
|
||||
#
|
||||
function getxdata()
|
||||
{
|
||||
xlen = 0
|
||||
xdata = ""
|
||||
# search "Length" field
|
||||
for ( i = 1; i <= NF; ++i )
|
||||
if ( $i ~ "^Length" )
|
||||
break
|
||||
if ( i > NF ) { # "Length" field not found
|
||||
# check if log from "ic35sync"
|
||||
for ( i = 1; i <= NF; ++i )
|
||||
if ( $i ~ "^[0-9A-F][0-9A-F][0-9A-F][0-9A-F]:$" )
|
||||
break;
|
||||
if ( i > NF )
|
||||
return -1
|
||||
# process log from "ic35sync"
|
||||
xdata = ""
|
||||
for ( i = i+1; i <= NF; ++i ) {
|
||||
if ( $i !~ "^[0-9A-F][0-9A-F]$" )
|
||||
break;
|
||||
xdata = xdata $i " "
|
||||
if ( --hadxmit == 0 )
|
||||
break;
|
||||
}
|
||||
xdlen = length( xdata ) / 3
|
||||
return xdlen
|
||||
}
|
||||
# get length value from next field, remove trail ":"
|
||||
split( $(i+1), flds, ":" )
|
||||
len = int( flds[1] )
|
||||
if ( len == 0 )
|
||||
return 0 # no data transmitted
|
||||
# extract get data bytes after "Length" and <nn:>
|
||||
lentxt = $(i) " " $(i+1)
|
||||
xdata = substr( $0, index($0, lentxt) + length(lentxt)+1 )
|
||||
# make string of 2dig-hex with trail " " for append
|
||||
sub( "^[^0-9A-Fa-f]*", "", xdata ); # remove leading garbage
|
||||
sub( "[^0-9A-Fa-f]*$", "", xdata ); # remove trailing garbage
|
||||
xdata = xdata " "
|
||||
xdlen = length( xdata ) / 3
|
||||
# return length value, maybe not all bytes logged
|
||||
return len
|
||||
}
|
||||
|
||||
function prxdata( dir, xbuf, xlen,
|
||||
_offs, _i, _hex, _pbuf, _plen )
|
||||
{
|
||||
if ( xlen <= skip )
|
||||
return
|
||||
_plen = length( xbuf )
|
||||
_offs = skip * 3
|
||||
if ( skip >= 3 )
|
||||
_plen = length( xbuf ) - _offs - 2 * 3 # skip checksum also
|
||||
printf( "%s%sx %2d\t%s\n", xstamp, dir, xlen, substr(xbuf,_offs,_plen) )
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
# max.number of bytes per output line
|
||||
if ( ! MAXBPL ) MAXBPL = 128
|
||||
}
|
||||
|
||||
NF >= 2 {
|
||||
if ( $2 == "ic35sync" || $2 == "ic35mgr" )
|
||||
tsecs = $1
|
||||
else
|
||||
tsecs += $2
|
||||
}
|
||||
# Windows-98:
|
||||
# 35 0.00034960 Ic35 syn VCOMM_ReadComm COM1 SUCCESS Length: 1: 57
|
||||
/VCOMM_ReadComm/ && /SUCCESS/ {
|
||||
if ( oldxdir == "WR" ) do_print = 1
|
||||
xdir = "RD"
|
||||
if ( DEBUG ) print "DBG: xdir=" xdir, $0
|
||||
}
|
||||
# 36 0.00005040 Ic35 syn VCOMM_GetCommQueueStatus COM1 SUCCESS RX: 6 TX: 0
|
||||
/VCOMM_GetCommQueueStatus/ {
|
||||
if ( DEBUG ) print "DBG: next ", $0
|
||||
next
|
||||
}
|
||||
# 58 0.00063840 Ic35 syn VCOMM_WriteComm COM1 SUCCESS Length: 1: 41
|
||||
/VCOMM_WriteComm/ {
|
||||
if ( oldxdir == "RD" ) do_print = 1
|
||||
xdir = "WR"
|
||||
if ( DEBUG ) print "DBG: xdir=" xdir, $0
|
||||
}
|
||||
|
||||
# Windows-NT:
|
||||
# 22 0.00106488 IC35Mgr.exe IRP_MJ_READ Serial1 SUCCESS Length 1: 80
|
||||
# 16 0.00000000 IC35 Sync.exe IRP_MJ_READ Serial0 Length 1
|
||||
# 16 0.00000953 SUCCESS Length 1: 57
|
||||
/IRP_MJ_READ/ {
|
||||
if ( oldxdir == "WR" ) do_print = 1
|
||||
if ( $0 ~ "SUCCESS" ) {
|
||||
xdir = "RD"
|
||||
if ( DEBUG ) print "DBG: xdir=" xdir, $0
|
||||
} else if ( $0 !~ "TIMEOUT" ) {
|
||||
hadread = 1
|
||||
if ( DEBUG ) print "DBG: hadread", $0
|
||||
} else {
|
||||
do_print = 1
|
||||
}
|
||||
}
|
||||
# 16 0.00000953 SUCCESS Length 1: 57
|
||||
/SUCCESS/ && hadread {
|
||||
xdir = "RD"
|
||||
hadread = 0
|
||||
if ( DEBUG ) print "DBG: dlyd RD", $0
|
||||
}
|
||||
# 15 0.07746540 TIMEOUT Length 0:
|
||||
/TIMEOUT/ && hadread {
|
||||
do_print = 1
|
||||
}
|
||||
# 419 0.00000000 IC35 Sync.exe IOCTL_SERIAL_CLR_DTR Serial0
|
||||
/IOCTL_SERIAL_CLR_DTR/ {
|
||||
do_print = 1
|
||||
}
|
||||
# 3 0.00000000 IC35 Sync.exe IRP_MJ_WRITE Serial0 Length 1: 41
|
||||
/IRP_MJ_WRITE/ {
|
||||
if ( oldxdir == "RD" ) do_print = 1
|
||||
hadread = 0
|
||||
xdir = "WR"
|
||||
if ( DEBUG ) print "DBG: xdir=" xdir, $0
|
||||
}
|
||||
|
||||
# ic35sync/Linux
|
||||
# 01:11:48.3206 ic35sync 6 com_send(0x8055180,19) = 19
|
||||
# 01:11:48.3206 ic35sync 6 0000: 02 13 00 83 0E 00 49 0B 00 01 07 03 00 00 00 00
|
||||
# 01:11:48.3206 ic35sync 6 0010: 00 05 01
|
||||
/ com_send\(/ {
|
||||
if ( oldxdir == "RD" ) do_print = 1
|
||||
hadxmit = $NF
|
||||
xmitdir = "WR"
|
||||
}
|
||||
# 01:11:48.3703 ic35sync 6 com_recv(0xbffff89b,1) = 1
|
||||
# 01:11:48.3703 ic35sync 6 0000: F2
|
||||
# 01:11:48.3706 ic35sync 6 com_recv(0x8055181,2) = 2
|
||||
# 01:11:48.3706 ic35sync 6 0000: 10 00
|
||||
# 01:11:48.3800 ic35sync 6 com_recv(0x8055183,13) = 13
|
||||
# 01:11:48.3800 ic35sync 6 0000: A0 0B 00 49 08 00 0A 00 00 06 20 2E 02
|
||||
/ com_recv\(/ {
|
||||
if ( oldxdir == "WR" ) do_print = 1
|
||||
hadxmit = $NF
|
||||
xmitdir = "RD"
|
||||
}
|
||||
/ [0-9A-F][0-9A-F][0-9A-F][0-9A-F]: / && hadxmit {
|
||||
xdir = xmitdir
|
||||
}
|
||||
|
||||
DEBUG {
|
||||
print "DBG1: old,xdir=" oldxdir "," xdir, "xbuff=" xblen, "\047" xbuff "\047"
|
||||
}
|
||||
do_print {
|
||||
prxdata( oldxdir, xbuff, xblen )
|
||||
if ( txlen > xblen ) {
|
||||
txdir = (oldxdir == "WR" ? "Wx " : "Rx ")
|
||||
print txdir txlen
|
||||
}
|
||||
xbuff = ""
|
||||
xblen = txlen = 0
|
||||
do_print = 0
|
||||
}
|
||||
xdir {
|
||||
if ( DEBUG ) print "DBG: do_x=" xdir, $0
|
||||
xlen = getxdata() # get transmit data to xdata,xdlen
|
||||
if ( xlen <= 0 )
|
||||
next # no transmit / timeout
|
||||
if ( xblen == 0 && stamp ) {
|
||||
if ( stamp == 2 )
|
||||
if ( tsecs ~ ":" )
|
||||
xstamp = tsecs " "
|
||||
else
|
||||
xstamp = sprintf( "%010.4f ", tsecs )
|
||||
else
|
||||
xstamp = sprintf( "%05d\t", $1 )
|
||||
}
|
||||
xbuff = xbuff xdata # buffer transmit data
|
||||
xblen += xlen
|
||||
txlen += xlen
|
||||
if ( xdlen != xlen || xblen >= MAXBPL ) { # not all logged or too much
|
||||
prxdata( xdir, xbuff, xblen )
|
||||
xbuff = ""
|
||||
xblen = 0
|
||||
}
|
||||
oldxdir = xdir
|
||||
xdir = ""
|
||||
}
|
||||
DEBUG {
|
||||
print "DBG2: old,xdir=" oldxdir "," xdir, "xbuff=" xblen, "\047" xbuff "\047"
|
||||
}
|
||||
' -
|
||||
}
|
||||
|
||||
# decode IC35sync Level-4 protocol
|
||||
# expects output from ic35prot()
|
||||
#
|
||||
ic35L4prot() # [-vDEBUG=1] <hex_logfile >L4prot_logfile
|
||||
{
|
||||
awk $* '
|
||||
# parameters
|
||||
# DEBUG if non-zero/non-empty print verbose debugging output
|
||||
# default: 0 / "" (disabled)
|
||||
|
||||
BEGIN {
|
||||
# create table chr[] for hex to char conversion
|
||||
ascii = ascii " !\"#$%&\047()*+,-./"
|
||||
ascii = ascii "0123456789:;<=>?"
|
||||
ascii = ascii "@ABCDEFGHIJKLMNO"
|
||||
ascii = ascii "PQRSTUVWXYZ[\\]^_"
|
||||
ascii = ascii "`abcdefghijklmno"
|
||||
ascii = ascii "pqrstuvwxyz{|}~"
|
||||
for ( c = 0; c <= 255; ++c ) {
|
||||
xc = sprintf("%02X", c)
|
||||
if ( 32 <= c && c <= 126 ) # 32=space 126=tilda
|
||||
chr[ xc ] = substr( ascii, c - 32+1, 1 )
|
||||
else
|
||||
chr[ xc ] = "\\x" xc
|
||||
}
|
||||
}
|
||||
|
||||
# get block of bytes from hex transmit data
|
||||
# convert to ASCII and enclose in " quotes
|
||||
#
|
||||
function ascblk( beg, len, _end, _blk, _i )
|
||||
{
|
||||
if ( (_end = beg + len-1) > NF )
|
||||
_end = NF # truncate to end of input line
|
||||
_blk = "\""
|
||||
for ( _i = beg; _i <= _end; ++_i )
|
||||
_blk = _blk chr[ $_i ]
|
||||
_blk = _blk "\""
|
||||
return _blk
|
||||
}
|
||||
|
||||
# get byte block of bytes from hex transmit data
|
||||
#
|
||||
function hexblk( beg, len, _end, _blk, _i )
|
||||
{
|
||||
if ( (_end = beg + len-1) > NF )
|
||||
_end = NF # truncate to end of input line
|
||||
_blk = $beg
|
||||
for ( _i = beg+1; _i <= _end; ++_i )
|
||||
_blk = _blk " " $_i
|
||||
return _blk
|
||||
}
|
||||
|
||||
# convert hex strings to decimal
|
||||
#
|
||||
function hex2dec( hexstr, _xval, _xdig, _i )
|
||||
{
|
||||
if ( hexstr ~ "^0[Xx]" )
|
||||
hexstr = substr(hexstr, 3)
|
||||
_xval = 0
|
||||
for ( _i = 1; _i <= length(hexstr); ++_i ) {
|
||||
_xdig = index( "0123456789ABCDEFabcdef", substr(hexstr, _i, 1) ) - 1
|
||||
if ( _xdig < 0 )
|
||||
break
|
||||
if ( _xdig >= 16 )
|
||||
_xdig -= 16 - 10
|
||||
_xval = _xval * 16 + _xdig
|
||||
}
|
||||
return _xval
|
||||
}
|
||||
|
||||
# decode field data from IC35 record
|
||||
function recdata( beg, fid, _i, _recblk )
|
||||
{
|
||||
if ( fid != "" ) { # file-id specified: this the header fragment
|
||||
nflens = 0
|
||||
if ( fid == "05" ) nflens = 21 # Addresses
|
||||
else if ( fid == "06" ) nflens = 4 # Memo
|
||||
else if ( fid == "07" ) nflens = 8 # ToDoList
|
||||
else if ( fid == "08" ) nflens = 10 # Schedule
|
||||
if ( nflens == 0 ) {
|
||||
printf( "ERR: recdata(beg=%s,fid=%s) unkown fid\n", beg, fid )
|
||||
return ""
|
||||
}
|
||||
delete flens
|
||||
for ( _i = 1; _i <= nflens; ++_i )
|
||||
flens[_i] = hex2dec( $(beg+_i-1) )
|
||||
fidx = 1
|
||||
fldrest = 0
|
||||
}
|
||||
if ( fldrest ) { # partial last field from previous fragment
|
||||
_recblk = " f" fidx-1 "=" ascblk( beg, fldrest )
|
||||
sub( "=\"", "=<", _recblk )
|
||||
_i = beg + fldrest
|
||||
fldrest = 0
|
||||
} else { # record data on field boundary
|
||||
_recblk = ""
|
||||
if ( fid != "" ) _i = beg + nflens # header fragment
|
||||
else _i = beg # 2nd ff. fragment
|
||||
}
|
||||
while ( _i <= NF && fidx <= nflens ) {
|
||||
_recblk = _recblk " f" fidx "=" ascblk( _i, flens[fidx] )
|
||||
_i += flens[fidx++]
|
||||
}
|
||||
if ( _i != NF+1 ) { # partial last field
|
||||
fldrest = _i - (NF+1)
|
||||
sub( "\"$", ">", _recblk )
|
||||
}
|
||||
return _recblk
|
||||
}
|
||||
|
||||
# WRx 43 80 26 00 10 00 64 00 4A 1F 00 49 4E 56 45 4E 54 45 43 ...
|
||||
# WRx 14 83 09 00 49 06 00 02 00 00
|
||||
# WRx 8 83 00 03
|
||||
# RDx 46 A0 29 00 10 00 D0 07 4A 22 00 49 4E 56 45 4E 54 45 43 ...
|
||||
# RDx 13 A0 08 00 49 05 00 03 01
|
||||
# RDx 8 A0 03 00
|
||||
# variables:
|
||||
# type indicates command "Cmd" "C??" or response "Rsp" "R??"
|
||||
# "C??","R??" flag PDU contents not matching current knowledge
|
||||
# pi parameter index: PDU paramters begin at pi-th input field
|
||||
# pdu PDU identification for output, e.g. "identify", "openfile"
|
||||
# pars decoded parameters from PDU for output
|
||||
# l2l3 concatenation of Level-2 and Level-3 id-bytes
|
||||
# l4 Level-4 command
|
||||
# l2l3l4 concatenation of l2l3 and l4
|
||||
# printhex flag to also output the hex input (for debugging)
|
||||
# may be set by some decoder, reset on every input block
|
||||
# DEBUG global debug flag to also output the hex input
|
||||
#
|
||||
/^WRx/ || /^RDx/ {
|
||||
if ( $1 == "WRx" ) {
|
||||
type = "Cmd"
|
||||
pi = 2+3+3+2 + 1 # command parameter index
|
||||
} else { # "RDx"
|
||||
type = "Rsp"
|
||||
pi = 2+3+3 + 1 # response parameter index
|
||||
}
|
||||
printhex = 0
|
||||
pdu = pars = l2l3 = l4 = l2l3l4 = ""
|
||||
if ( NF >= 2+3+3 ) { # have L2- and L3 id-bytes
|
||||
l2l3 = $3 $6
|
||||
if ( NF >= 2+3+3+2 ) { # have also L4 command
|
||||
l4 = $9 $10
|
||||
l2l3l4 = l2l3 l4
|
||||
}
|
||||
# identify
|
||||
if ( l2l3 == "8010" ) {
|
||||
# AdsGetDeviceVersion ?
|
||||
pdu = "identify"
|
||||
} else if ( l2l3 == "A010" ) {
|
||||
pdu = "identify"
|
||||
pars = ascblk(pi+25, 99) # "DCS15" version
|
||||
|
||||
# power, passwd
|
||||
} else if ( l2l3l4 == "8249" "0301" ) {
|
||||
pdu = "power"
|
||||
pars = ascblk(pi, 5) # "Power"
|
||||
pars = pars " " hexblk(pi+5, 99) # 00 00 00
|
||||
if ( pars != "\"Power\" 00 00 00" )
|
||||
type = "C??"
|
||||
} else if ( l2l3 == "A049" && lastcmd == "power" ) {
|
||||
pdu = "power"
|
||||
pars = $(pi) $(pi+1) # 0301
|
||||
if ( pars != "0301" || NF+1 - pi != 2 )
|
||||
type = "R??"
|
||||
} else if ( l2l3l4 == "8249" "0300" ) {
|
||||
pdu = "passwd"
|
||||
pars = ascblk(pi, 8) # [password]
|
||||
if ( NF+1 - pi != 8 )
|
||||
type = "C??"
|
||||
} else if ( l2l3 == "A049" && lastcmd == "passwd" ) {
|
||||
pdu = "passwd"
|
||||
pars = $(pi) $(pi+1) # 0101
|
||||
if ( pars != "0101" || NF+1 - pi != 2 )
|
||||
type = "R??"
|
||||
|
||||
# getdtime, setdtime
|
||||
} else if ( l2l3l4 == "8349" "0200" ) {
|
||||
# AdsReadSysInfo ?
|
||||
pdu = "getdtime"
|
||||
pars = hexblk(pi, 99) # 00
|
||||
if ( pars != "00" )
|
||||
type = "C??"
|
||||
} else if ( l2l3 == "A049" && lastcmd == "getdtime" ) {
|
||||
pdu = "dtime"
|
||||
pars = ascblk(pi, 14) # [mmddyyyyhhmmss]
|
||||
tail = hexblk(pi+14, 99) # 00 00
|
||||
if ( tail != "00 00" ) {
|
||||
pars = pars " " tail
|
||||
type = "R??"
|
||||
}
|
||||
} else if ( l2l3l4 == "8249" "0201" ) {
|
||||
# AdsWriteSysInfo ?
|
||||
pdu = "setdtime"
|
||||
head = hexblk(pi, 1) # 00
|
||||
pars = ascblk(pi+1, 14) # [mmddyyyyhhmmss]
|
||||
tail = hexblk(pi+1+14, 99) # 00 00
|
||||
if ( head != "00" && tail != "00 00" ) {
|
||||
pars = head " " pars " " tail
|
||||
type = "C??"
|
||||
}
|
||||
# response "A0"
|
||||
# pdu = "done" below
|
||||
|
||||
# category
|
||||
} else if ( l2l3l4 == "8249" "0302" ) {
|
||||
# AdsReadCategoryData ?
|
||||
pdu = "category"
|
||||
pars = ascblk(pi, 8) # [category]
|
||||
if ( NF+1 - pi != 8 )
|
||||
type = "C??"
|
||||
} else if ( l2l3 == "A049" && lastcmd == "category" ) {
|
||||
pdu = "category"
|
||||
pars = $(pi) $(pi+1)
|
||||
if ( NF+1 - pi != 2 )
|
||||
type = "R??"
|
||||
|
||||
# openfile, closefile
|
||||
} else if ( l2l3l4 == "8249" "0002" ) {
|
||||
# AdsOpenDataBase ?
|
||||
pdu = "openfile"
|
||||
head = hexblk( pi, 7 )
|
||||
lf2 = hex2dec( $(pi+10) $(pi+9) $(pi+8) $(pi+7) )
|
||||
lf = hex2dec( $(pi+11) )
|
||||
fn = ascblk(pi+12, lf)
|
||||
tail = hexblk( pi+12+lf, 99 )
|
||||
if ( length( fn ) == lf + 2 \
|
||||
&& lf2 == lf + 2 \
|
||||
&& head == "00 00 00 00 00 00 00" \
|
||||
&& tail == "02" )
|
||||
pars = fn
|
||||
else {
|
||||
pars = head " lf2=" lf2 " lf=" lf " " fn " " tail
|
||||
type = "C??"
|
||||
}
|
||||
# set current file-id, to determine num.of record fields
|
||||
if ( fn ~ "Addresses" ) currfid = "05"
|
||||
else if ( fn ~ "Memo" ) currfid = "06"
|
||||
else if ( fn ~ "To Do List" ) currfid = "07"
|
||||
else if ( fn ~ "Schedule" ) currfid = "08"
|
||||
|
||||
} else if ( l2l3 == "A049" && lastcmd == "openfile" ) {
|
||||
pdu = "openfile"
|
||||
pars = "fd=" $(pi+1) $(pi)
|
||||
if ( NF+1 - pi != 2 )
|
||||
type = "R??"
|
||||
} else if ( l2l3l4 == "8249" "0003" ) {
|
||||
# AdsCloseDataBase ? AdsCloseHandle ?
|
||||
pdu = "closefile"
|
||||
pars = "fd=" $(pi+1) $(pi)
|
||||
tail = hexblk( pi+2, 99 )
|
||||
if ( tail != "00 00 00 00" ) {
|
||||
pars = pars " " tail
|
||||
type = "C??"
|
||||
}
|
||||
# unset current file-id on close
|
||||
currfid = ""
|
||||
# response "A0"
|
||||
# pdu = "done" below
|
||||
|
||||
# getflen
|
||||
} else if ( l2l3l4 == "8349" "0103" ) {
|
||||
# AdsGetRecordCount
|
||||
pdu = "getflen"
|
||||
pars = "fd=" $(pi+1) $(pi)
|
||||
tail = hexblk( pi+2, 99 )
|
||||
if ( tail != "00 00 00 00" ) {
|
||||
pars = pars " " tail
|
||||
type = "C??"
|
||||
}
|
||||
} else if ( l2l3l4 == "8349" "0104" ) {
|
||||
# AdsGetModifiedRecordCount
|
||||
pdu = "getflenmod"
|
||||
pars = "fd=" $(pi+1) $(pi)
|
||||
tail = hexblk( pi+2, 99 )
|
||||
if ( tail != "00 00 00 00" ) {
|
||||
pars = pars " " tail
|
||||
type = "C??"
|
||||
}
|
||||
} else if ( l2l3 == "A049" && (lastcmd == "getflen" \
|
||||
|| lastcmd == "getflenmod") ) {
|
||||
pdu = lastcmd
|
||||
pars = "n=" hex2dec( $(pi+1) ($pi) )
|
||||
if ( NF+1 - pi != 2 )
|
||||
type = "R??"
|
||||
|
||||
# read record
|
||||
} else if ( l2l3l4 == "8349" "0105" ) {
|
||||
# AdsReadRecordByID
|
||||
pdu = "readrecrid"
|
||||
pars = "fd=" $(pi+1) $(pi)
|
||||
pars = pars " ri=" $(pi+3) $(pi+2)
|
||||
pars = pars " " $(pi+4)
|
||||
pars = pars " fi=" $(pi+5)
|
||||
reqrid = hex2dec( $(pi+5) $(pi+4) $(pi+3) $(pi+2) )
|
||||
if ( NF+1 - pi != 6 )
|
||||
type = "C??"
|
||||
} else if ( l2l3l4 == "8349" "0106" ) {
|
||||
# AdsReadRecordByIndex
|
||||
pdu = "readrec"
|
||||
reqrid = ""
|
||||
pars = "fd=" $(pi+1) $(pi)
|
||||
pars = pars " ix=" hex2dec( $(pi+3) $(pi+2) )
|
||||
tail = hexblk( pi+4, 99 )
|
||||
if ( tail != "00 00" ) {
|
||||
pars = pars " " tail
|
||||
type = "C??"
|
||||
}
|
||||
} else if ( l2l3l4 == "8349" "0107" ) {
|
||||
# AdsReadNextModifiedRecord
|
||||
pdu = "readrecmod"
|
||||
reqrid = ""
|
||||
pars = "fd=" $(pi+1) $(pi)
|
||||
tail = hexblk(pi+2, 99)
|
||||
if ( NF+1 - pi != 6 || tail != "00 00 00 00" ) {
|
||||
pars = pars " " tail
|
||||
type = "C??"
|
||||
}
|
||||
} else if ( (l2l3 == "A049" \
|
||||
|| l2l3 == "2048") && (lastcmd == "readrec" \
|
||||
|| lastcmd == "readrecmod" \
|
||||
|| lastcmd == "readrecrid") ) {
|
||||
pdu = "rechdr" (l2l3 == "2048" ? "(more)" : "(last)")
|
||||
rsprid = hex2dec( $(pi+3) $(pi+2) $(pi+1) $(pi) )
|
||||
pars = "ri=" $(pi+1) $(pi)
|
||||
pars = pars " " $(pi+2)
|
||||
pars = pars " fi=" $(pi+3)
|
||||
pars = pars " ch=" $(pi+4)
|
||||
if ( NF+1 - pi == 5 )
|
||||
pars = pars " (nodata)"
|
||||
else if ( lastcmd == "readrecrid" && rsprid != reqrid )
|
||||
pars = pars " notfound (" NF+1 - (pi+5) " bytes garbage)"
|
||||
else
|
||||
pars = pars " " recdata( pi+5, $(pi+3) )
|
||||
reqrid = ""
|
||||
} else if ( (l2l3 == "A049" \
|
||||
|| l2l3 == "2048") && lastcmd == "readmore" ) {
|
||||
pdu = "recdat" (l2l3 == "2048" ? "(more)" : "(last)")
|
||||
pars = " "
|
||||
pars = pars " " recdata( pi, "" )
|
||||
|
||||
# write record
|
||||
} else if ( l2l3l4 == "0248" "0108" \
|
||||
|| l2l3l4 == "8249" "0108" ) {
|
||||
# AdsWriteRecord
|
||||
pdu = "writerec" (l2l3 == "0248" ? "(more)" : "(last)")
|
||||
fdesc = $(pi+1) $(pi)
|
||||
zero1 = hexblk(pi+2, 4)
|
||||
p678 = hexblk(pi+6, 3)
|
||||
zero2 = hexblk(pi+9, 2)
|
||||
lrec = hex2dec( $(pi+14) $(pi+13) $(pi+12) $(pi+11) )
|
||||
if ( zero1 == "00 00 00 00" && zero2 == "00 00" ) {
|
||||
pars = "fd=" fdesc " " p678 " lr=" lrec
|
||||
pars = pars " " recdata( pi+15, currfid )
|
||||
} else {
|
||||
pars = "fd=" fdesc " " zero1 " " p678 " " zero2 " lr=" lrec
|
||||
pars = pars " " recdata( pi+15, currfid )
|
||||
type = "C??"
|
||||
}
|
||||
# update record
|
||||
} else if ( l2l3l4 == "0248" "0109" \
|
||||
|| l2l3l4 == "8249" "0109" ) {
|
||||
# AdsUpdateRecord
|
||||
pdu = "updatrec" (l2l3 == "0248" ? "(more)" : "(last)")
|
||||
pars1 = "fd=" $(pi+1) $(pi)
|
||||
pars1 = pars1 " ri=" $(pi+3) $(pi+2)
|
||||
pars1 = pars1 " " $(pi+4)
|
||||
pars1 = pars1 " fi=" $(pi+5)
|
||||
pars1 = pars1 " " hexblk(pi+6, 3)
|
||||
zero2 = hexblk(pi+9, 2)
|
||||
pars2 = " lr=" hex2dec( $(pi+14) $(pi+13) $(pi+12) $(pi+11) )
|
||||
if ( zero2 == "00 00" ) {
|
||||
pars = pars1 pars2
|
||||
pars = pars " " recdata( pi+15, currfid )
|
||||
} else {
|
||||
pars = pars1 " " zero2 pars2
|
||||
pars = pars " " recdata( pi+15, currfid )
|
||||
type = "C??"
|
||||
}
|
||||
} else if ( (l2l3 == "0248" \
|
||||
|| l2l3 == "8249") && (lastcmd == "writerec(more)" \
|
||||
|| lastcmd == "updatrec(more)") ) {
|
||||
pdu = substr(lastcmd, 1, 8)
|
||||
pdu = pdu (l2l3 == "0248" ? "(more)" : "(last)")
|
||||
pars = " "
|
||||
pars = pars " " recdata( pi-2, "" )
|
||||
# response l2 == "90"
|
||||
# pdu = "writemore" below
|
||||
} else if ( l2l3 == "A049" && (lastcmd == "writerec(last)" \
|
||||
|| lastcmd == "updatrec(last)") ) {
|
||||
pdu = substr(lastcmd, 1, 8)
|
||||
pars = "ri=" $(pi+1) $(pi)
|
||||
pars = pars " " $(pi+2)
|
||||
pars = pars " fi=" $(pi+3)
|
||||
if ( NF+1 - pi != 4 )
|
||||
type = "R??"
|
||||
|
||||
# delete record
|
||||
} else if ( l2l3l4 == "8249" "0102" ) {
|
||||
# AdsDeleteRecord
|
||||
pdu = "deleterec"
|
||||
pars = "fd=" $(pi+1) $(pi)
|
||||
pars = pars " ri=" $(pi+3) $(pi+2)
|
||||
pars = pars " " $(pi+4)
|
||||
pars = pars " fi=" $(pi+5)
|
||||
if ( NF+1 - pi != 6 || $(pi+4) != "00" )
|
||||
type = "C??"
|
||||
# response l2 == "A0"
|
||||
# pdu = "done" below
|
||||
|
||||
# reset changeflag
|
||||
} else if ( l2l3l4 == "8249" "010A" ) {
|
||||
# AdsCommitRecord
|
||||
pdu = "resetchg"
|
||||
pars = "fd=" $(pi+1) $(pi)
|
||||
pars = pars " ri=" $(pi+3) $(pi+2)
|
||||
pars = pars " " $(pi+4)
|
||||
pars = pars " fi=" $(pi+5)
|
||||
if ( $(pi+4) != "00" || NF+1 - pi != 6 )
|
||||
type = "C??"
|
||||
# response l2 == "A0"
|
||||
# pdu = "done" below
|
||||
|
||||
}
|
||||
|
||||
# short PDUs with Level-2 id-byte only
|
||||
} else if ( NF == 2+3 ) {
|
||||
if ( $3 == "83" ) {
|
||||
pdu = "readmore"
|
||||
} else if ( $3 == "90" ) {
|
||||
pdu = "writemore"
|
||||
} else if ( $3 == "81" ) {
|
||||
pdu = "disconn"
|
||||
} else if ( $3 == "A0" ) {
|
||||
pdu = "done"
|
||||
}
|
||||
}
|
||||
|
||||
if ( $1 == "WRx" ) {
|
||||
lastcmd = pdu
|
||||
if ( pdu == "" ) type = "C??" # unknown command PDU
|
||||
if ( type !~ "^C..$" )
|
||||
print "INTERNAL ERROR"
|
||||
} else { # "RDx"
|
||||
lastrsp = pdu
|
||||
if ( pdu == "" ) type = "R??" # unknown response PDU
|
||||
if ( type !~ "^R..$" )
|
||||
print "INTERNAL ERROR"
|
||||
}
|
||||
|
||||
if ( type == "C??" || type == "R??" \
|
||||
|| DEBUG || printhex )
|
||||
print # show hex data for unknown PDU / params
|
||||
printf( "%s %2d\t", type, $2 )
|
||||
if ( pdu == "" ) {
|
||||
for ( i = 3; i <= NF; ++i ) printf( " %s", $i )
|
||||
printf( "\n" )
|
||||
} else {
|
||||
printf( " %-14s %s\n", pdu, pars )
|
||||
}
|
||||
}
|
||||
' -
|
||||
}
|
||||
|
||||
# process options
|
||||
#
|
||||
LEVEL=all
|
||||
while getopts "l:s:aDh" OPT
|
||||
do case $OPT in
|
||||
l ) LEVEL=$OPTARG ;;# level of output
|
||||
s ) STAMP="-vstamp=$OPTARG" ;;# prepend lineno/time stamp
|
||||
a ) ASCII=1 ;;# also ASCII chars
|
||||
D ) DEBUG="-vDEBUG=1" ; KEEPTMP=1 ;;# debug/diagnostic
|
||||
h|? ) usage ;;# for other options give help and exit
|
||||
esac
|
||||
done
|
||||
shift `expr $OPTIND - 1`
|
||||
[ $# -eq 1 -o $# -eq 2 ] || usage
|
||||
|
||||
# the real work ..
|
||||
#
|
||||
case "$LEVEL" in
|
||||
all)
|
||||
PASS1="ic35prot $STAMP $DEBUG"
|
||||
if [ -n "$ASCII" ]
|
||||
then PASS2=showascii
|
||||
else PASS2=cat
|
||||
fi
|
||||
;;
|
||||
syn2)
|
||||
PASS1="ic35prot -vskip=3 $DEBUG"
|
||||
if [ -n "$ASCII" ]
|
||||
then PASS2=showascii
|
||||
else PASS2=cat
|
||||
fi
|
||||
;;
|
||||
syn4)
|
||||
PASS1="ic35prot -vskip=3"
|
||||
PASS2="ic35L4prot $DEBUG"
|
||||
;;
|
||||
*)
|
||||
echo "$PROGNAME -- unsupported output level: $LEVEL"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
if [ $# -eq 2 ] ; then
|
||||
if [ "$1" != "-" ] && expr "`file $1`" : '.*\<gzip.*' >/dev/null ; then
|
||||
tar -xOzf $1 $2 | tr -d '\015' | $PASS1 | $PASS2 | $PAGER
|
||||
else
|
||||
tar -xOf $1 $2 | tr -d '\015' | $PASS1 | $PASS2 | $PAGER
|
||||
fi
|
||||
else
|
||||
if [ "$1" != "-" ] && expr "`file $1`" : '.*\<gzip.*' >/dev/null ; then
|
||||
zcat $1 | tr -d '\015' | $PASS1 | $PASS2 | $PAGER
|
||||
else
|
||||
cat $1 | tr -d '\015' | $PASS1 | $PASS2 | $PAGER
|
||||
fi
|
||||
fi
|
|
@ -0,0 +1,991 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2001 Thomas Schulz *
|
||||
* */
|
||||
static char rcsid[] =
|
||||
"$Id: ic35mgr.c,v 1.20 2001/11/20 23:08:35 thosch Exp $"; /*
|
||||
* *
|
||||
* IC35 manager *
|
||||
* *
|
||||
*************************************************************************
|
||||
* *
|
||||
* ??? is "fixme" mark: sections of code needing fixes *
|
||||
* *
|
||||
* conditional compile on NO_LOGSIM: if #defined, logging of the *
|
||||
* IC35 communications as well as simulated communication are NOT *
|
||||
* supported, default WITH logging and com-simulation support. *
|
||||
* *
|
||||
* for usage run ic35mgr -h or see function usage() below. *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include <stdio.h> /* printf(), .. */
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
#include <string.h> /* memcpy(), strcpy() ..*/
|
||||
#include <ctype.h> /* islower(), .. */
|
||||
#include <getopt.h> /* getopt(), optarg, .. */
|
||||
#include <time.h> /* struct tm, time() .. */
|
||||
#include <utime.h> /* struct utimbuf, .. */
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "util.h" /* FALSE, .. */
|
||||
#include "comio.h" /* COM_SIMINIT(), .. */
|
||||
#include "mgrtrans.h" /* IC35mgr transactions */
|
||||
NOTUSED(rcsid)
|
||||
|
||||
|
||||
extern char * pkgvers; /* these are all */
|
||||
extern char * pkgdate; /* in versinfo.c, which is */
|
||||
extern char * bldinfo; /* auto-generated by Makefile */
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* IC35 manager commands */
|
||||
/* ==================================== */
|
||||
|
||||
/* report IC35 status
|
||||
* ------------------
|
||||
*/
|
||||
static int
|
||||
ic35mgrstat( char * devname, char * statfname )
|
||||
{
|
||||
int mmcnum;
|
||||
int rval;
|
||||
char label[11+1];
|
||||
|
||||
if ( (rval = mconnect( devname, statfname )) != OK )
|
||||
return rval;
|
||||
|
||||
for ( mmcnum = 1; mmcnum <= 2; ++mmcnum ) {
|
||||
if ( (rval = mmc_status( mmcnum )) < 0 )
|
||||
break;
|
||||
if ( rval != 0 ) {
|
||||
if ( (rval = mmc_label( mmcnum, label )) < 0 )
|
||||
break;
|
||||
message( "MMCard%d found, label: \"%s\"", mmcnum, label );
|
||||
} else {
|
||||
message( "MMCard%d not present", mmcnum );
|
||||
}
|
||||
}
|
||||
|
||||
mdisconnect();
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/* backup IC35 database to file
|
||||
* ----------------------------
|
||||
*/
|
||||
static int
|
||||
ic35backup( char * devname, char * fname )
|
||||
{
|
||||
int rval;
|
||||
|
||||
if ( (rval = mconnect( devname, NULL )) != OK )
|
||||
return rval;
|
||||
|
||||
rval = readdatabase( fname );
|
||||
|
||||
mdisconnect();
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* restore IC35 database from file
|
||||
* -------------------------------
|
||||
*/
|
||||
static int
|
||||
ic35restore( char * devname, char * fname )
|
||||
{
|
||||
int rval;
|
||||
|
||||
if ( (rval = mconnect( devname, NULL )) != OK )
|
||||
return rval;
|
||||
|
||||
rval = writedatabase( fname );
|
||||
|
||||
mdisconnect();
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/* list IC35 MMCard(s) directories
|
||||
* -------------------------------
|
||||
* list looks like:
|
||||
* MMCardn "Label"
|
||||
* size filetimestamp attr filepath
|
||||
* nnnnnnnnnn yyyy-mm-dd hh:mm:ss xxx MMCard1\subdir\filename.ext
|
||||
*/
|
||||
static int
|
||||
mmcdirlist( char * dirpath )
|
||||
{
|
||||
MMCDIR * dirp;
|
||||
MMCDIRENT * dirent;
|
||||
size_t pfxlen;
|
||||
char * subdir;
|
||||
char attrtext[4+1];
|
||||
int rval, rc;
|
||||
|
||||
if ( (dirp = mmc_opendir( dirpath )) == NULL )
|
||||
return ERR;
|
||||
pfxlen = strlen( dirpath ) + 1;
|
||||
rval = OK;
|
||||
while ( (dirent = mmc_readdir( dirp )) != NULL ) {
|
||||
switch ( dirent->attr ) {
|
||||
case MMCattrDirectory: strcpy( attrtext, "dir" ); break;
|
||||
case MMCattrArchive: strcpy( attrtext, "arc" ); break;
|
||||
default: sprintf( attrtext, "0x%02X", dirent->attr & 0xFF );
|
||||
}
|
||||
printf( "%10ld %s %4s %s\\%s\n",
|
||||
dirent->size, mmctstampstr( dirent->tstamp ),
|
||||
attrtext, dirpath, dirent->name );
|
||||
fflush( stdout );
|
||||
if ( dirent->attr & MMCattrDirectory
|
||||
&& strcmp( dirent->name, ".." ) != 0
|
||||
&& (subdir = malloc( pfxlen + strlen(dirent->name) + 1 )) != NULL ) {
|
||||
sprintf( subdir, "%s\\%s", dirpath, dirent->name );
|
||||
rc = mmcdirlist( subdir );
|
||||
if ( rval == OK ) rval = rc;
|
||||
free( subdir );
|
||||
}
|
||||
}
|
||||
rc = mmc_closedir( dirp );
|
||||
if ( rval == OK ) rval = rc;
|
||||
return rval; /* errcode of first failure or success OK */
|
||||
}
|
||||
static int
|
||||
ic35mmcdir( char * devname )
|
||||
{
|
||||
int mmcnum;
|
||||
int rval;
|
||||
char label[11+1];
|
||||
char dirpath[7+1];
|
||||
|
||||
if ( (rval = mconnect( devname, NULL )) != OK )
|
||||
return rval;
|
||||
|
||||
for ( mmcnum = 1; mmcnum <= 2; ++mmcnum ) {
|
||||
if ( (rval = mmc_status( mmcnum )) < 0 )
|
||||
break;
|
||||
if ( rval == 0 ) {
|
||||
message( "MMCard%d not present", mmcnum );
|
||||
continue;
|
||||
}
|
||||
if ( (rval = mmc_label( 1, label )) < 0 )
|
||||
break;
|
||||
printf( "MMCard%d \"%s\"\n", mmcnum, label );
|
||||
fflush( stdout );
|
||||
sprintf( dirpath, "MMCard%d", mmcnum );
|
||||
if ( (rval = mmcdirlist( dirpath )) < 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
mdisconnect();
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* IC35 MMCard file commands */
|
||||
/* ==================================== */
|
||||
|
||||
#define MINBLKSZ 1 /* min.blocksize */
|
||||
#define MAXBLKSZ 16350 /* max.blocksize (found by experiments) */
|
||||
|
||||
#define ERR_mmcpfx -1
|
||||
#define ERR_mmcnum -2
|
||||
#define ERR_mmcslash -3
|
||||
#define ERR_mmcbadpath -4
|
||||
|
||||
static char * MMCard = "MMCard";
|
||||
|
||||
static int blocksize; /* read/write buffer size mmcget/mmcput */
|
||||
|
||||
/* check,convert MMCard path to IC35 format & get MMCard number
|
||||
* ------------------------------------------------------
|
||||
* the ic35path will be checked (slash means / or \):
|
||||
* - prefix must be "MMCard" in lowercase or uppercase or mixed
|
||||
* - MMCard number after prefix must be '1' or '2'
|
||||
* - slash after MMCard number (unless the path ends there)
|
||||
* - no adjacent slashes
|
||||
* - at most one dot between slashes
|
||||
* - max. 8 characters after slash until dot or slash or end
|
||||
* - max. 3 characters after dot until slash or end
|
||||
* the ic35path will be translated to match IC35 requirements:
|
||||
* translate '/' to '\' dir separators and lowercase to upper.
|
||||
* the translation is done in place, i.e. the argument string
|
||||
* is modified.
|
||||
* returns:
|
||||
* -1 ERR, missing "MMCard" prefix
|
||||
* -2 ERR, bad MMCard number (not 1,2)
|
||||
* -3 ERR, missing slash/backslash after "MMCard[12]"
|
||||
* -4 ERR, bad path component (too long, >1 dot, adjacent slashes)
|
||||
*
|
||||
* parameter mode: if 1 create directories
|
||||
*/
|
||||
static int
|
||||
_ic35mmcpath( char * ic35path , int mode)
|
||||
{
|
||||
MMCDIR * mdirp;
|
||||
int mmcnum;
|
||||
char * ptr;
|
||||
char * pdot;
|
||||
char * pslash;
|
||||
|
||||
/* check/set "MMCard" prefix in ic35fpath */
|
||||
if ( strncasecmp( ic35path, MMCard, strlen(MMCard) ) != 0
|
||||
|| ! isdigit( ic35path[strlen(MMCard)] ) )
|
||||
return ERR_mmcpfx; /* error: missing MMCard prefix */
|
||||
memcpy( ic35path, MMCard, strlen(MMCard) );
|
||||
/* check MMCard number and slash/backslash after prefix */
|
||||
ptr = ic35path + strlen(MMCard);
|
||||
if ( *ptr != '1' && *ptr != '2' )
|
||||
return ERR_mmcnum; /* error: bad MMCard number */
|
||||
mmcnum = *ptr - '0';
|
||||
++ptr;
|
||||
if ( *ptr == 0 ) return mmcnum; /* allow just MMCard<n> */
|
||||
if ( *ptr == '/' ) *ptr = '\\';
|
||||
if ( *ptr != '\\' )
|
||||
return ERR_mmcslash; /* error: miss slash/backslash */
|
||||
/* check path components for 8+3, too many dots, etc. */
|
||||
pslash = ptr++; pdot = NULL;
|
||||
do {
|
||||
switch ( *ptr ) {
|
||||
case '/':
|
||||
case '\\':
|
||||
if (mode == 1) {
|
||||
/* create directory if it does not yet exist */
|
||||
*ptr = 0;
|
||||
if ((mdirp = mmc_opendir(ic35path)) == NULL)
|
||||
mdirp = mmc_createdir(ic35path);
|
||||
mmc_closedir(mdirp);
|
||||
}
|
||||
*ptr = '\\';
|
||||
/* fall through */
|
||||
case '\0':
|
||||
if ( ptr - (pslash+1) == 0 ) {
|
||||
if (*ptr == 0) *pslash = 0; /* remove trailing slash */
|
||||
else return ERR_mmcbadpath; /* error: adjacent slashes */
|
||||
}
|
||||
if ( (pdot != NULL && ptr - (pdot+1) > 3)
|
||||
|| (pdot == NULL && ptr - (pslash+1) > 8) )
|
||||
return ERR_mmcbadpath; /* error: too long since slash */
|
||||
pslash = ptr; pdot = NULL;
|
||||
break;
|
||||
case '.':
|
||||
if ( pdot != NULL )
|
||||
return ERR_mmcbadpath; /* error: too many dots */
|
||||
if ( ptr - (pslash+1) > 8 )
|
||||
return ERR_mmcbadpath; /* error: too long before dot */
|
||||
pdot = ptr;
|
||||
break;
|
||||
}
|
||||
} while ( *ptr++ );
|
||||
/* convert ic35path '/' to '\\', lowercase to uppercase */
|
||||
for ( ptr = ic35path+strlen(MMCard); *ptr; ++ptr ) {
|
||||
if ( islower( *ptr ) )
|
||||
*ptr = (char)toupper( *ptr );
|
||||
}
|
||||
return mmcnum;
|
||||
}
|
||||
|
||||
/* output MMCard path error message
|
||||
* --------------------------------
|
||||
*/
|
||||
static void
|
||||
_mmcpatherror( int errnum, char * ic35path )
|
||||
{
|
||||
switch ( errnum ) {
|
||||
case ERR_mmcpfx:
|
||||
error( "missing \"%s\" prefix in IC35 filepath: %s", MMCard, ic35path );
|
||||
break;
|
||||
case ERR_mmcnum:
|
||||
error( "bad MMCard number in IC35 filepath: %s", ic35path );
|
||||
break;
|
||||
case ERR_mmcslash:
|
||||
error( "missing \\ or / in IC35 filepath: %s", ic35path );
|
||||
break;
|
||||
case ERR_mmcbadpath:
|
||||
default:
|
||||
error( "bad path component in IC35 filepath: %s", ic35path );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* get filename from IC35 MMCard path
|
||||
* ----------------------------------
|
||||
* derive local filename from base filename in ic35path, i.e. leading
|
||||
* directory components removed, and translate to lowercase.
|
||||
* the buffer for the local filename is strdup()'d and shall be freed
|
||||
* by caller.
|
||||
*/
|
||||
static char *
|
||||
_dupic35fname( char * ic35path, int mode)
|
||||
{
|
||||
char * ptr;
|
||||
char * fname;
|
||||
|
||||
/* create copy */
|
||||
if ( (fname = strdup( ic35path )) == NULL )
|
||||
return NULL;
|
||||
|
||||
/* convert to unix filename, creating dirs on the way */
|
||||
ptr = fname;
|
||||
while (*ptr) {
|
||||
if (*ptr == '\\' || *ptr == '/') {
|
||||
if ( mode == 1 ) {
|
||||
/* create subdir */
|
||||
*ptr = 0;
|
||||
if (mkdir(fname, 0700) < 0
|
||||
&& errno != EEXIST ) {
|
||||
perror(fname);
|
||||
}
|
||||
}
|
||||
*ptr++ = '/';
|
||||
} else {
|
||||
*ptr++ = tolower( *ptr );
|
||||
}
|
||||
}
|
||||
return fname;
|
||||
}
|
||||
|
||||
static void progress( int mode, char* ipath, char *upath, ulong curr, ulong total)
|
||||
{
|
||||
fprintf( stderr, "\r%s %s %s %s %ld",
|
||||
mode? "read": "write", ipath,
|
||||
mode? "->" : "<-", upath, (curr+511)/1024);
|
||||
if (total) fprintf( stderr, "/%ldk, %ld%% ", (total+511)/1024,
|
||||
curr*100/total);
|
||||
else fprintf( stderr, "k ");
|
||||
}
|
||||
|
||||
/* read file from IC35 MMCard
|
||||
* --------------------------
|
||||
* the ic35path will be translated to match IC35 requirements:
|
||||
* translate '/' to '\' dir separators and lowercase to upper.
|
||||
* on absent local filename (NULL or empty string) derive it from
|
||||
* base filename in ic35path, i.e. leading directory components
|
||||
* removed, translated to lowercase.
|
||||
* e.g. mmcard1/Ic35\App\Reversi.APP will be translated
|
||||
* to MMCard1\IC35\APP\REVERSI.APP and local file reversi.app
|
||||
* the local file's timestamp will be set to the IC35 file's.
|
||||
* (but IC35 seems to errorneously set the IC35 file's timestamp
|
||||
* to the time of read, although the IC35 file is not modified!?)
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
mmcget( char * ic35path, char * a_fname )
|
||||
{
|
||||
int rbuffsize = 5 * 1024;
|
||||
char * fname;
|
||||
MMCFILE * mmcfp;
|
||||
MMCDIRENT * mmcfstat;
|
||||
FILE * fp;
|
||||
struct utimbuf ftime;
|
||||
uchar * buff;
|
||||
size_t blen;
|
||||
int rlen;
|
||||
ulong frlen;
|
||||
int rval = OK;
|
||||
ulong size;
|
||||
|
||||
if ( MINBLKSZ <= blocksize && blocksize <= MAXBLKSZ )
|
||||
rbuffsize = blocksize;
|
||||
|
||||
else if ( blocksize != 0 )
|
||||
error( "bad buffer size %d, using default %d", blocksize, rbuffsize );
|
||||
|
||||
/* create fname from basename(ic35path) if absent */
|
||||
if ( a_fname && *a_fname ) {
|
||||
fname = a_fname;
|
||||
} else
|
||||
if ( (fname = _dupic35fname( ic35path, 1 )) == NULL ) {
|
||||
error( "no memory for local filename from %s", ic35path );
|
||||
return ERR;
|
||||
}
|
||||
|
||||
if ( (mmcfp = mmc_openfile( ic35path, MMCopenexist )) != NULL ) {
|
||||
if ( (mmcfstat = mmc_statfile( mmcfp )) != NULL ) {
|
||||
size = mmcfstat->size;
|
||||
if ( (buff = malloc( blen = rbuffsize )) != NULL ) {
|
||||
if ( (fp = fopen( fname, "w" )) != NULL ) {
|
||||
rval = OK;
|
||||
frlen = 0;
|
||||
progress( 1, ic35path, fname, frlen, size );
|
||||
while ( (rlen = mmc_readfile( mmcfp, buff, blen )) > 0 ) {
|
||||
frlen += rlen;
|
||||
progress( 1, ic35path, fname, frlen, size );
|
||||
if ( fwrite( buff, 1, rlen, fp ) != rlen ) {
|
||||
error( "write error %s: %s (%d)",
|
||||
fname, strerror(errno), errno );
|
||||
rval = ERR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose( fp );
|
||||
if ( rlen == 0 && rval == OK ) {
|
||||
ftime.actime = time( NULL );
|
||||
ftime.modtime = mmctstampunixtime( mmcfstat->tstamp );
|
||||
utime( fname, &ftime ); /* set file modtime from IC35 */
|
||||
fprintf( stderr, "\n" );
|
||||
} else /* mmc_readfile() or fwrite() failed */
|
||||
rval = ERR;
|
||||
} else /* (fp = fopen()) == NULL */
|
||||
error( "cannot open %s: %s (%d)",
|
||||
fname, strerror(errno), errno );
|
||||
free( buff );
|
||||
} else /* (buff = malloc()) == NULL */
|
||||
error( "no memory for read buffer (%d)", rbuffsize );
|
||||
} else /* mmc_statfile() failed */
|
||||
rval = ERR;
|
||||
mmc_closefile( mmcfp );
|
||||
} else /* mmc_openfile() failed */
|
||||
rval = ERR;
|
||||
if ( fname != a_fname )
|
||||
free( fname );
|
||||
return rval;
|
||||
}
|
||||
|
||||
static int
|
||||
ic35mmcget( char * devname, char * ic35path, char * a_fname )
|
||||
{
|
||||
int mmcnum;
|
||||
int rval;
|
||||
|
||||
/* check ic35path, check/set "MMCard" prefix and */
|
||||
/* convert '/' to '\\', lowercase to uppercase */
|
||||
if ( (mmcnum = _ic35mmcpath( ic35path, 0 )) < 0 ) {
|
||||
_mmcpatherror( mmcnum, ic35path );
|
||||
return ERR;
|
||||
}
|
||||
/* connect to IC35 in SyncStation via serial device */
|
||||
if ( (rval = mconnect( devname, NULL )) != OK )
|
||||
return rval;
|
||||
/* get MMCard status (else other MMCard ops would fail) */
|
||||
if ( (rval = mmc_status( mmcnum )) <= 0 ) {
|
||||
if ( rval == 0 )
|
||||
message( "MMCard%d not present", mmcnum );
|
||||
mdisconnect();
|
||||
return ERR;
|
||||
}
|
||||
|
||||
/* read file from IC35 MMCard */
|
||||
rval = mmcget( ic35path, a_fname);
|
||||
|
||||
/* cleanup and disconnect from IC35 */
|
||||
mdisconnect();
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* get complete tree from IC35 MMCard(s)
|
||||
* -------------------------------
|
||||
* dirpath = subdir from which to start
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
static int
|
||||
mmcgettree( char * dirpath )
|
||||
{
|
||||
MMCDIR * dirp;
|
||||
MMCDIRENT * dirent;
|
||||
size_t pfxlen;
|
||||
char * subdir;
|
||||
char * ic35path;
|
||||
int rval, rc;
|
||||
|
||||
if ( (dirp = mmc_opendir( dirpath )) == NULL )
|
||||
return ERR;
|
||||
pfxlen = strlen( dirpath ) + 1;
|
||||
rval = OK;
|
||||
while ( (dirent = mmc_readdir( dirp )) != NULL ) {
|
||||
switch ( dirent->attr ) {
|
||||
case MMCattrDirectory:
|
||||
if (strcmp(dirent->name, ".." ) != 0
|
||||
&& (subdir = malloc( pfxlen + strlen(dirent->name) + 1 )) != NULL ) {
|
||||
sprintf(subdir, "%s\\%s", dirpath, dirent->name );
|
||||
rc = mmcgettree(subdir);
|
||||
if ( rval == OK ) rval = rc;
|
||||
free(subdir);
|
||||
}
|
||||
break;
|
||||
case MMCattrArchive:
|
||||
ic35path = malloc(pfxlen + strlen(dirent->name) + 1 );
|
||||
sprintf(ic35path, "%s\\%s", dirpath, dirent->name);
|
||||
mmcget(ic35path, NULL);
|
||||
free(ic35path);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
rc = mmc_closedir( dirp );
|
||||
if ( rval == OK ) rval = rc;
|
||||
return rval; /* errcode of first failure or success OK */
|
||||
}
|
||||
|
||||
static int
|
||||
ic35mmcgettree( char * devname, char * ic35path)
|
||||
{
|
||||
int mmcnum;
|
||||
int rval;
|
||||
char dirpath[7+1];
|
||||
|
||||
if (ic35path) {
|
||||
/* check ic35path, check/set "MMCard" prefix and */
|
||||
/* convert '/' to '\\', lowercase to uppercase */
|
||||
if ( (mmcnum = _ic35mmcpath( ic35path, 0 )) < 0 ) {
|
||||
_mmcpatherror( mmcnum, ic35path );
|
||||
return ERR;
|
||||
}
|
||||
if ( (rval = mconnect( devname, NULL )) != OK )
|
||||
return rval;
|
||||
if ( (rval = mmc_status( mmcnum )) == 0 ) {
|
||||
message( "MMCard%d not present", mmcnum );
|
||||
rval = ERR;
|
||||
} else if (rval > 0)
|
||||
rval = mmcgettree( ic35path );
|
||||
}
|
||||
else {
|
||||
if ( (rval = mconnect( devname, NULL )) != OK )
|
||||
return rval;
|
||||
for ( mmcnum = 1; mmcnum <= 2; ++mmcnum ) {
|
||||
if ( (rval = mmc_status( mmcnum )) < 0 )
|
||||
break;
|
||||
if ( rval == 0 ) {
|
||||
message( "MMCard%d not present", mmcnum );
|
||||
continue;
|
||||
}
|
||||
sprintf( dirpath, "MMCard%d", mmcnum );
|
||||
if ( (rval = mmcgettree( dirpath )) < 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
mdisconnect();
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* write file to IC35 MMCard
|
||||
* -------------------------
|
||||
* see ic35mmcget() comment about ic35path conversions and deriving
|
||||
* fname from it if a_fname is NULL or empty.
|
||||
*/
|
||||
|
||||
static int
|
||||
mmcput(char * ic35path, char * a_fname )
|
||||
{
|
||||
int wbuffsize = 2 * 1024;
|
||||
MMCFILE * mmcfp;
|
||||
FILE * fp;
|
||||
uchar * buff;
|
||||
size_t blen;
|
||||
char * fname;
|
||||
int rlen;
|
||||
ulong fwlen;
|
||||
ulong size;
|
||||
int rval = OK;
|
||||
struct stat statbuf;
|
||||
|
||||
if ( MINBLKSZ <= blocksize && blocksize <= MAXBLKSZ )
|
||||
wbuffsize = blocksize;
|
||||
else if ( blocksize != 0 )
|
||||
error( "bad buffer size %d, using default %d", blocksize, wbuffsize );
|
||||
|
||||
/* create fname from basename(ic35path) if absent */
|
||||
if ( a_fname && *a_fname ) {
|
||||
fname = a_fname;
|
||||
} else
|
||||
if ( (fname = _dupic35fname( ic35path, 0 )) == NULL ) {
|
||||
error( "no memory for local filename from %s", ic35path );
|
||||
return ERR;
|
||||
}
|
||||
|
||||
/* write file to IC35 MMCard */
|
||||
if ( (mmcfp = mmc_openfile( ic35path, MMCcreatrunc )) != NULL ) {
|
||||
if ( (buff = malloc( blen = wbuffsize )) != NULL ) {
|
||||
if ( (fp = fopen( fname, "r" )) != NULL ) {
|
||||
rval = OK;
|
||||
fwlen = 0;
|
||||
stat(fname, &statbuf);
|
||||
size = statbuf.st_size;
|
||||
progress( 0, ic35path, fname, fwlen, size );
|
||||
while ( (rlen = fread( buff, 1, blen, fp )) > 0 ) {
|
||||
if ( mmc_writefile( mmcfp, buff, rlen ) != rlen ) {
|
||||
rval = ERR;
|
||||
break;
|
||||
}
|
||||
fwlen += rlen;
|
||||
progress( 0, ic35path, fname, fwlen, size );
|
||||
}
|
||||
if ( rlen <= 0 && feof( fp ) && rval == OK ) {
|
||||
fprintf( stderr, "\n" );
|
||||
} else { /* fread() or mmc_writefile() failed */
|
||||
if ( rval != ERR )
|
||||
error( "read error %s: %s (%d)",
|
||||
fname, strerror(errno), errno );
|
||||
rval = ERR;
|
||||
}
|
||||
fclose( fp );
|
||||
} else /* (fp = fopen()) == NULL */
|
||||
error( "cannot open %s: %s (%d)",
|
||||
fname, strerror(errno), errno );
|
||||
free( buff );
|
||||
} else /* (buff = malloc()) == NULL */
|
||||
error( "no memory for write buffer (%d)", wbuffsize );
|
||||
mmc_closefile( mmcfp );
|
||||
} else /* mmc_openfile() failed */
|
||||
rval = ERR;
|
||||
if ( fname != a_fname )
|
||||
free( fname );
|
||||
return rval;
|
||||
}
|
||||
|
||||
static int
|
||||
ic35mmcput( char * devname, char * ic35path, char * a_fname )
|
||||
{
|
||||
int mmcnum;
|
||||
int rval;
|
||||
|
||||
/* check ic35path, check/set "MMCard" prefix and */
|
||||
/* convert '/' to '\\', lowercase to uppercase */
|
||||
if ( (mmcnum = _ic35mmcpath( ic35path, 0 )) < 0 ) {
|
||||
_mmcpatherror( mmcnum, ic35path );
|
||||
return ERR;
|
||||
}
|
||||
/* connect to IC35 in SyncStation via serial device */
|
||||
if ( (rval = mconnect( devname, NULL )) != OK )
|
||||
return rval;
|
||||
/* get MMCard status (else other MMCard ops would fail) */
|
||||
if ( (rval = mmc_status( mmcnum )) <= 0 ) {
|
||||
if ( rval == 0 )
|
||||
message( "MMCard%d not present", mmcnum );
|
||||
mdisconnect();
|
||||
return ERR;
|
||||
}
|
||||
rval = mmcput(ic35path, a_fname );
|
||||
|
||||
/* cleanup and disconnect from IC35 */
|
||||
mdisconnect();
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* put complete tree to IC35 MMCard(s)
|
||||
* -------------------------------
|
||||
* dirpath = subdir from which to start
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
static int
|
||||
mmcputtree( char * dirpath )
|
||||
{
|
||||
DIR * dirp;
|
||||
struct dirent * dirent;
|
||||
size_t pfxlen;
|
||||
char * path;
|
||||
int rval, rc;
|
||||
int mmcnum;
|
||||
struct stat statbuf;
|
||||
|
||||
if ( (dirp = opendir( dirpath )) == NULL )
|
||||
return ERR;
|
||||
pfxlen = strlen( dirpath ) + 1;
|
||||
rval = OK;
|
||||
while ( (dirent = readdir( dirp )) != NULL ) {
|
||||
if (strcmp(dirent->d_name, ".." ) == 0) continue;
|
||||
if (strcmp(dirent->d_name, "." ) == 0) continue;
|
||||
path = malloc(pfxlen + strlen(dirent->d_name) + 1 );
|
||||
if (path == NULL) {
|
||||
rval = ERR;
|
||||
break;
|
||||
}
|
||||
sprintf(path, "%s/%s", dirpath, dirent->d_name);
|
||||
if (stat(path, &statbuf) == -1) {
|
||||
rval = ERR;
|
||||
break;
|
||||
}
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
rval = mmcputtree(path);
|
||||
} else if (S_ISREG(statbuf.st_mode)) {
|
||||
/* convert to IC35 name */
|
||||
if ( (mmcnum = _ic35mmcpath( path, 1)) < 0 ) {
|
||||
_mmcpatherror( mmcnum, path );
|
||||
return ERR;
|
||||
}
|
||||
mmcput(path, NULL);
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
rc = closedir( dirp );
|
||||
if ( rval == OK ) rval = rc;
|
||||
return rval; /* errcode of first failure or success OK */
|
||||
}
|
||||
|
||||
static int
|
||||
ic35mmcputtree( char * devname, char * ic35path)
|
||||
{
|
||||
int mmcnum;
|
||||
int rval;
|
||||
char * tmp;
|
||||
|
||||
/* check ic35path, check/set "MMCard" prefix and */
|
||||
/* convert '/' to '\\', lowercase to uppercase */
|
||||
tmp = strdup(ic35path);
|
||||
mmcnum = _ic35mmcpath( tmp, 0 );
|
||||
free(tmp);
|
||||
if ( mmcnum < 0 ) {
|
||||
_mmcpatherror( mmcnum, tmp );
|
||||
return ERR;
|
||||
}
|
||||
if ( (rval = mconnect( devname, NULL )) != OK )
|
||||
return rval;
|
||||
if ( (rval = mmc_status( mmcnum )) == 0 ) {
|
||||
message( "MMCard%d not present", mmcnum );
|
||||
rval = ERR;
|
||||
} else if (rval > 0)
|
||||
rval = mmcputtree( ic35path );
|
||||
mdisconnect();
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* delete file on IC35 MMCard
|
||||
* -------------------------
|
||||
*/
|
||||
static int
|
||||
ic35mmcdel( char * devname, char * ic35path )
|
||||
{
|
||||
int mmcnum;
|
||||
int rval;
|
||||
|
||||
/* check ic35path, check/set "MMCard" prefix and */
|
||||
/* convert '/' to '\\', lowercase to uppercase */
|
||||
if ( (mmcnum = _ic35mmcpath( ic35path, 0 )) < 0 ) {
|
||||
_mmcpatherror( mmcnum, ic35path );
|
||||
return ERR;
|
||||
}
|
||||
|
||||
/* connect to IC35 in SyncStation via serial device */
|
||||
if ( (rval = mconnect( devname, NULL )) != OK )
|
||||
return rval;
|
||||
/* get MMCard status (else delete MMCard file fails) */
|
||||
if ( (rval = mmc_status( mmcnum )) > 0 ) {
|
||||
message( "delete %s", ic35path );
|
||||
rval = mmc_delfile( ic35path ); /* delete IC35 MMCard file */
|
||||
} else if ( rval == 0 ) {
|
||||
message( "MMCard%d not present", mmcnum );
|
||||
rval = ERR;
|
||||
}
|
||||
/* disconnect from IC35 */
|
||||
mdisconnect();
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------- M A I N - program ----------------------------- */
|
||||
static void
|
||||
versinfo( void )
|
||||
{
|
||||
printf( "IC35manager for GNU/Linux %s (%s)\n", pkgvers, pkgdate );
|
||||
printf( "%s\n", bldinfo );
|
||||
printf(
|
||||
"Copyright (C) 2001 Thomas Schulz\n"
|
||||
"This is free software; see the GNU General Public Licence version 2 in\n"
|
||||
"the file named COPYING for copying conditions. There is NO warranty.\n"
|
||||
);
|
||||
}
|
||||
static void
|
||||
usage( void )
|
||||
{
|
||||
static char * usetext[] = {
|
||||
"usage: ic35mgr [option..] command [argument..]",
|
||||
"commands and arguments are:",
|
||||
" status [FILE] report IC35 status (and write to FILE)",
|
||||
" backup FILE backup IC35 database to FILE",
|
||||
" restore FILE restore IC35 database from FILE",
|
||||
" mmcdir list contents of IC35 MMCard(s)",
|
||||
" mmcdel IC35PATH delete MMCard file IC35PATH",
|
||||
" mmcget IC35PATH [FILE] read FILE from IC35PATH on IC35 MMCard",
|
||||
" mmcgettree [IC35PATH] read file tree starting at IC35PATH on IC35 MMCard",
|
||||
" mmcput IC35PATH [FILE] write FILE to IC35PATH on IC35 MMCard",
|
||||
" mmcputtree IC35PATH write file tree starting at IC35PATH to IC35 MMCard",
|
||||
" IC35PATH e.g. MMCard1/ic35/app/reversi.app will be",
|
||||
" converted to MMCard1\\IC35\\APP\\REVERSI.APP on IC35",
|
||||
" filename FILE is taken from IC35PATH if absent",
|
||||
"options in short and long form are:",
|
||||
" -d DEV --device=DEV serial device with IC35 connected, default /dev/ic35",
|
||||
" -b SIZE --blocksize=SIZE block size for mmcget / mmcput, default 5120 / 2048",
|
||||
" -n NINC --nice=NINC lower process priority for restore,mmcput, default 2",
|
||||
#ifndef NO_LOGSIM
|
||||
" -l FILE --logfile=FILE log communications to FILE, default no logging",
|
||||
" -s FILE --simfile=FILE simulate communication with IC35 using FILE",
|
||||
" (create simulation FILE from logfile with 'ic35log')",
|
||||
#endif
|
||||
" -V --version show version information and exit",
|
||||
" -h --help show this help and exit",
|
||||
NULL
|
||||
};
|
||||
char ** lptr;
|
||||
|
||||
for ( lptr = usetext; *lptr != NULL; ++lptr )
|
||||
printf( "%s\n", *lptr );
|
||||
}
|
||||
|
||||
int
|
||||
main( int argc, char *argv[] )
|
||||
{
|
||||
static struct option const long_opts[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "device", required_argument, NULL, 'd' },
|
||||
{ "blocksize", required_argument, NULL, 'b' },
|
||||
{ "nice", required_argument, NULL, 'n' },
|
||||
#ifndef NO_LOGSIM
|
||||
{ "logfile", required_argument, NULL, 'l' },
|
||||
{ "simfile", required_argument, NULL, 's' },
|
||||
#endif
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
char * devname = "/dev/ic35";
|
||||
char * nicearg = "2";
|
||||
char * command = NULL;
|
||||
#ifndef NO_LOGSIM
|
||||
char * logfname = NULL;
|
||||
char * simfname = NULL;
|
||||
#endif
|
||||
int rval;
|
||||
|
||||
/*
|
||||
* parse command line
|
||||
*/
|
||||
for ( ; ; ) {
|
||||
switch ( getopt_long( argc, argv,
|
||||
#ifndef NO_LOGSIM
|
||||
"l:s:"
|
||||
#endif
|
||||
"d:b:hV", long_opts, NULL ) ) {
|
||||
default: /* invalid option */
|
||||
fprintf( stderr, "use 'ic35mgr --help' for more information\n" );
|
||||
return 1;
|
||||
case 'h': /* show Help and exit */
|
||||
usage();
|
||||
return 0;
|
||||
case 'V': /* show Version and exit */
|
||||
versinfo();
|
||||
return 0;
|
||||
case 'd': /* serial Device where IC35 */
|
||||
devname = optarg;
|
||||
continue;
|
||||
case 'b': /* buffer size for mmcget,put */
|
||||
blocksize = atoi( optarg );
|
||||
continue;
|
||||
case 'n': /* nice processs priority */
|
||||
nicearg = optarg;
|
||||
continue;
|
||||
#ifndef NO_LOGSIM
|
||||
case 'l': /* communication logfile */
|
||||
logfname = optarg;
|
||||
continue;
|
||||
case 's': /* simulate: no communication */
|
||||
simfname = optarg;
|
||||
continue;
|
||||
#endif /*NO_LOGSIM*/
|
||||
case -1: /* end of options */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( argc < optind+1 ) {
|
||||
fatal( "missing command\n"
|
||||
"use 'ic35mgr --help' for more information" );
|
||||
return 1;
|
||||
}
|
||||
if ( atoi( nicearg ) == 0 && !isdigit(*nicearg) ) {
|
||||
fatal( "non-integer nice argument: %s", nicearg );
|
||||
return 1;
|
||||
}
|
||||
com_waitnice( atoi( nicearg ) );
|
||||
|
||||
/*
|
||||
* initial info to logfile: date,time, version, command line
|
||||
* if 'logfname' is NULL or empty, nothing will be logged.
|
||||
*/
|
||||
LOG_INIT(( logfname, "ic35mgr", 0 ));
|
||||
LOG_PROGINFO(( "ic35mgr", pkgvers, pkgdate, bldinfo ));
|
||||
LOG_ARGSINFO(( argc, argv ));
|
||||
|
||||
/*
|
||||
* setup simulated communication if requested
|
||||
*/
|
||||
COM_SIMINIT(( simfname ));
|
||||
|
||||
/*
|
||||
* process command
|
||||
*/
|
||||
command = argv[optind]; /* note command */
|
||||
argv += optind, argc -= optind; /* skip options */
|
||||
rval = 1;
|
||||
if ( strcmp( command, "status" ) == 0 ) {
|
||||
if ( argc <= 2 )
|
||||
rval = ic35mgrstat( devname, argc > 1 ? argv[1] /*???*/
|
||||
: "/tmp/ic35.stat" );
|
||||
else
|
||||
error( "too many arguments" );
|
||||
} else if ( strcmp( command, "backup" ) == 0 ) {
|
||||
if ( argc == 2 )
|
||||
rval = ic35backup( devname, argv[1] );
|
||||
else
|
||||
error( argc < 2 ? "missing backup file"
|
||||
: "too many arguments" );
|
||||
} else if ( strcmp( command, "restore" ) == 0 ) {
|
||||
if ( argc == 2 )
|
||||
rval = ic35restore( devname, argv[1] );
|
||||
else
|
||||
error( argc < 2 ? "missing restore file"
|
||||
: "too many arguments" );
|
||||
} else if ( strcmp( command, "mmcdir" ) == 0 ) {
|
||||
if ( argc == 1 )
|
||||
rval = ic35mmcdir( devname ) == OK ? 0 : 1;
|
||||
else
|
||||
error( "too many arguments" );
|
||||
} else if ( strcmp( command, "mmcdel" ) == 0 ) {
|
||||
if ( argc == 2 )
|
||||
rval = ic35mmcdel( devname, argv[1] ) == OK ? 0 : 1;
|
||||
else
|
||||
error( argc < 2 ? "missing ic35path"
|
||||
: "too many arguments" );
|
||||
} else if ( strcmp( command, "mmcget" ) == 0 ) {
|
||||
if ( argc == 2 || argc == 3 )
|
||||
rval = ic35mmcget( devname, argv[1], argc == 3 ? argv[2] : NULL );
|
||||
else
|
||||
error( argc < 2 ? "missing ic35path"
|
||||
: "too many arguments" );
|
||||
} else if ( strcmp( command, "mmcgettree" ) == 0 ) {
|
||||
if ( argc == 1 || argc == 2 )
|
||||
rval = ic35mmcgettree( devname, argc == 2 ? argv[1] : NULL );
|
||||
else
|
||||
error( "too many arguments" );
|
||||
} else if ( strcmp( command, "mmcput" ) == 0 ) {
|
||||
if ( argc == 2 || argc == 3 )
|
||||
rval = ic35mmcput( devname, argv[1], argc == 3 ? argv[2] : NULL );
|
||||
else
|
||||
error( argc < 2 ? "missing ic35path,file"
|
||||
: "too many arguments" );
|
||||
} else if ( strcmp( command, "mmcputtree" ) == 0 ) {
|
||||
if ( argc == 2 )
|
||||
rval = ic35mmcputtree( devname, argv[1]);
|
||||
else
|
||||
error( argc < 2 ? "missing ic35path,file"
|
||||
: "too many arguments" );
|
||||
} else {
|
||||
error( "unsupported command: %s", command );
|
||||
rval = 1;
|
||||
}
|
||||
if ( rval != OK )
|
||||
rval = 1;
|
||||
|
||||
LOG_CLOSE(());
|
||||
return rval;
|
||||
}
|
|
@ -0,0 +1,980 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000,2001 Thomas Schulz *
|
||||
* */
|
||||
static char rcsid[] =
|
||||
"$Id: ic35sync.c,v 1.19 2001/03/02 02:10:42 tsch Rel $"; /*
|
||||
* *
|
||||
* IC35 synchronize PIM data *
|
||||
* *
|
||||
*************************************************************************
|
||||
* *
|
||||
* ??? is "fixme" mark: sections of code needing fixes *
|
||||
* *
|
||||
* conditional compile on NO_LOGSIM: if #defined, logging of the *
|
||||
* IC35 communications as well as simulated communication are NOT *
|
||||
* supported, default WITH logging and com-simulation support. *
|
||||
* *
|
||||
* for usage run ic35sync -h or see function usage() below. *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include <stdio.h> /* printf(), .. */
|
||||
#include <string.h> /* strcmp(), .. */
|
||||
#include <getopt.h> /* getopt(), optarg, .. */
|
||||
#include <time.h> /* struct tm, time() .. */
|
||||
|
||||
#include "util.h" /* FALSE, .. */
|
||||
#include "comio.h" /* com_siminit() */
|
||||
#include "syntrans.h" /* IC35sync transactions */
|
||||
#include "ic35frec.h" /* FILEADDR, .. */
|
||||
#include "dataio.h" /* IC35sync import/export */
|
||||
NOTUSED(rcsid)
|
||||
|
||||
|
||||
extern char * pkgvers; /* these are all */
|
||||
extern char * pkgdate; /* in versinfo.c, which is */
|
||||
extern char * bldinfo; /* auto-generated by Makefile */
|
||||
|
||||
|
||||
static const int fileids[4] = {
|
||||
FILEADDR,
|
||||
FILEMEMO,
|
||||
FILESCHED,
|
||||
FILETODO
|
||||
};
|
||||
|
||||
|
||||
/* report IC35 status
|
||||
* ------------------
|
||||
* show firmware version, sysinfo (date+time), total and modified
|
||||
* number of records per IC35 file.
|
||||
*/
|
||||
static int
|
||||
ic35status( char * devname, char * passwd )
|
||||
{
|
||||
int i, fileid;
|
||||
int fd;
|
||||
char * fname;
|
||||
int nrec, nmod, nspc;
|
||||
int rval;
|
||||
char ic35dtime[16+1];
|
||||
|
||||
if ( (rval = connect( devname, passwd, ic35dtime )) != OK )
|
||||
return rval;
|
||||
|
||||
for ( i = 0; i < sizeof(fileids)/sizeof(fileids[0]); ++i ) {
|
||||
fileid = fileids[i];
|
||||
rval = ERR;
|
||||
if ( (fname = ic35fname( fileid )) == NULL ) {
|
||||
error( "status failed: bad fileid %02X", fileid );
|
||||
break;
|
||||
}
|
||||
LPRINTF(( L_INFO, "status fid=%02X \"%s\" ..", fileid, fname ));
|
||||
if ( (fd = open_file( ic35fname( fileid ) )) >= 0 ) {
|
||||
if ( (nrec = get_flen( fd )) >= 0 ) {
|
||||
if ( (nmod = get_mod_flen( fd )) >= 0 ) {
|
||||
if ( (nspc = 10 - strlen( fname )) < 0 ) nspc = 0;
|
||||
message( "status \"%s\"%*s total %2d modified %2d records",
|
||||
fname, nspc, "", nrec, nmod );
|
||||
rval = OK;
|
||||
} else
|
||||
error( "status %s failed: get_mod_flen failed", fname );
|
||||
} else
|
||||
error( "status %s failed: get_flen failed", fname );
|
||||
close_file( fd );
|
||||
} else
|
||||
error( "status %s failed: open_file failed", fname );
|
||||
LPRINTF(( L_INFO, "status fid=%02X \"%s\" %s", fileid, fname,
|
||||
rval == OK ? "OK" : "ERR" ));
|
||||
if ( rval != OK )
|
||||
break;
|
||||
}
|
||||
|
||||
disconnect();
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/* run IC35 export session
|
||||
* -----------------------
|
||||
* read all IC35 records and export (i.e. add/update) to PIMfile:
|
||||
* - set modified+created time in PIMrecord if added IC35 record
|
||||
* - set modified time in PIMrecord if updated from IC35 record
|
||||
* - do not change modified time in PIMrecord if same as IC35 record
|
||||
* - set PIMrecord status to CLEAN if added/updated/same as IC35
|
||||
* - set IC35 record-ID to added/updated PIMfile records
|
||||
* changeflags of records in IC35 will not be reset,
|
||||
* records in IC35 will not be modified/deleted, and
|
||||
* sysinfo (date+time) will not be written to IC35.
|
||||
* IC35 overrides PIMfile, PIMfile records not in IC35 remain untouched.
|
||||
*/
|
||||
static int
|
||||
exportfile( int fileid )
|
||||
{
|
||||
char * fname;
|
||||
int fd, nrec, irec;
|
||||
IC35REC * rec;
|
||||
int rval;
|
||||
|
||||
if ( (fname = ic35fname( fileid )) == NULL ) {
|
||||
error( "export failed: bad fileid %02X", fileid );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "exportfile(fid=%02X) \"%s\" ..", fileid, fname ));
|
||||
if ( (rec = new_ic35rec()) == NULL ) {
|
||||
error( "export %s failed: no memory", fname );
|
||||
return ERR;
|
||||
}
|
||||
if ( (fd = open_file( ic35fname( fileid ) )) < 0 ) {
|
||||
error( "export %s failed: open_file failed", fname );
|
||||
del_ic35rec( rec );
|
||||
return ERR;
|
||||
}
|
||||
if ( (nrec = get_flen( fd )) < 0 ) {
|
||||
error( "export %s failed: get_flen failed", fname );
|
||||
close_file( fd );
|
||||
del_ic35rec( rec );
|
||||
return ERR;
|
||||
}
|
||||
message( "export \"%s\", %d records", fname, nrec );
|
||||
rval = OK;
|
||||
for ( irec = 0; irec < nrec; ++irec ) {
|
||||
if ( read_frec( fd, irec, rec ) < 0 ) {
|
||||
rval = ERR;
|
||||
break;
|
||||
}
|
||||
pim_putic35rec( rec );
|
||||
}
|
||||
close_file( fd );
|
||||
del_ic35rec( rec );
|
||||
LPRINTF(( L_INFO, "exportfile(fid=%02X) \"%s\" %s",
|
||||
fileid, fname, rval == OK ? "OK" : "ERR" ));
|
||||
return rval;
|
||||
}
|
||||
static int
|
||||
ic35export( char * devname, char * passwd )
|
||||
{
|
||||
int i, rval;
|
||||
|
||||
if ( (rval = connect( devname, passwd, NULL )) != 0 )
|
||||
return rval;
|
||||
|
||||
for ( i = 0; i < sizeof(fileids)/sizeof(fileids[0]); ++i )
|
||||
if ( (rval = exportfile( fileids[i] )) != OK )
|
||||
break;
|
||||
|
||||
disconnect();
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/* maintain IC35 record table for import,sync
|
||||
* ------------------------------------------
|
||||
*/
|
||||
enum ic35op { /* IC35 record operation */
|
||||
IC35NOACT, /* 0 no action */
|
||||
IC35DELETE, /* 1 delete record */
|
||||
IC35WRITE, /* 2 write new record */
|
||||
IC35UPDATE, /* 3 re-write existing record */
|
||||
IC35COMMIT, /* 4 commit clears changeflag */
|
||||
};
|
||||
struct recop { /* IC35 record,op entry */
|
||||
IC35REC * rec; /* ptr to IC35 record */
|
||||
enum ic35op op; /* record operation to do */
|
||||
void * pim; /* ptr to PIM record */
|
||||
};
|
||||
|
||||
static struct recop * _ic35rectab;
|
||||
static size_t _ic35rectablen;
|
||||
|
||||
#define ADD_CHUNKS 64
|
||||
|
||||
/* put IC35 record and action into table
|
||||
* -------------------------------------
|
||||
* if record already in table, just update action
|
||||
* if free entry available, put record,action there
|
||||
* if table full or not allocated yet, make it bigger
|
||||
* in chunks of
|
||||
*/
|
||||
static void
|
||||
_put_ic35recs( IC35REC * ic35rec, enum ic35op action, void * pimrec )
|
||||
{
|
||||
int i;
|
||||
struct recop * ntab;
|
||||
size_t nlen;
|
||||
|
||||
for ( i = 0; i < _ic35rectablen; ++i ) {
|
||||
if ( _ic35rectab[i].rec == ic35rec ) {
|
||||
_ic35rectab[i].op = action;
|
||||
_ic35rectab[i].pim = pimrec;
|
||||
return;
|
||||
}
|
||||
if ( _ic35rectab[i].rec == NULL )
|
||||
break;
|
||||
}
|
||||
if ( i >= _ic35rectablen ) {
|
||||
nlen = _ic35rectablen + ADD_CHUNKS;
|
||||
if ( (ntab = realloc( _ic35rectab, nlen * sizeof(ntab[0]) )) == NULL )
|
||||
return;
|
||||
memset( ntab+_ic35rectablen, 0, ADD_CHUNKS * sizeof(ntab[0]) );
|
||||
_ic35rectab = ntab;
|
||||
_ic35rectablen = nlen;
|
||||
}
|
||||
_ic35rectab[i].rec = ic35rec;
|
||||
_ic35rectab[i].op = action;
|
||||
_ic35rectab[i].pim = pimrec;
|
||||
}
|
||||
/* get IC35 record and action from table
|
||||
* -------------------------------------
|
||||
* if non-zero 'recid' lookup IC35 record with that record-ID,
|
||||
* otherwise just retrieve first non-NULL record in table.
|
||||
* pass action associated with record to non-NULL 'paction'.
|
||||
* the record will be removed from table !
|
||||
*/
|
||||
static IC35REC *
|
||||
_get_ic35recs( ulong recid, enum ic35op * paction, void ** ppimrec )
|
||||
{
|
||||
int i;
|
||||
IC35REC * rec;
|
||||
|
||||
for ( i = 0; i < _ic35rectablen; ++i ) {
|
||||
if ( (rec = _ic35rectab[i].rec) == NULL )
|
||||
continue;
|
||||
if ( recid == 0 || ic35recid( rec ) == recid ) {
|
||||
if ( paction ) *paction = _ic35rectab[i].op;
|
||||
if ( ppimrec ) *ppimrec = _ic35rectab[i].pim;
|
||||
_ic35rectab[i].op = IC35NOACT;
|
||||
_ic35rectab[i].rec = NULL;
|
||||
return rec;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/* delete IC35 record table
|
||||
* ------------------------
|
||||
* release all non-NULL records in table, then release table
|
||||
* return number of records yet in table, used by "import" to
|
||||
* detect records in IC35 but not in PIMfile.
|
||||
*/
|
||||
static int
|
||||
_del_ic35recs( void )
|
||||
{
|
||||
int i;
|
||||
int only_ic35;
|
||||
|
||||
for ( i = only_ic35 = 0; i < _ic35rectablen; ++i )
|
||||
if ( _ic35rectab[i].rec != NULL ) {
|
||||
++only_ic35; /* IC35 record not in PIMfile */
|
||||
del_ic35rec( _ic35rectab[i].rec );
|
||||
}
|
||||
free( _ic35rectab );
|
||||
_ic35rectab = NULL;
|
||||
_ic35rectablen = 0;
|
||||
return only_ic35; /* num.of records not in PIMfile */
|
||||
}
|
||||
|
||||
|
||||
/* run IC35 import session
|
||||
* -----------------------
|
||||
* read all records from IC35 and compare with PIMfile
|
||||
* - update PIMrecord to IC35 if same record-ID on IC35
|
||||
* - write PIMrecord to IC35 if record not on IC35
|
||||
* and write back new IC35 record-ID to PIMrecord
|
||||
* - reset IC35 record changeflag if same as PIMrecord
|
||||
* - set PIMrecord status to CLEAN
|
||||
* - owner address data must be written with update_frec() and recID 1
|
||||
* otherwise on IC35 in category "Address", but not as owner data
|
||||
* do not delete records neither in IC35 nor in PIMfile
|
||||
* write sysinfo (date+time) if all IC35 records match PIMfile
|
||||
* PIMfile overrides IC35, IC35 records not in PIMfile remain untouched,
|
||||
* sysinfo (date+time) is not written if any IC35 record not in PIMfile.
|
||||
*/
|
||||
static int
|
||||
importfile( int fileid, char * ic35dtime )
|
||||
{
|
||||
char * fname;
|
||||
int fd, nrec, irec;
|
||||
IC35REC * ic35rec;
|
||||
void * pimrec;
|
||||
ulong recid;
|
||||
int n_write, n_update, n_commit;
|
||||
int ic35_not_in_PIM;
|
||||
enum ic35op action;
|
||||
char * actext;
|
||||
int rc, rval;
|
||||
|
||||
if ( (fname = ic35fname( fileid )) == NULL ) {
|
||||
error( "import failed: bad fileid %02X", fileid );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "importfile(fid=%02X) \"%s\" ..", fileid, fname ));
|
||||
if ( (fd = open_file( ic35fname( fileid ) )) < 0 ) {
|
||||
error( "import %s failed: open_file failed", fname );
|
||||
return ERR;
|
||||
}
|
||||
if ( (nrec = get_flen( fd )) < 0 ) {
|
||||
error( "import %s failed: get_flen failed", fname );
|
||||
close_file( fd );
|
||||
return ERR;
|
||||
}
|
||||
/*
|
||||
* read all IC35-records and note them
|
||||
*/
|
||||
message( "import \"%s\", read %d records", fname, nrec );
|
||||
rval = OK;
|
||||
for ( irec = 0; irec < nrec; ++irec ) {
|
||||
if ( (ic35rec = new_ic35rec()) == NULL ) {
|
||||
error( "import %s failed: no memory for ic35rec", fname );
|
||||
rval = ERR;
|
||||
break;
|
||||
}
|
||||
if ( read_frec( fd, irec, ic35rec ) < 0 ) {
|
||||
rval = ERR;
|
||||
break;
|
||||
}
|
||||
_put_ic35recs( ic35rec, IC35NOACT, NULL );
|
||||
}
|
||||
if ( rval != OK ) {
|
||||
close_file( fd );
|
||||
LPRINTF(( L_INFO, "importfile(fid=%02X) \"%s\" rval=ERR", fileid,fname ));
|
||||
return rval;
|
||||
}
|
||||
/*
|
||||
* compare all PIM-records with IC35-records, and do:
|
||||
* - if PIM-record not in IC35, write it to IC35
|
||||
* and write back record-ID from IC35 to PIM-record,
|
||||
* - if different update IC35-record with PIM-record,
|
||||
* - if same commit to IC35 if non-zero changeflag in IC35.
|
||||
* mark all PIM-records CLEAN as they are now same as IC35.
|
||||
* collect IC35 records with actions to do.
|
||||
*/
|
||||
n_write = n_update = n_commit = 0;
|
||||
pim_rewind();
|
||||
while ( (pimrec = pim_getrec( fileid )) != NULL ) {
|
||||
if ( (recid = pim_recid( pimrec )) != 0 /* PIM record-ID on IC35 */
|
||||
&& (ic35rec = _get_ic35recs( recid, NULL, NULL )) != NULL ) {
|
||||
if ( pim_cmpic35rec( ic35rec, pimrec ) == 0 ) {
|
||||
if ( ic35recchg( ic35rec ) == IC35_CLEAN ) {
|
||||
del_ic35rec( ic35rec ); /* same as PIM, unchanged */
|
||||
continue; /* no need for commit */
|
||||
}
|
||||
action = IC35COMMIT; /* same as PIM, commit it */
|
||||
++n_commit;
|
||||
} else {
|
||||
action = IC35UPDATE; /* different, update rec */
|
||||
++n_update;
|
||||
}
|
||||
} else { /* PIMrecord not on IC35 */
|
||||
ic35rec = new_ic35rec();
|
||||
if ( recid == FileRecId(FILEADDR,1) ) {
|
||||
action = IC35UPDATE; /* must update owner-addr */
|
||||
++n_update;
|
||||
} else {
|
||||
action = IC35WRITE; /* write new IC35 record */
|
||||
++n_write;
|
||||
}
|
||||
}
|
||||
pim_updic35rec( ic35rec, pimrec ); /* PIM update/new to IC35 */
|
||||
_put_ic35recs( ic35rec, action, pimrec ); /* add action and PIMrec */
|
||||
}
|
||||
/*
|
||||
* execute actions on IC35 records collected above.
|
||||
* count records with no action, i.e. only existing
|
||||
* on IC35, but not in PIMfile.
|
||||
*/
|
||||
message( "import \"%s\", write %d update %d commit %d records",
|
||||
fname, n_write, n_update, n_commit );
|
||||
ic35_not_in_PIM = 0;
|
||||
while ( (ic35rec = _get_ic35recs( 0, &action, &pimrec )) != NULL ) {
|
||||
rc = 0; actext = "";
|
||||
switch ( action ) {
|
||||
case IC35COMMIT:
|
||||
actext = "commit";
|
||||
rc = commit_frec( fd, ic35recid( ic35rec ) );
|
||||
break;
|
||||
case IC35UPDATE:
|
||||
actext = "update";
|
||||
rc = update_frec( fd, ic35rec );
|
||||
break;
|
||||
case IC35WRITE:
|
||||
actext = "write";
|
||||
rc = write_frec( fd, ic35rec );
|
||||
break;
|
||||
default:
|
||||
++ic35_not_in_PIM;
|
||||
continue;
|
||||
}
|
||||
if ( rc >= 0 ) { /* commit/update/write success */
|
||||
if ( pimrec != NULL ) {
|
||||
pim_set_recid( pimrec, ic35recid( ic35rec ) );
|
||||
pim_set_recstat( pimrec, PIM_CLEAN );
|
||||
}
|
||||
} else { /* commit/update/write failed */
|
||||
error( "import %s failed: %s_frec failed", fname, actext );
|
||||
rval = ERR;
|
||||
}
|
||||
del_ic35rec( ic35rec );
|
||||
}
|
||||
_del_ic35recs();
|
||||
if ( rval == OK )
|
||||
rval = ic35_not_in_PIM; /* any IC35 records not in PIMfile */
|
||||
close_file( fd );
|
||||
LPRINTF(( L_INFO, "importfile(fid=%02X) \"%s\" rval=%d",
|
||||
fileid, fname, rval ));
|
||||
return rval;
|
||||
}
|
||||
static int
|
||||
ic35import( char * devname, char * passwd )
|
||||
{
|
||||
int i, rc, rval;
|
||||
bool ic35_same_as_PIM;
|
||||
char ic35dtime[16+1];
|
||||
|
||||
if ( (rval = connect( devname, passwd, ic35dtime )) != 0 )
|
||||
return rval;
|
||||
set_oldic35dt( ic35dtime );
|
||||
|
||||
rval = OK;
|
||||
ic35_same_as_PIM = TRUE;
|
||||
for ( i = 0; i < sizeof(fileids)/sizeof(fileids[0]); ++i )
|
||||
if ( (rc = importfile( fileids[i], ic35dtime )) != OK ) {
|
||||
ic35_same_as_PIM = FALSE;
|
||||
if ( rc < 0 ) {
|
||||
rval = rc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ic35_same_as_PIM ) {
|
||||
get_newic35dt( ic35dtime );
|
||||
WriteSysInfo( ic35dtime );
|
||||
}
|
||||
|
||||
disconnect();
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/* run IC35 sync session
|
||||
* ---------------------
|
||||
* update PIMfile with IC35 changes (modify/delete) and vice versa
|
||||
* - phase-0: initial export if PIMfile does not contains any records
|
||||
* otherwise phase-3 below would delete all unmodified records on IC35,
|
||||
* as they are regarded deleted from PIMfile.
|
||||
* - phase-1a: update records modified/deleted on IC35 to PIMfile
|
||||
* read all modified records from IC35, if unchanged in PIMfile:
|
||||
* - delete from PIMfile if deleted on IC35,
|
||||
* - update from IC35 to PIMfile if modified on IC35.
|
||||
* note IC35-recID for commit (commit now would disturb read_mod_frec)
|
||||
* conflict if record changed in IC35 AND also in PIMfile, resolve:
|
||||
* - PIMfile overrides IC35: update from PIMrecord to IC35record
|
||||
* will be done in next phase below (now would disturb read_mod_frec),
|
||||
* - IC35 overrides PIMfile: update from IC35record to PIMrecord
|
||||
* ??? ? add changed record on IC35/PIM to PIM/IC35 with conflict mark
|
||||
* - phase-1b: commit handled IC35 changes to IC35
|
||||
* commits noted above to avoid disturbing read_mod_frec, now do them.
|
||||
* - phase-2: update records modified in PIMfile to IC35
|
||||
* - if record exists on IC35, i.e. has record-ID,
|
||||
* read record by ID from IC35, update with PIMrecord
|
||||
* write record to IC35
|
||||
* - if record is new in PIMfile (no record-ID)
|
||||
* create IC35 record from PIMrecord, write to IC35
|
||||
* and writeback new IC35 record-ID to PIMrecord
|
||||
* - phase-3a: records deleted from PIMfile are detected by reading
|
||||
* all records from IC35 and check if record in PIMfile
|
||||
* ??? sanity check IC35 changeflags clean
|
||||
* - PIMfile overrides IC35: note IC35-recID for delete
|
||||
* (delete now would disturb read_frec)
|
||||
* - IC35 overrides PIMfile: re-create PIMrecord from IC35 record
|
||||
* - phase-3b: delete records on IC35
|
||||
* deletes were noted above to avoid disturbing read_frec, now do them.
|
||||
* now there should be no more pending changes neither in IC35 nor in PIM.
|
||||
* write sysinfo (date+time) as now all IC35 records (shall) match PIMfile
|
||||
*/
|
||||
static int
|
||||
syncfile( int fileid, char * ic35dtime )
|
||||
{
|
||||
char * fname;
|
||||
bool initexp;
|
||||
int fd, nrec, irec;
|
||||
IC35REC * ic35rec;
|
||||
void * pimrec;
|
||||
ulong recid;
|
||||
enum ic35op action;
|
||||
int n_commit, n_delete;
|
||||
int rc, rval;
|
||||
|
||||
if ( (fname = ic35fname( fileid )) == NULL ) {
|
||||
error( "sync failed: bad fileid %02X", fileid );
|
||||
return ERR;
|
||||
}
|
||||
/*
|
||||
* phase-0: initial export if PIMfile does not contains any records
|
||||
* otherwise phase-3 below would delete all unmodified records on IC35
|
||||
*/
|
||||
initexp = FALSE;
|
||||
pim_rewind();
|
||||
if ( pim_getrec( fileid ) == NULL ) {
|
||||
message( "sync \"%s\", no PIM records: initial export", fname );
|
||||
if ( (rval = exportfile( fileid )) != OK )
|
||||
return rval;
|
||||
initexp = TRUE;
|
||||
}
|
||||
|
||||
LPRINTF(( L_INFO, "syncfile(fid=%02X) \"%s\" ..", fileid, fname ));
|
||||
if ( (fd = open_file( ic35fname( fileid ) )) < 0 ) {
|
||||
error( "sync %s failed: open_file failed", fname );
|
||||
return ERR;
|
||||
}
|
||||
/*
|
||||
* phase-1a: update records modified/deleted on IC35 to PIMfile
|
||||
* read all modified records from IC35, if unchanged in PIMfile:
|
||||
* - delete from PIMfile if deleted on IC35,
|
||||
* - update from IC35 to PIMfile if modified on IC35.
|
||||
* note IC35-recID for commit (commit now would disturb read_mod_frec)
|
||||
* conflict if record changed in IC35 AND also in PIMfile, resolve:
|
||||
* - PIMfile overrides IC35: update from PIMrecord to IC35record
|
||||
* will be done in next phase below (now would disturb read_mod_frec),
|
||||
* - IC35 overrides PIMfile: update from IC35record to PIMrecord
|
||||
* ? add changed record on IC35/PIM to PIM/IC35 with conflict mark ???
|
||||
*/
|
||||
if ( (nrec = get_mod_flen( fd )) < 0 ) {
|
||||
error( "sync %s failed: get_mod_flen failed", fname );
|
||||
close_file( fd );
|
||||
return ERR;
|
||||
}
|
||||
message( "sync \"%s\", read %d modified records%s",
|
||||
fname, nrec, nrec > 0 ? ", update PIM" : "" );
|
||||
n_commit = 0;
|
||||
rval = OK;
|
||||
for ( irec = 0; irec < nrec; ++irec ) {
|
||||
if ( (ic35rec = new_ic35rec()) == NULL ) {
|
||||
error( "sync %s failed: no memory", fname );
|
||||
rval = ERR;
|
||||
break;
|
||||
}
|
||||
if ( read_mod_frec( fd, ic35rec ) < 0 ) {
|
||||
error( "sync %s failed: read_mod_frec failed", fname );
|
||||
rval = ERR;
|
||||
break;
|
||||
}
|
||||
if ( (pimrec = pim_getrec_byID( ic35recid( ic35rec ) )) == NULL
|
||||
|| pim_recstat( pimrec ) == PIM_CLEAN ) {
|
||||
switch ( ic35recchg( ic35rec ) ) {
|
||||
case IC35_NEW:
|
||||
case IC35_MOD:
|
||||
pim_putic35rec( ic35rec );
|
||||
break;
|
||||
case IC35_DEL:
|
||||
if ( pimrec )
|
||||
pim_delrec( pimrec );
|
||||
break;
|
||||
}
|
||||
_put_ic35recs( ic35rec, IC35COMMIT, NULL );
|
||||
++n_commit;
|
||||
} else {
|
||||
; /*??? CONFLICT: changed on both sides */
|
||||
}
|
||||
}
|
||||
/*
|
||||
* phase-1b: commit handled IC35 changes to IC35
|
||||
* commits noted above to avoid disturbing read_mod_frec, now do them.
|
||||
*/
|
||||
if ( rval == OK && n_commit > 0 ) {
|
||||
message( "sync \"%s\", commit %d IC35 records", fname, n_commit );
|
||||
while ( (ic35rec = _get_ic35recs( 0, &action, NULL )) != NULL ) {
|
||||
if ( action == IC35COMMIT
|
||||
&& commit_frec( fd, ic35recid( ic35rec ) ) < 0 ) {
|
||||
error( "sync %s failed: commit_frec failed", fname );
|
||||
rval = ERR;
|
||||
break;
|
||||
}
|
||||
del_ic35rec( ic35rec );
|
||||
}
|
||||
}
|
||||
_del_ic35recs();
|
||||
if ( rval != OK ) {
|
||||
close_file( fd );
|
||||
LPRINTF(( L_INFO, "syncfile(fid=%02X) \"%s\" rval=ERR", fileid,fname ));
|
||||
return rval;
|
||||
}
|
||||
/*
|
||||
* if initial export was done, update from PIM to IC35 and
|
||||
* check records removed from PIM and delete is not needed.
|
||||
*/
|
||||
if ( initexp ) {
|
||||
close_file( fd );
|
||||
LPRINTF(( L_INFO, "syncfile(fid=%02X) \"%s\" rval=OK", fileid, fname ));
|
||||
return rval;
|
||||
}
|
||||
/*
|
||||
* phase-2: update records modified in PIMfile to IC35
|
||||
* - if record exists on IC35, i.e. has record-ID,
|
||||
* read record by ID from IC35, update with PIMrecord
|
||||
* write record to IC35
|
||||
* - if record is new in PIMfile (no record-ID)
|
||||
* create IC35 record from PIMrecord, write to IC35
|
||||
* and writeback new IC35 record-ID to PIMrecord
|
||||
*/
|
||||
if ( (ic35rec = new_ic35rec()) == NULL ) {
|
||||
close_file( fd );
|
||||
error( "sync %s failed: no memory", fname );
|
||||
return ERR;
|
||||
}
|
||||
message( "sync \"%s\", update IC35", fname );
|
||||
pim_rewind();
|
||||
while ( rval == OK && (pimrec = pim_getrec( fileid )) != NULL ) {
|
||||
switch ( pim_recstat( pimrec ) ) {
|
||||
case PIM_CLEAN:
|
||||
continue;
|
||||
case PIM_DEL:
|
||||
if ( (recid = pim_recid( pimrec )) != 0 ) {
|
||||
if ( delete_frec( fd, recid ) >= 0 ) {
|
||||
pim_delrec( pimrec );
|
||||
} else {
|
||||
error( "sync %s failed: delete_frec failed", fname );
|
||||
rval = ERR;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
error( "bad PIM record status: %d", pim_recstat( pimrec ) );
|
||||
/* full through and handle as PIM_DIRTY */
|
||||
case PIM_DIRTY:
|
||||
if ( (recid = pim_recid( pimrec )) != 0 ) { /* PIMrec on IC35 */
|
||||
if ( (rc = read_id_frec( fd, recid, ic35rec )) < 0 ) {
|
||||
error( "sync %s failed: read_id_frec failed", fname );
|
||||
rval = ERR;
|
||||
break;
|
||||
}
|
||||
if ( rc > 0 ) { /* PIMrec found on IC35 */
|
||||
pim_updic35rec( ic35rec, pimrec );
|
||||
if ( update_frec( fd, ic35rec ) >= 0 ) {
|
||||
pim_set_recstat( pimrec, PIM_CLEAN );
|
||||
} else {
|
||||
error( "sync %s failed: update_frec failed", fname );
|
||||
rval = ERR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} /* PIMrecord not on IC35 */
|
||||
set_ic35recdata( ic35rec, NULL, 0 );
|
||||
pim_updic35rec( ic35rec, pimrec );
|
||||
if ( write_frec( fd, ic35rec ) >= 0 ) {
|
||||
pim_set_recid( pimrec, ic35recid( ic35rec ) );
|
||||
pim_set_recstat( pimrec, PIM_CLEAN );
|
||||
} else {
|
||||
error( "sync %s failed: write_frec failed", fname );
|
||||
rval = ERR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
del_ic35rec( ic35rec ); ic35rec = NULL;
|
||||
if ( rval != OK ) {
|
||||
close_file( fd );
|
||||
LPRINTF(( L_INFO, "syncfile(fid=%02X) \"%s\" rval=ERR", fileid,fname ));
|
||||
return rval;
|
||||
}
|
||||
/*
|
||||
* phase-3a: records deleted from PIMfile are detected by reading
|
||||
* all records from IC35 and check if record in PIMfile
|
||||
* ? sanity check IC35 changeflags clean ???
|
||||
* - PIMfile overrides IC35: note IC35-recID for delete
|
||||
* (delete now would disturb read_frec)
|
||||
* - IC35 overrides PIMfile: re-create PIMrecord from IC35 record
|
||||
*/
|
||||
if ( (nrec = get_flen( fd )) < 0 ) {
|
||||
error( "sync %s failed: get_flen failed", fname );
|
||||
close_file( fd );
|
||||
return ERR;
|
||||
}
|
||||
message( "sync \"%s\", read %d records, check PIM deleted", fname, nrec );
|
||||
n_delete = 0;
|
||||
for ( irec = 0; irec < nrec; ++irec ) {
|
||||
if ( (ic35rec = new_ic35rec()) == NULL ) {
|
||||
error( "sync %s failed: no memory", fname );
|
||||
rval = ERR;
|
||||
break;
|
||||
}
|
||||
if ( read_frec( fd, irec, ic35rec ) < 0 ) {
|
||||
error( "sync %s failed: read_frec failed", fname );
|
||||
rval = ERR;
|
||||
break;
|
||||
}
|
||||
if ( pim_getrec_byID( ic35recid( ic35rec ) ) ) {
|
||||
del_ic35rec( ic35rec );
|
||||
continue;
|
||||
}
|
||||
/*??? sanity check ic35recchg() == 0 ? */
|
||||
/*??? if PIM overrides IC35 */
|
||||
_put_ic35recs( ic35rec, IC35DELETE, NULL );
|
||||
++n_delete;
|
||||
/*??? if IC35 overrides PIM */
|
||||
/*??? pim_putic35rec( ic35rec ); */
|
||||
}
|
||||
/*
|
||||
* phase-3b: delete records on IC35
|
||||
* deletes were noted above to avoid disturbing read_frec, now do them.
|
||||
*/
|
||||
if ( rval == OK && n_delete ) {
|
||||
message( "sync \"%s\", delete %d IC35 records", fname, n_delete );
|
||||
while ( (ic35rec = _get_ic35recs( 0, &action, NULL )) != NULL ) {
|
||||
if ( action == IC35DELETE
|
||||
&& delete_frec( fd, ic35recid( ic35rec ) ) < 0 ) {
|
||||
error( "sync %s failed: delete_frec failed", fname );
|
||||
rval = ERR;
|
||||
break;
|
||||
}
|
||||
del_ic35rec( ic35rec );
|
||||
}
|
||||
}
|
||||
_del_ic35recs();
|
||||
|
||||
close_file( fd );
|
||||
LPRINTF(( L_INFO, "syncfile(fid=%02X) \"%s\" rval=%d",
|
||||
fileid, fname, rval ));
|
||||
return rval;
|
||||
}
|
||||
static int
|
||||
ic35sync( char * devname, char * passwd )
|
||||
{
|
||||
int i, rval;
|
||||
char ic35dtime[16+1];
|
||||
|
||||
if ( (rval = connect( devname, passwd, ic35dtime )) != 0 )
|
||||
return rval;
|
||||
set_oldic35dt( ic35dtime );
|
||||
|
||||
for ( i = 0; i < sizeof(fileids)/sizeof(fileids[0]); ++i ) {
|
||||
if ( (rval = syncfile( fileids[i], ic35dtime )) != OK )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( rval == OK ) {
|
||||
get_newic35dt( ic35dtime );
|
||||
WriteSysInfo( ic35dtime );
|
||||
}
|
||||
|
||||
disconnect();
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------- M A I N - program ----------------------------- */
|
||||
static void
|
||||
versinfo( void )
|
||||
{
|
||||
printf( "IC35sync for GNU/Linux %s (%s)\n", pkgvers, pkgdate );
|
||||
printf( "%s\n", bldinfo );
|
||||
printf(
|
||||
"Copyright (C) 2000,2001 Thomas Schulz\n"
|
||||
"This is free software; see the GNU General Public Licence version 2 in\n"
|
||||
"the file named COPYING for copying conditions. There is NO warranty.\n"
|
||||
);
|
||||
}
|
||||
static void
|
||||
usage( void )
|
||||
{
|
||||
static char * usetext[] = {
|
||||
"usage: ic35sync [option..] command [pimfile..]",
|
||||
"commands are:",
|
||||
" sync synchronize IC35 with pimfile(s) data",
|
||||
" export read all data from IC35 and write to pimfile(s)",
|
||||
" import write to IC35 all data read from pimfile(s)",
|
||||
" status report IC35 status (no pimfile access)",
|
||||
"pimfile contains local Personal Information Management data,",
|
||||
"e.g. in vCard/vCalendar format.",
|
||||
"options in short and long form are:",
|
||||
" -d DEV --device=DEV serial device with IC35 connected, default /dev/ic35",
|
||||
" -p TEXT --password=TEXT password TEXT on IC35, default none",
|
||||
" -f FORM --format=FORM format of pimfile(s), FORM and default pimfile(s):",
|
||||
" vca (default) vCard,vCalendar,Memo, ic35.vcard ic35.vcal ic35.memo",
|
||||
" txt (export only) plain text, ic35.txt",
|
||||
" bin raw binary data, ic35.bin",
|
||||
#ifndef NO_LOGSIM
|
||||
" -l FILE --logfile=FILE log communications to FILE, default no logging",
|
||||
" -s FILE --simfile=FILE simulate communication with IC35 using FILE",
|
||||
" (create simulation FILE from logfile with 'ic35log')",
|
||||
#endif
|
||||
" -V --version show version information and exit",
|
||||
" -h --help show this help and exit",
|
||||
NULL
|
||||
};
|
||||
char ** lptr;
|
||||
|
||||
for ( lptr = usetext; *lptr != NULL; ++lptr )
|
||||
printf( "%s\n", *lptr );
|
||||
}
|
||||
|
||||
int
|
||||
main( int argc, char *argv[] )
|
||||
{
|
||||
static struct option const long_opts[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "device", required_argument, NULL, 'd' },
|
||||
{ "password", required_argument, NULL, 'p' },
|
||||
{ "format", required_argument, NULL, 'f' },
|
||||
#ifndef NO_LOGSIM
|
||||
{ "logfile", required_argument, NULL, 'l' },
|
||||
{ "simfile", required_argument, NULL, 's' },
|
||||
#endif
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
char * passwd = "";
|
||||
char * devname = "/dev/ic35";
|
||||
char * pimfmtstr = "vca";
|
||||
char * command = NULL;
|
||||
char * pimaddrfname = NULL;
|
||||
char * pimvcalfname = NULL;
|
||||
char * pimmemofname = NULL;
|
||||
#ifndef NO_LOGSIM
|
||||
char * logfname = NULL;
|
||||
char * simfname = NULL;
|
||||
#endif
|
||||
int rval;
|
||||
|
||||
/*
|
||||
* parse command line
|
||||
*/
|
||||
for ( ; ; ) {
|
||||
switch ( getopt_long( argc, argv,
|
||||
#ifndef NO_LOGSIM
|
||||
"l:s:"
|
||||
#endif
|
||||
"d:p:f:hV", long_opts, NULL ) ) {
|
||||
default:
|
||||
fprintf( stderr, "use 'ic35sync --help' for more information\n" );
|
||||
return 1;
|
||||
case 'h': /* show Help and exit */
|
||||
usage();
|
||||
return 0;
|
||||
case 'V': /* show Version and exit */
|
||||
versinfo();
|
||||
return 0;
|
||||
case 'd': /* serial Device where IC35 */
|
||||
devname = optarg;
|
||||
continue;
|
||||
case 'p': /* password on IC35 */
|
||||
passwd = optarg;
|
||||
continue;
|
||||
case 'f': /* format of PIMfile */
|
||||
pimfmtstr = optarg;
|
||||
continue;
|
||||
#ifndef NO_LOGSIM
|
||||
case 'l': /* communication logfile */
|
||||
logfname = optarg;
|
||||
continue;
|
||||
case 's': /* simulate: no communication */
|
||||
simfname = optarg;
|
||||
continue;
|
||||
#endif/*NO_LOGSIM*/
|
||||
case -1: /* end of options */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( argc < optind+1 ) {
|
||||
error( "missing command\n"
|
||||
"use 'ic35sync --help' for more information" );
|
||||
return 1;
|
||||
}
|
||||
command = argv[optind];
|
||||
|
||||
/*
|
||||
* initial info to logfile: date,time, version, command line
|
||||
* if 'logfname' is NULL or empty, nothing will be logged.
|
||||
*/
|
||||
LOG_INIT(( logfname, "ic35sync", 0 ));
|
||||
LOG_PROGINFO(( "ic35sync", pkgvers, pkgdate, bldinfo ));
|
||||
LOG_ARGSINFO(( argc, argv ));
|
||||
|
||||
/*
|
||||
* setup simulated communication if requested
|
||||
*/
|
||||
COM_SIMINIT(( simfname ));
|
||||
|
||||
/*
|
||||
* status command does not use pimfile(s)
|
||||
*/
|
||||
if ( strcmp( command, "status" ) == 0 ) {
|
||||
rval = ic35status( devname, passwd ) == OK ? 0 : 1;
|
||||
LOG_CLOSE(());
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* defaults for filenames are:
|
||||
* - no filename
|
||||
* use defaults depending on format
|
||||
* - text format ic35.txt
|
||||
* - binary format ic35.bin
|
||||
* - vCard,vCal format ic35.vcard, ic35.vcal, ic35.memo
|
||||
* - 1 filename
|
||||
* Addresses, Schedule,ToDo, Memo all in 1 file
|
||||
* - 2 filenames
|
||||
* Addresses to 1st file, Schedule,ToDo,Memo to 2nd file
|
||||
* - 3 filenames
|
||||
* Addresses to 1st file, Schedule,ToDo to 2nd, Memo to 3rd
|
||||
*/
|
||||
if ( set_pim_format( pimfmtstr ) != OK ) {
|
||||
error( "unknown format: %s", pimfmtstr );
|
||||
return 1;
|
||||
}
|
||||
argv += optind, argc -= optind; /* skip to non-option arguments */
|
||||
switch ( argc ) {
|
||||
default:
|
||||
error( "max. 3 pimfiles supported, have %d", argc - 1 );
|
||||
return 1;
|
||||
case 4: /* 3 filenames */
|
||||
pimmemofname = argv[3];
|
||||
/* fall through */
|
||||
case 3: /* 2 filenames */
|
||||
pimvcalfname = argv[2];
|
||||
/* fall through */
|
||||
case 2: /* 1 filename */
|
||||
pimaddrfname = argv[1];
|
||||
break;
|
||||
case 1: /* no filename */
|
||||
switch ( pim_format() ) {
|
||||
case PIM_TXT:
|
||||
pimaddrfname = "ic35.txt";
|
||||
break;
|
||||
case PIM_BIN:
|
||||
pimaddrfname = "ic35.bin";
|
||||
break;
|
||||
case PIM_VCA:
|
||||
pimaddrfname = "ic35.vcard";
|
||||
pimvcalfname = "ic35.vcal";
|
||||
pimmemofname = "ic35.memo";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( pim_open( pimaddrfname, pimvcalfname, pimmemofname ) != OK ) {
|
||||
error( "failed to open pimfile(s): %s %s %s\n",
|
||||
pimaddrfname,
|
||||
pimvcalfname ? pimvcalfname : "",
|
||||
pimmemofname ? pimmemofname : "" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* process command
|
||||
*/
|
||||
if ( strcmp( command, "export" ) == 0 ) {
|
||||
rval = ic35export( devname, passwd ) == OK ? 0 : 1;
|
||||
} else if ( strcmp( command, "import" ) == 0 ) {
|
||||
rval = ic35import( devname, passwd ) == OK ? 0 : 1;
|
||||
} else if ( strcmp( command, "sync" ) == 0 ) {
|
||||
rval = ic35sync( devname, passwd ) == OK ? 0 : 1;
|
||||
} else {
|
||||
error( "unsupported command: %s", command );
|
||||
rval = 1;
|
||||
}
|
||||
|
||||
pim_close();
|
||||
LOG_CLOSE(());
|
||||
return rval;
|
||||
}
|
|
@ -0,0 +1,951 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2001 Thomas Schulz *
|
||||
* */
|
||||
static char rcsid[] =
|
||||
"$Id: mgrproto.c,v 1.17 2001/11/20 23:08:35 thosch Exp $"; /*
|
||||
* *
|
||||
* IC35 manager protocol *
|
||||
* *
|
||||
*************************************************************************
|
||||
* *
|
||||
* ??? is "fixme" mark: sections of code needing fixes *
|
||||
* *
|
||||
* IC35 manager protocol *
|
||||
* Mcmdrsp send command-byte, get+check response-byte *
|
||||
* Msendblk send datablock, test checksum, ack/retry *
|
||||
* Mrecvblk receive datablock, test checksum, ack/retry *
|
||||
* MMCard access protocol *
|
||||
* MMCsend send MMCard command using Msendblk *
|
||||
* MMCrecv receive MMCard response using Mrecvblk *
|
||||
* MMCard commands *
|
||||
* MMCgetstatus check if MMCard present / absent *
|
||||
* MMCgetlabel get MMCard label *
|
||||
* MMCdiropen open MMCard directory *
|
||||
* MMCdirgetlen get number of entries in MMCard directory *
|
||||
* MMCdirread read MMCard directory entry *
|
||||
* MMCdirclose close MMCard directory *
|
||||
* MMCfiledel delete MMCard file *
|
||||
* MMCfileopen open MMCard file *
|
||||
* MMCfilestat get MMCard file attributes *
|
||||
* MMCfileread read block from MMCard file *
|
||||
* MMCfilewrite write block to MMCard file *
|
||||
* MMCfileclose close MMCard file *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include <stdlib.h> /* malloc(), .. */
|
||||
#include <string.h> /* memcpy(), .. */
|
||||
|
||||
#include "util.h" /* ERR,OK, uchar, .. */
|
||||
#include "comio.h" /* com_send(), .. */
|
||||
#include "genproto.h" /* putxxx(),getxxx() .. */
|
||||
#include "mgrproto.h"
|
||||
NOTUSED(rcsid)
|
||||
|
||||
#define MAXRETRY 5 /* max.retries for manager protocol */
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* IC35 manager protocol */
|
||||
/* ==================================== */
|
||||
|
||||
/* send command-byte, get+check response-byte
|
||||
* ------------------------------------------
|
||||
*/
|
||||
int
|
||||
Mcmdrsp( uchar cmd, uchar rsp )
|
||||
{
|
||||
uchar rbyte;
|
||||
int retry;
|
||||
|
||||
for ( retry = 0; retry < MAXRETRY; ++retry ) {
|
||||
com_send( &cmd, sizeof(cmd) );
|
||||
if ( com_recv( &rbyte, sizeof(rbyte) ) == sizeof(rbyte)
|
||||
&& rbyte == rsp )
|
||||
return OK;
|
||||
}
|
||||
return ERR;
|
||||
}
|
||||
|
||||
/* local: send/receive block and ack or nak,retry
|
||||
* ----------------------------------------------
|
||||
* used by Msendblk(), Mrecvblk() for ack- or nak-handshake and retry,
|
||||
* the trasnsmit function _sendblk(), _recvblk() is passed as function
|
||||
* pointer 'pfxmit' and will set the appropriate timeout(s).
|
||||
*/
|
||||
static int
|
||||
_xmitblk( uchar * data, size_t dlen, int pfxmit(uchar* data, size_t dlen) )
|
||||
{
|
||||
int old_tmo;
|
||||
int retry;
|
||||
int rval = ERR;
|
||||
|
||||
com_settimeout( old_tmo = com_settimeout( 0 ) );
|
||||
for ( retry = 0; retry < MAXRETRY+1; ++retry ) {
|
||||
rval = (*pfxmit)( data, dlen ); /* xmit data, recv csum */
|
||||
if ( rval == dlen ) { /* datablock xmit OK */
|
||||
if ( Mcmdrsp( MCMDposack, MRSPgotack ) != OK )
|
||||
rval = ERR_acknak;
|
||||
break;
|
||||
} else if ( rval != ERR_recv /* bad checksum/length */
|
||||
&& retry < MAXRETRY ) { /* and retries left */
|
||||
if ( Mcmdrsp( MCMDnegack, MRSPgotack ) != OK ) {
|
||||
rval = ERR_acknak;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
} else /* recv.err / timeout */
|
||||
break; /* or out of retries */
|
||||
}
|
||||
com_settimeout( old_tmo );
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* send block and ack/retry
|
||||
* ------------------------
|
||||
* send database block, receive checksum and test it, on success send
|
||||
* acknowledge, receive ready response and return OK.
|
||||
* on failure send nak and retry, after max.retries return ERR.
|
||||
* -> (block of 'dlen' bytes)
|
||||
* set timeout 10.0 sec
|
||||
* <- cc_cc got them, checksum is cc_cc (arithmetic, LSB first)
|
||||
* set timeout 3.0 sec
|
||||
* -> 60 positive acknowledge
|
||||
* <- A0 got ack
|
||||
* on checksum mismatch send negative acknowledge:
|
||||
* -> 62 negative acknowledge
|
||||
* <- A0 got nak
|
||||
* and restart send block.
|
||||
* the long "(block of 'dlen' bytes)" must be sent with waiting!
|
||||
*/
|
||||
static int
|
||||
_sendblk( uchar * data, size_t dlen )
|
||||
{
|
||||
uchar rcsum[2];
|
||||
int lcsum;
|
||||
ushort cksum;
|
||||
int rval;
|
||||
|
||||
com_sendw( data, dlen ); /* -> data (with wait) */
|
||||
com_settimeout( 10000 ); /* timeout 10.0 sec for chksum */
|
||||
if ( (lcsum = com_recv( rcsum, sizeof(rcsum) )) /* <- checksum */
|
||||
== sizeof(rcsum)
|
||||
&& (cksum = chksum( data, dlen ))
|
||||
== getword( rcsum ) ) {
|
||||
rval = dlen;
|
||||
} else {
|
||||
if ( lcsum == sizeof(rcsum) ) { /* checksum mismatch */
|
||||
LPRINTF(( L_NOISE, "_senddblk: chksum=%04X mismatch", cksum ));
|
||||
rval = ERR_chksum;
|
||||
} else /* recv.error / timeout */
|
||||
rval = ERR_recv;
|
||||
}
|
||||
LPRINTF(( L_NOISE, "_sendblk(data,%d) = %d", dlen, rval ));
|
||||
com_settimeout( 3000 ); /* timeout 3.0 sec ack/nak resp */
|
||||
return rval;
|
||||
}
|
||||
int
|
||||
Msendblk( uchar * data, size_t dlen )
|
||||
{
|
||||
return _xmitblk( data, dlen, _sendblk );
|
||||
}
|
||||
|
||||
/* receive block and ack/retry
|
||||
* ---------------------------
|
||||
* receive data block, on success acknowledge and return OK.
|
||||
* on failure send nak and retry, after max.retries return ERR.
|
||||
* set timeout 2.0 sec
|
||||
* <- (block of 'blen' bytes) cc_cc (arithmetic sum, LSB first)
|
||||
* -> 60 positive acknowledge
|
||||
* <- A0 got ack
|
||||
* on mismatch of checksum or length, send negative acknowledge:
|
||||
* -> 62 negative acknowledge
|
||||
* <- A0 got nak
|
||||
* and restart receive block.
|
||||
*/
|
||||
static int
|
||||
_recvblk( uchar * buff, size_t blen )
|
||||
{
|
||||
uchar rcsum[2];
|
||||
ushort cksum;
|
||||
int lcsum;
|
||||
int rval;
|
||||
|
||||
rcsum[0] = rcsum[1] = (uchar)0x00;
|
||||
com_settimeout( 2000 ); /* timeout 2.0 sec for data,ack */
|
||||
if ( (rval = com_recv( buff, blen )) >= 2 /* <- data */
|
||||
&& (lcsum = com_recv( rcsum, sizeof(rcsum)) ) >= 0 ) { /* <- csum */
|
||||
if ( lcsum == 1 ) {
|
||||
rcsum[1] = buff[--rval]; /* take .. */
|
||||
rcsum[0] = buff[--rval]; /* .. checksum bytes .. */
|
||||
} else if ( lcsum == 0 ) {
|
||||
rcsum[1] = rcsum[0]; /* .. from .. */
|
||||
rcsum[0] = buff[--rval]; /* .. end of datablock */
|
||||
}
|
||||
if ( (cksum = chksum( buff, rval )) != getword( rcsum ) ) {
|
||||
LPRINTF(( L_NOISE, "_recvblk: chksum=%04X mismatch", cksum ));
|
||||
rval = ERR_chksum; /* checksum mismatch */
|
||||
}
|
||||
} else
|
||||
rval = ERR_recv; /* too short for chksum */
|
||||
LPRINTF(( L_NOISE, "_recvblk(buff,%d) = %d", blen, rval ));
|
||||
return rval;
|
||||
}
|
||||
int
|
||||
Mrecvblk( uchar * buff, size_t blen )
|
||||
{
|
||||
return _xmitblk( buff, blen, _recvblk );
|
||||
}
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* MMCard access protocol */
|
||||
/* ==================================== */
|
||||
/*
|
||||
* protocol of MMCard operations
|
||||
* MMCsend
|
||||
* use timeout 0.5 sec
|
||||
* -> 15 are you there ?
|
||||
* <- 90 yes i am here !
|
||||
* -> nn_nn expect nn_nn bytes from me
|
||||
* <- E0 ok, send them
|
||||
* sendretry:
|
||||
* -> (block of nn_nn bytes)
|
||||
* set timeout 10.0 sec
|
||||
* <- cc_cc got them, checksum is cc_cc (arithmetic, LSB first)
|
||||
* set timeout 3.0 sec
|
||||
* -> 60 ack
|
||||
* <- A0 got ack
|
||||
* on checksum mismatch send negative acknowledge:
|
||||
* -> 62 nak
|
||||
* <- A0 got nak
|
||||
* and restart at sendretry.
|
||||
* the long "(block of nn_nn bytes)" must be sent with waiting!
|
||||
* the blocklength nn_nn must be sent with wait before 1st byte!
|
||||
* MMCrecv
|
||||
* set timeout 5.0 sec
|
||||
* <- nn_nn expect nn_nn bytes plus trailing checksum
|
||||
* -> E0 ok, send them
|
||||
* recvretry:
|
||||
* <- (block of nn_nn bytes) cc_cc (arithmetic sum, LSB first)
|
||||
* -> 60 ack
|
||||
* <- A0 got ack
|
||||
* on mismatch of checksum or length, send negative acknowledge:
|
||||
* -> 62 nak
|
||||
* <- A0 got nak
|
||||
* and restart at recvretry.
|
||||
*/
|
||||
|
||||
/* send MMCard command
|
||||
* -------------------
|
||||
*/
|
||||
static int
|
||||
MMCsend( uchar * sbuff, size_t slen )
|
||||
{
|
||||
uchar rchar;
|
||||
uchar slbuff[2];
|
||||
int rval;
|
||||
|
||||
if ( Mcmdrsp( MCMDmmcard, MRSPgotcmd ) == OK ) { /* -> 15 */
|
||||
putword( slbuff, slen ); /* <- 90 */
|
||||
com_sendw( slbuff, sizeof(slbuff) ); /* -> nn_nn (with wait) */
|
||||
if ( com_recv( &rchar, 1 ) == 1 /* <- E0 */
|
||||
&& rchar == MRSPgotlen ) {
|
||||
rval = Msendblk( sbuff, slen ); /* send cmd, ack/retry */
|
||||
if ( rval != slen ) /* Msendblk() bad length */
|
||||
rval = ERR;
|
||||
} else /* com_recv() MRSPgotlen failed */
|
||||
rval = ERR;
|
||||
} else /* Mcmdrsp() failed */
|
||||
rval = ERR;
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* receive MMCard response
|
||||
* -----------------------
|
||||
*/
|
||||
static int
|
||||
MMCrecv( uchar ** prbuff )
|
||||
{
|
||||
int old_tmo;
|
||||
uchar rlbuff[2];
|
||||
size_t rblen;
|
||||
uchar rspgotlen = MRSPgotlen;
|
||||
uchar * rbuff;
|
||||
int rval;
|
||||
|
||||
old_tmo = com_settimeout( 5000 );
|
||||
if ( (rval = com_recv( rlbuff, sizeof(rlbuff) )) == sizeof(rlbuff) ) {
|
||||
rblen = getword( rlbuff ); /* <- nn nn */
|
||||
if ( (rbuff = calloc( rblen, 1 )) != NULL ) {
|
||||
com_send( &rspgotlen, 1 ); /* -> E0 */
|
||||
rval = Mrecvblk( rbuff, rblen ); /* recv resp, ack/retry */
|
||||
if ( rval == rblen ) {
|
||||
*prbuff = rbuff; /* OK, buffer to caller */
|
||||
} else {
|
||||
free( rbuff ); /* Mrecvblk() bad length */
|
||||
rval = ERR;
|
||||
}
|
||||
} else { /* calloc(rblen,1) failed */
|
||||
LPRINTF(( L_ERROR, "MMCrecv: calloc(%d,1) failed", rblen ));
|
||||
rval = ERR;
|
||||
}
|
||||
} else /* com_recv(rlbuff,) failed */
|
||||
rval = ERR;
|
||||
com_settimeout( old_tmo );
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/* ============================ */
|
||||
/* MMCard commands */
|
||||
/* ============================ */
|
||||
|
||||
/*
|
||||
* MMCard command implementation
|
||||
* the MMCard commands correspond to IC35 SDK API functions and are
|
||||
* implemented as remote procedure calls: encode arguments to command
|
||||
* PDU and send it to IC35, receive response PDU from IC35 and decode
|
||||
* results from PDU.
|
||||
* struct mcmdxxxx/mrspxxxx define the command/response PDU encoding.
|
||||
* all MMCxxxx() functions work like:
|
||||
* - _init*pdu() allocates the command PDU buffer and encodes the
|
||||
* command code into it
|
||||
* - encode MMCxxxx() function argument(s) into command PDU buffer
|
||||
* (except fdstat argument)
|
||||
* - _sendrecv() optionally encodes the MMCxxxx() fdstat argument
|
||||
* into the command PDU for file/directory commands,
|
||||
* sends the command PDU to IC35 with MMCsend() and releases it,
|
||||
* receives the response PDU from IC35 with MMCrecv(),
|
||||
* optionally decodes FILE_IDEN from response PDU back into the
|
||||
* fdstat argument,
|
||||
* and returns the status decoded from the response PDU.
|
||||
* - decode MMCxxxx() result arguments
|
||||
* - decode from the response PDU into MMCxxxx() result arguments,
|
||||
* release response PDU buffer and return status from _sendrecv().
|
||||
*/
|
||||
|
||||
/* MMCard command codes */ /* IC35 SDK API function: */
|
||||
#define MMCMDgetstatus 0x20 /* 13.1 mInitialCard() */
|
||||
#define MMCMDgetlabel 0x34 /* 13.4 mGetCardLabel() */
|
||||
#define MMCMDdiropen 0x2A /* 13.14 mOpenDirectory() */
|
||||
#define MMCMDdirgetlen 0x2B /* 13.15 mGetDirectorySubItemNum() */
|
||||
#define MMCMDdirread 0x2C /* 13.16 mGetDirectorySubItem() */
|
||||
#define MMCMDdirclose 0x2E /* 13.18 mCloseDirectory() */
|
||||
#define MMCMDfileopen 0x22 /* 13.6 mOpenFile() */
|
||||
#define MMCMDfilestat 0x26 /* 13.10 mGetFileInfo() */
|
||||
#define MMCMDfilewrite 0x23 /* 13.8 mWriteToFile() */
|
||||
#define MMCMDfileread 0x24 /* 13.9 mReadFromFile() */
|
||||
#define MMCMDfileclose 0x27 /* 13.11 mCloseFile() */
|
||||
#define MMCMDfiledel 0x28 /* 13.13 mDeleteFile() */
|
||||
|
||||
/* MMCard PDU definitions
|
||||
* ----------------------
|
||||
*/
|
||||
/* getstatus, getlabel */
|
||||
struct mcmdstatlbl { /* stat label */
|
||||
char cmd[1]; /* 20 or 34 */
|
||||
char mmcard[6]; /* "MMCard" */
|
||||
char mmcnum[1]; /* "1" or "2" */
|
||||
uchar zero[1]; /* 00 */
|
||||
};
|
||||
struct mrspstat {
|
||||
uchar stat[2]; /* 01 00 or FF FF */
|
||||
};
|
||||
struct mrsplbl {
|
||||
uchar stat[2]; /* 01 00 */
|
||||
uchar zero[1]; /* 00 */
|
||||
char label[8+1]; /* [MMClabel] 00 */
|
||||
char reserved[11]; /* 20 20 00 00 00 00 00 00 00 00 48 */
|
||||
};
|
||||
/* diropen, fileopen */
|
||||
struct mcmdfdopen { /* dopen fopen */
|
||||
char cmd[1]; /* 2A or 22 */
|
||||
uchar mode[2]; /* 01 00 */
|
||||
uchar path[1]; /* [MMCardx\dir] 00 */
|
||||
};
|
||||
struct mrspfdopen {
|
||||
uchar stat[2]; /* 01 00 */
|
||||
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
|
||||
};
|
||||
/* dirglen, dirclose, filestat, fileclose */
|
||||
struct mcmdfdstatcl { /* dglen dcls fstat fcls*/
|
||||
char cmd[1]; /* 2B 2E 26 27 */
|
||||
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
|
||||
uchar zero[1]; /* 00 */
|
||||
};
|
||||
struct mrspdirglen {
|
||||
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
|
||||
uchar stat[2]; /* 01 00 */
|
||||
uchar ndent[2]; /* nn_nn */
|
||||
};
|
||||
struct mrspfdclose {
|
||||
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
|
||||
};
|
||||
/* dirread, fileread */
|
||||
struct mcmdfdread { /* dread fread */
|
||||
uchar cmd[1]; /* 2C or 24 */
|
||||
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
|
||||
union {
|
||||
uchar index[2]; /* in_dx dir-index */
|
||||
uchar blen[2]; /* nn_nn file-bufflen */
|
||||
} u;
|
||||
uchar zero[1]; /* 00 */
|
||||
};
|
||||
struct mrspfdstat {
|
||||
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
|
||||
uchar stat[2]; /* 01 00 */
|
||||
FILE_INFO dirent; /* (24 bytes FILE_INFO) */
|
||||
};
|
||||
struct mrspfileread {
|
||||
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
|
||||
uchar stat[2]; /* 01 00 */
|
||||
uchar rlen[2]; /* nn_nn */
|
||||
uchar data[1]; /* filedata[nn_nn] */
|
||||
};
|
||||
/* filedel */
|
||||
struct mcmdfiledel {
|
||||
char cmd[1]; /* 28 */
|
||||
uchar path[1]; /* [MMCardx\file] 00 */
|
||||
};
|
||||
/*resp mrspstat
|
||||
*/
|
||||
/* filewrite */
|
||||
struct mcmdfilewrite {
|
||||
uchar cmd[1]; /* 23 */
|
||||
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
|
||||
uchar wlen[2]; /* nn_nn */
|
||||
uchar data[1]; /* filedata[nn_nn] 00 */
|
||||
};
|
||||
struct mrspfilewrite {
|
||||
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
|
||||
uchar stat[2]; /* 01 00 */
|
||||
};
|
||||
|
||||
union mcmdpdu { /* MMCard command PDU */
|
||||
uchar cmd;
|
||||
struct mcmdstatlbl status;
|
||||
struct mcmdstatlbl label;
|
||||
struct mcmdfdopen diropen;
|
||||
struct mcmdfdstatcl dirglen;
|
||||
struct mcmdfdread dirread;
|
||||
struct mcmdfdstatcl dirclose;
|
||||
struct mcmdfiledel filedel;
|
||||
struct mcmdfdopen fileopen;
|
||||
struct mcmdfdstatcl filestat;
|
||||
struct mcmdfdread fileread;
|
||||
struct mcmdfilewrite filewrite;
|
||||
struct mcmdfdstatcl fileclose;
|
||||
uchar data[1];
|
||||
};
|
||||
union mrsppdu { /* MMCard response PDU */
|
||||
uchar stat[2];
|
||||
struct mrspstat status;
|
||||
struct mrsplbl label;
|
||||
struct mrspfdopen diropen;
|
||||
struct mrspdirglen dirglen;
|
||||
struct mrspfdstat dirread;
|
||||
struct mrspfdclose dirclose;
|
||||
struct mrspstat filedel;
|
||||
struct mrspfdopen fileopen;
|
||||
struct mrspfdstat filestat;
|
||||
struct mrspfileread fileread;
|
||||
struct mrspfilewrite filewrite;
|
||||
struct mrspfdclose fileclose;
|
||||
uchar data[1];
|
||||
};
|
||||
union mmcpdu { /* generic MMCard PDU */
|
||||
union mcmdpdu cmd;
|
||||
union mrsppdu rsp;
|
||||
};
|
||||
|
||||
|
||||
/* MMCard PDU table
|
||||
* ----------------
|
||||
*/
|
||||
#define SPDULENOF(type) sizeof( struct type )
|
||||
#define FIDENOFFS(type) offsetof( struct type, iden )
|
||||
#define RSTATOFFS(type) offsetof( struct type, stat )
|
||||
#define NOFFS 0xFFFF
|
||||
|
||||
struct mpdudesc { /* MMCard PDU description */
|
||||
uchar cmd; /* command code */
|
||||
size_t slen; /* fixed length of PDU */
|
||||
size_t sidenoffs; /* offset FILE_IDEN in cmd PDU */
|
||||
size_t rstatoffs; /* offset status in resp.PDU */
|
||||
size_t ridenoffs; /* offset FILE_IDEN in rsp PDU */
|
||||
};
|
||||
struct mpdudesc mmcpdutab[] = {
|
||||
{ MMCMDgetstatus, SPDULENOF(mcmdstatlbl), NOFFS,
|
||||
RSTATOFFS(mrspstat), NOFFS, },
|
||||
{ MMCMDgetlabel, SPDULENOF(mcmdstatlbl), NOFFS,
|
||||
RSTATOFFS(mrsplbl), NOFFS, },
|
||||
{ MMCMDdiropen, SPDULENOF(mcmdfdopen), NOFFS,
|
||||
RSTATOFFS(mrspfdopen), FIDENOFFS(mrspfdopen) },
|
||||
{ MMCMDdirgetlen, SPDULENOF(mcmdfdstatcl), FIDENOFFS(mcmdfdstatcl),
|
||||
RSTATOFFS(mrspdirglen), FIDENOFFS(mrspdirglen) },
|
||||
{ MMCMDdirread, SPDULENOF(mcmdfdread), FIDENOFFS(mcmdfdread),
|
||||
RSTATOFFS(mrspfdstat), FIDENOFFS(mrspfdstat) },
|
||||
{ MMCMDdirclose, SPDULENOF(mcmdfdstatcl), FIDENOFFS(mcmdfdstatcl),
|
||||
NOFFS, FIDENOFFS(mrspfdclose) },
|
||||
{ MMCMDfileopen, SPDULENOF(mcmdfdopen), NOFFS,
|
||||
RSTATOFFS(mrspfdopen), FIDENOFFS(mrspfdopen) },
|
||||
{ MMCMDfilestat, SPDULENOF(mcmdfdstatcl), FIDENOFFS(mcmdfdstatcl),
|
||||
RSTATOFFS(mrspfdstat), FIDENOFFS(mrspfdstat) },
|
||||
{ MMCMDfilewrite, SPDULENOF(mcmdfilewrite), FIDENOFFS(mcmdfilewrite),
|
||||
RSTATOFFS(mrspfilewrite), FIDENOFFS(mrspfilewrite) },
|
||||
{ MMCMDfileread, SPDULENOF(mcmdfdread), FIDENOFFS(mcmdfdread),
|
||||
RSTATOFFS(mrspfileread), FIDENOFFS(mrspfileread) },
|
||||
{ MMCMDfileclose, SPDULENOF(mcmdfdstatcl), FIDENOFFS(mcmdfdstatcl),
|
||||
NOFFS, FIDENOFFS(mrspfdclose), },
|
||||
{ MMCMDfiledel, SPDULENOF(mcmdfiledel), NOFFS,
|
||||
RSTATOFFS(mrspstat), NOFFS },
|
||||
{ 0, 0, 0,
|
||||
0, 0 }
|
||||
};
|
||||
|
||||
/* init MMCard command PDU
|
||||
* -----------------------
|
||||
* lookup MMCard PDU description by command code
|
||||
* allocate MMCard PDU buffer plus optionally variable length
|
||||
* setup MMCard command code and return allocated PDU length
|
||||
*/
|
||||
static int /* init variable length PDU */
|
||||
_initvpdu( uchar cmd, size_t varlen, union mmcpdu ** ppdu )
|
||||
{
|
||||
struct mpdudesc * pmpdu;
|
||||
union mmcpdu * spdu;
|
||||
size_t pdulen;
|
||||
|
||||
for ( pmpdu = mmcpdutab; pmpdu->slen != 0; ++pmpdu )
|
||||
if ( pmpdu->cmd == cmd ) {
|
||||
pdulen = pmpdu->slen + varlen;
|
||||
if ( ppdu == NULL /* allocate PDU buffer */
|
||||
|| (spdu = calloc( 1, pdulen )) == NULL )
|
||||
break;
|
||||
spdu->cmd.cmd = cmd; /* MMCard command code */
|
||||
*ppdu = spdu;
|
||||
return pdulen; /* length of PDU buffer */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int /* init fixe length PDU */
|
||||
_initfpdu( uchar cmd, union mmcpdu ** ppdu )
|
||||
{
|
||||
return _initvpdu( cmd, 0, ppdu );
|
||||
}
|
||||
|
||||
/* send MMCard command PDU, receive response PDU
|
||||
* ---------------------------------------------
|
||||
* optionally encode FILE_IDEN into command PDU
|
||||
* send command PDU and release it
|
||||
* receive response PDU, MMCrecv() will allocate it
|
||||
* optionally decode FILE_IDEN and status from response PDU
|
||||
*/
|
||||
static long
|
||||
_sendrecv( union mmcpdu ** ppdu, size_t * ppdulen, uchar * fdstat )
|
||||
{
|
||||
struct mpdudesc * pmpdu;
|
||||
int rval;
|
||||
|
||||
for ( pmpdu = mmcpdutab; pmpdu->cmd != (*ppdu)->cmd.cmd; ++pmpdu )
|
||||
if ( pmpdu->slen == 0 )
|
||||
return ERR; /* PDU description not in table */
|
||||
|
||||
if ( pmpdu->sidenoffs != NOFFS && fdstat ) /* encode FILE_IDEN */
|
||||
putbtxt( (*ppdu)->cmd.data + pmpdu->sidenoffs, fdstat, FIDENSZ );
|
||||
rval = MMCsend( (*ppdu)->cmd.data, *ppdulen ); /* send command PDU */
|
||||
free( *ppdu ); *ppdu = NULL; *ppdulen = 0; /* and release it */
|
||||
if ( rval < 0 ) /* ERR, send failed */
|
||||
return rval;
|
||||
|
||||
if ( (rval = MMCrecv( (uchar**)ppdu )) < 0 ) /* recv response PDU */
|
||||
return rval; /* ERR, recv failed */
|
||||
*ppdulen = rval; /* recv'd PDU length */
|
||||
if ( pmpdu->ridenoffs != NOFFS && fdstat ) /* decode FILE_IDEN */
|
||||
getbtxt( (*ppdu)->rsp.data + pmpdu->ridenoffs, fdstat, FIDENSZ );
|
||||
if ( pmpdu->rstatoffs != NOFFS ) /* return status .. */
|
||||
return getword( (uchar*)*ppdu + pmpdu->rstatoffs );/* from resp PDU */
|
||||
else
|
||||
return 0x0000; /* or no status */
|
||||
}
|
||||
|
||||
/* convert FILE_INFO
|
||||
* -----------------
|
||||
* converts integer fields from IC35's to host's byte order
|
||||
*/
|
||||
static void
|
||||
_cvtfinfo( FILE_INFO * pdudirent, FILE_INFO * hostdirent )
|
||||
{
|
||||
if ( pdudirent == NULL || hostdirent == NULL )
|
||||
return;
|
||||
getbtxt( (uchar*)pdudirent, (uchar*)hostdirent, sizeof(*hostdirent) );
|
||||
hostdirent->ModifyTime = getword( (uchar*)&pdudirent->ModifyTime);
|
||||
hostdirent->ModifyDate = getword( (uchar*)&pdudirent->ModifyDate);
|
||||
hostdirent->FileSize = getdword( (uchar*)&pdudirent->FileSize );
|
||||
}
|
||||
|
||||
|
||||
/* MMCard general commands */
|
||||
/* ======================= */
|
||||
|
||||
/* get MMCard status
|
||||
* -----------------
|
||||
* IC35 SDK API 13.1 mInitialCard()
|
||||
* command: 20 "MMCard" [mmc_num] 00
|
||||
* response: 01 00 MMCard present
|
||||
* FF FF MMCard not detected
|
||||
*/
|
||||
long
|
||||
MMCgetstatus( int mmcnum )
|
||||
{
|
||||
union mmcpdu * pdu;
|
||||
int pdulen;
|
||||
long mstat;
|
||||
|
||||
if ( (pdulen = _initfpdu( MMCMDgetstatus, &pdu )) <= 0 )
|
||||
return ERR;
|
||||
|
||||
puttext( pdu->cmd.status.mmcard, "MMCard" );
|
||||
putbyte( pdu->cmd.status.mmcnum, (char)('0'+mmcnum) );
|
||||
|
||||
if ( (mstat = _sendrecv( &pdu, &pdulen, NULL )) < 0 )
|
||||
return mstat;
|
||||
|
||||
free( pdu );
|
||||
return mstat;
|
||||
}
|
||||
|
||||
/* get MMCard label
|
||||
* ----------------
|
||||
* IC35 ADK API 13.4 mGetCardLabel()
|
||||
* command: 34 "MMCard" [mmc_num] 00
|
||||
* response: 01 00 00 label[8] 00 20 20 00 00 00 00 00 00 00 00 48
|
||||
*/
|
||||
long
|
||||
MMCgetlabel( int mmcnum, char * plabel )
|
||||
{
|
||||
union mmcpdu * pdu;
|
||||
int pdulen;
|
||||
long mstat;
|
||||
|
||||
if ( (pdulen = _initfpdu( MMCMDgetlabel, &pdu )) <= 0 )
|
||||
return ERR;
|
||||
|
||||
/* encode cmdargs */
|
||||
puttext( pdu->cmd.status.mmcard, "MMCard" );
|
||||
putbyte( pdu->cmd.status.mmcnum, (char)('0'+mmcnum) );
|
||||
|
||||
if ( (mstat = _sendrecv( &pdu, &pdulen, NULL )) < 0 )
|
||||
return mstat;
|
||||
|
||||
/* decode rspargs */
|
||||
gettext( pdu->rsp.label.label, plabel, strlen(pdu->rsp.label.label) );
|
||||
|
||||
free( pdu );
|
||||
return mstat;
|
||||
}
|
||||
|
||||
|
||||
/* MMCard directory commands */
|
||||
/* ========================= */
|
||||
|
||||
/* open MMC directory
|
||||
* ------------------
|
||||
* IC35 SDK API 13.14 mOpenDirectory()
|
||||
* command: 2A 01 00 [MMCard1\path\to\dir] 00
|
||||
* response: 01 00 fdiden[27]
|
||||
*/
|
||||
long
|
||||
MMCdiropen( char * dirpath, uchar * fdstat )
|
||||
{
|
||||
union mmcpdu * pdu;
|
||||
int pdulen;
|
||||
long mstat;
|
||||
|
||||
if ( (pdulen = _initvpdu( MMCMDdiropen, strlen(dirpath), &pdu )) <= 0 )
|
||||
return ERR;
|
||||
|
||||
/* encode cmdargs */
|
||||
putword( pdu->cmd.diropen.mode, 0x0001 );
|
||||
puttxt0( pdu->cmd.diropen.path, dirpath );
|
||||
|
||||
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
|
||||
return mstat;
|
||||
|
||||
free( pdu );
|
||||
return mstat;
|
||||
}
|
||||
long
|
||||
MMCdircreate( char * dirpath, uchar * fdstat )
|
||||
{
|
||||
union mmcpdu * pdu;
|
||||
int pdulen;
|
||||
long mstat;
|
||||
|
||||
if ( (pdulen = _initvpdu( MMCMDdiropen, strlen(dirpath), &pdu )) <= 0 )
|
||||
return ERR;
|
||||
|
||||
/* encode cmdargs */
|
||||
putword( pdu->cmd.diropen.mode, 0x0000 );
|
||||
puttxt0( pdu->cmd.diropen.path, dirpath );
|
||||
|
||||
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
|
||||
return mstat;
|
||||
|
||||
free( pdu );
|
||||
return mstat;
|
||||
}
|
||||
|
||||
/* get num.of entries in MMCard directory
|
||||
* --------------------------------------
|
||||
* IC35 ADK API 13.15 mGetDirectorySubItemNum()
|
||||
* command: 2B fdiden[27] 00
|
||||
* response: fdiden[27] 01 00 nn_nn
|
||||
*/
|
||||
long
|
||||
MMCdirgetlen( uchar * fdstat, ushort * pndent )
|
||||
{
|
||||
union mmcpdu * pdu;
|
||||
int pdulen;
|
||||
long mstat;
|
||||
|
||||
if ( (pdulen = _initfpdu( MMCMDdirgetlen, &pdu )) <= 0 )
|
||||
return ERR;
|
||||
|
||||
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
|
||||
return mstat;
|
||||
|
||||
/* decode rspargs */
|
||||
*pndent = getword( pdu->rsp.dirglen.ndent );
|
||||
|
||||
free( pdu );
|
||||
return mstat;
|
||||
}
|
||||
|
||||
/* read MMC directory
|
||||
* ------------------
|
||||
* IC35 SDK API 13.16 mGetDirectorySubItem()
|
||||
* command: 2C fdiden[27] in_dx 00
|
||||
* response: fdiden[27] 01 00
|
||||
* filename 00 ext 00 at ti_me_st_mp 00 00 fi_le_si_ze
|
||||
*/
|
||||
long
|
||||
MMCdirread( uchar * fdstat, ushort index, FILE_INFO * pdirent )
|
||||
{
|
||||
union mmcpdu * pdu;
|
||||
int pdulen;
|
||||
long mstat;
|
||||
|
||||
if ( (pdulen = _initfpdu( MMCMDdirread, &pdu )) <= 0 )
|
||||
return ERR;
|
||||
|
||||
/* encode cmdargs */
|
||||
putword( pdu->cmd.dirread.u.index, index );
|
||||
|
||||
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
|
||||
return mstat;
|
||||
|
||||
/* decode rspargs */
|
||||
_cvtfinfo( &pdu->rsp.dirread.dirent, pdirent );
|
||||
|
||||
free( pdu );
|
||||
return mstat;
|
||||
}
|
||||
|
||||
/* close MMC directory
|
||||
* -------------------
|
||||
* IC35 SDK API 13.18 mCloseDirectory()
|
||||
* command: 2E fdiden[27] 00
|
||||
* response: fdiden[27]
|
||||
*/
|
||||
long
|
||||
MMCdirclose( uchar * fdstat )
|
||||
{
|
||||
union mmcpdu * pdu;
|
||||
int pdulen;
|
||||
long mstat;
|
||||
|
||||
if ( (pdulen = _initfpdu( MMCMDdirclose, &pdu )) <= 0 )
|
||||
return ERR;
|
||||
|
||||
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
|
||||
return mstat;
|
||||
|
||||
free( pdu );
|
||||
return mstat;
|
||||
}
|
||||
|
||||
|
||||
/* MMCard file commands */
|
||||
/* ==================== */
|
||||
|
||||
/* delete MMC file
|
||||
* ---------------
|
||||
* IC35 SDK API 13.13 mDeleteFile()
|
||||
* command: 28 [MMCard1\path\to\file] 00
|
||||
* response: 01 00
|
||||
*/
|
||||
long
|
||||
MMCfiledel( char * filepath )
|
||||
{
|
||||
union mmcpdu * pdu;
|
||||
int pdulen;
|
||||
long mstat;
|
||||
|
||||
if ( (pdulen = _initvpdu( MMCMDfiledel, strlen(filepath), &pdu )) <= 0 )
|
||||
return ERR;
|
||||
|
||||
/* encode cmdargs */
|
||||
puttxt0( pdu->cmd.filedel.path, filepath );
|
||||
|
||||
if ( (mstat = _sendrecv( &pdu, &pdulen, NULL )) < 0 )
|
||||
return mstat;
|
||||
|
||||
free( pdu );
|
||||
return mstat;
|
||||
}
|
||||
|
||||
/* open MMC file
|
||||
* -------------
|
||||
* IC35 SDK API 13.6 mOpenFile()
|
||||
* command: 22 01 00 [MMCard1\path\to\file] 00
|
||||
* response: 01 00 fdiden[27]
|
||||
*/
|
||||
long
|
||||
MMCfileopen( char * filepath, ushort mode, uchar * fdstat, ulong * psize )
|
||||
{
|
||||
union mmcpdu * pdu;
|
||||
int pdulen;
|
||||
long mstat;
|
||||
|
||||
if ( (pdulen = _initvpdu( MMCMDfileopen, strlen(filepath), &pdu )) <= 0 )
|
||||
return ERR;
|
||||
|
||||
/* encode cmdargs */
|
||||
putword( pdu->cmd.fileopen.mode, mode );
|
||||
puttxt0( pdu->cmd.fileopen.path, filepath );
|
||||
|
||||
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
|
||||
return mstat;
|
||||
|
||||
/* decode rspargs */
|
||||
*psize = getdword( pdu->rsp.fileopen.iden+14 );
|
||||
|
||||
free( pdu );
|
||||
return mstat;
|
||||
}
|
||||
|
||||
/* get MMC file status
|
||||
* -------------------
|
||||
* IC35 SDK API 13.10 mGetFileInfo()
|
||||
* command: 26 fdiden[27] 00
|
||||
* response: fdiden[27] 01 00
|
||||
* filename 00 ext 00 at ti_me_st_mp 00 00 fi_le_si_ze
|
||||
*/
|
||||
long
|
||||
MMCfilestat( uchar * fdstat, FILE_INFO * pdirent )
|
||||
{
|
||||
union mmcpdu * pdu;
|
||||
int pdulen;
|
||||
long mstat;
|
||||
|
||||
if ( (pdulen = _initfpdu( MMCMDfilestat, &pdu )) <= 0 )
|
||||
return ERR;
|
||||
|
||||
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
|
||||
return mstat;
|
||||
|
||||
/* decode rspargs */
|
||||
_cvtfinfo( &pdu->rsp.filestat.dirent, pdirent );
|
||||
|
||||
free( pdu );
|
||||
return mstat;
|
||||
}
|
||||
|
||||
/* read data from MMC file
|
||||
* -----------------------
|
||||
* IC35 SDK API 13.9 mReadFormFile()
|
||||
* command: 24 fdiden[27] nn_nn 00
|
||||
* response: fdiden[27] 01 00 rr_rr
|
||||
* <rr_rr bytes filedata>
|
||||
*/
|
||||
long
|
||||
MMCfileread( uchar * fdstat, uchar * buff, ushort blen, ushort * prlen )
|
||||
{
|
||||
union mmcpdu * pdu;
|
||||
int pdulen;
|
||||
long mstat;
|
||||
size_t dlen;
|
||||
|
||||
if ( (pdulen = _initfpdu( MMCMDfileread, &pdu )) <= 0 )
|
||||
return ERR;
|
||||
|
||||
/* encode cmdargs */
|
||||
putword( pdu->cmd.fileread.u.blen, blen );
|
||||
|
||||
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
|
||||
return mstat;
|
||||
|
||||
/* decode rspargs */
|
||||
*prlen = getword( pdu->rsp.fileread.rlen );
|
||||
dlen = pdulen - offsetof(struct mrspfileread, data);
|
||||
getbtxt( pdu->rsp.fileread.data, buff, dlen );
|
||||
if ( dlen != *prlen )
|
||||
LPRINTF(( L_WARN, "MMCfileread: rlen=%u, dlen=%u", *prlen, dlen ));
|
||||
|
||||
free( pdu );
|
||||
return mstat;
|
||||
}
|
||||
|
||||
/* write data to MMC file
|
||||
* ----------------------
|
||||
* IC35 SDK API 13.8 mWriteToFile()
|
||||
* command: 23 fdiden[27] ww_ww
|
||||
* <ww_ww bytes filedata> 00
|
||||
* response: fdiden[27] 01 00
|
||||
*/
|
||||
long
|
||||
MMCfilewrite( uchar * fdstat, uchar * data, ushort dlen )
|
||||
{
|
||||
union mmcpdu * pdu;
|
||||
int pdulen;
|
||||
long mstat;
|
||||
|
||||
if ( (pdulen = _initvpdu( MMCMDfilewrite, dlen, &pdu )) <= 0 )
|
||||
return ERR;
|
||||
|
||||
/* encode cmdargs */
|
||||
putword( pdu->cmd.filewrite.wlen, dlen );
|
||||
putbtxt( pdu->cmd.filewrite.data, data, dlen );
|
||||
putbyte( pdu->cmd.filewrite.data+dlen, 0x00 );
|
||||
|
||||
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
|
||||
return mstat;
|
||||
|
||||
free( pdu );
|
||||
return mstat;
|
||||
}
|
||||
|
||||
/* close MMC file
|
||||
* --------------
|
||||
* IC35 SDK API 13.11 mCloseFile()
|
||||
* command: 27 fdiden[27] 00
|
||||
* response: fdiden[27]
|
||||
*/
|
||||
long
|
||||
MMCfileclose( uchar * fdstat )
|
||||
{
|
||||
union mmcpdu * pdu;
|
||||
int pdulen;
|
||||
long mstat;
|
||||
|
||||
if ( (pdulen = _initfpdu( MMCMDfileclose, &pdu )) <= 0 )
|
||||
return ERR;
|
||||
|
||||
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
|
||||
return mstat;
|
||||
|
||||
free( pdu );
|
||||
return mstat;
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2001 Thomas Schulz *
|
||||
* *
|
||||
* $Id: mgrproto.h,v 1.8 2001/11/20 23:08:35 thosch Exp $ *
|
||||
* *
|
||||
* header for IC35 manager protocol *
|
||||
* *
|
||||
************************************************************************/
|
||||
#ifndef _MGRPROTO_H
|
||||
#define _MGRPROTO_H 1
|
||||
|
||||
#include "util.h" /* uchar */
|
||||
|
||||
|
||||
/* manager command bytes */
|
||||
#define MCMDdisconn (uchar)0x01 /* disconnect */
|
||||
#define MCMDreset (uchar)0x09 /* reset communication */
|
||||
#define MCMDident (uchar)0x10 /* identify: get "DCS_SDK" 00 */
|
||||
#define MCMDbackup (uchar)0x13 /* backup database */
|
||||
#define MCMDrestinit (uchar)0x14 /* restore database command-1 */
|
||||
#define MCMDmmcard (uchar)0x15 /* start MMCard transaction */
|
||||
#define MCMDinfo (uchar)0x18 /* get backup info "0128" */
|
||||
#define MCMDinit (uchar)0x50 /* status command-2, no response*/
|
||||
#define MCMDposack (uchar)0x60 /* positive acknowledge */
|
||||
#define MCMDnegack (uchar)0x62 /* negative acknowledge */
|
||||
#define MCMDrestdata (uchar)0x70 /* restore database command-2 */
|
||||
#define MCMDstatus (uchar)0xFF /* get 16400 byte status block */
|
||||
/* manager response bytes */
|
||||
#define MRSPgotcmd (uchar)0x90 /* IC35 got command */
|
||||
#define MRSPgotack (uchar)0xA0 /* IC35 got ack/nak */
|
||||
#define MRSPrestdata (uchar)0xC0 /* restore database response-2 */
|
||||
#define MRSPgotlen (uchar)0xE0 /* IC35/PC got length */
|
||||
|
||||
/* MMCard file attributes (from IC35 SDK Mmc.h) */
|
||||
#define MMCattrReadOnly 0x01
|
||||
#define MMCattrHidden 0x02
|
||||
#define MMCattrSystemFile 0x04
|
||||
#define MMCattrVolumeLabel 0x08
|
||||
#define MMCattrDirectory 0x10
|
||||
#define MMCattrArchive 0x20
|
||||
/* MMCard file open modes (see IC35 SDK MMc.h) */
|
||||
#define MMCopenexist 0x0001 /* open existing file for read,write */
|
||||
#define MMCcreatrunc 0x0000 /* create new truncate existing file */
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct _file_info { /* directory entry (see IC35 SDK Mmc.h) */
|
||||
char FileName[8+1];
|
||||
char ExtName[3+1];
|
||||
uchar Attribute;
|
||||
ushort ModifyTime;
|
||||
ushort ModifyDate;
|
||||
ushort Reserved;
|
||||
ulong FileSize;
|
||||
} FILE_INFO;
|
||||
typedef struct _file_iden { /* file identifier (see IC35 SDK Mmc.h) */
|
||||
ushort Sector;
|
||||
ushort Cluster;
|
||||
ushort SectorOffset;
|
||||
ushort DirItemOffset;
|
||||
ushort StartCluster;
|
||||
ulong FilePointer;
|
||||
ulong FileSize;
|
||||
uchar CacheNo;
|
||||
ushort CurCluster;
|
||||
ushort CurClusterNo;
|
||||
ushort CurSectorNo;
|
||||
ushort Reserved;
|
||||
} FILE_IDEN;
|
||||
#pragma pack()
|
||||
#define FIDENSZ sizeof(FILE_IDEN)
|
||||
|
||||
|
||||
int Mcmdrsp( uchar cmd, uchar rsp ); /* send cmd, get+check rsp */
|
||||
|
||||
int Msendblk( uchar * data, size_t dlen ); /* send block, ack/retry */
|
||||
int Mrecvblk( uchar * buff, size_t blen ); /* receive block, ack/retry */
|
||||
|
||||
long MMCgetstatus( int mmcnum );
|
||||
long MMCgetlabel( int mmcnum, char * plabel );
|
||||
|
||||
long MMCdiropen( char * dirpath, uchar * fdstat );
|
||||
long MMCdircreate( char * dirpath, uchar * fdstat );
|
||||
long MMCdirgetlen( uchar * fdstat, ushort * pndent );
|
||||
long MMCdirread( uchar * fdstat, ushort index, FILE_INFO * pdirent );
|
||||
long MMCdirclose( uchar * fdstat );
|
||||
|
||||
long MMCfiledel( char * filepath );
|
||||
long MMCfileopen( char * filepath, ushort mode, uchar * fdstat, ulong * psize );
|
||||
long MMCfilestat( uchar * fdstat, FILE_INFO * pdirent );
|
||||
long MMCfileread( uchar * fdstat, uchar * buff, ushort blen, ushort * prlen );
|
||||
long MMCfilewrite( uchar * fdstat, uchar * data, ushort dlen );
|
||||
long MMCfileclose( uchar * fdstat );
|
||||
|
||||
#endif /*_MGRPROTO_H*/
|
|
@ -0,0 +1,943 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2001 Thomas Schulz *
|
||||
* */
|
||||
static char rcsid[] =
|
||||
"$Id: mgrtrans.c,v 1.17 2001/11/20 23:08:35 thosch Exp $"; /*
|
||||
* *
|
||||
* IC35 manager transactions *
|
||||
* *
|
||||
*************************************************************************
|
||||
* *
|
||||
* ??? is "fixme" mark: sections of code needing fixes *
|
||||
*
|
||||
* communication phases
|
||||
* mconnect
|
||||
* mdisconnect
|
||||
* MMCard info
|
||||
* mmc_status
|
||||
* mmc_label
|
||||
* MMCard directory ops
|
||||
* mmc_opendir
|
||||
* mmc_createdir
|
||||
* mmc_readdir
|
||||
* mmc_closedir
|
||||
* mmctstampstr
|
||||
* mmctstampunixtime
|
||||
* MMCard file operations
|
||||
* mmc_delfile
|
||||
* mmc_openfile
|
||||
* mmc_statfile
|
||||
* mmc_readfile
|
||||
* mmc_writefile
|
||||
* mmc_closefile
|
||||
* IC35 database backup,restore
|
||||
* readdatabase
|
||||
* writedatabase
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include <stdio.h> /* fprintf(), .. */
|
||||
#include <string.h> /* memcpy(), strlen() ..*/
|
||||
#include <stdlib.h> /* malloc(), .. */
|
||||
#include <unistd.h> /* usleep() */
|
||||
#include <sys/types.h> /* size_t, .. */
|
||||
#include <time.h> /* time_t, localtime()..*/
|
||||
#include <errno.h>
|
||||
|
||||
#include "util.h" /* ERR,OK, uchar, .. */
|
||||
#include "comio.h" /* com_init(), .. */
|
||||
#include "genproto.h" /* welcome() */
|
||||
#include "mgrproto.h" /* manager protocol */
|
||||
#include "mgrtrans.h"
|
||||
NOTUSED(rcsid);
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* communication phases */
|
||||
/* ==================================== */
|
||||
|
||||
/* welcome phase
|
||||
* -------------
|
||||
* opens comm.device and does welcome handshake
|
||||
*/
|
||||
static int
|
||||
mgrwelcome( char * devname )
|
||||
{
|
||||
int rval;
|
||||
|
||||
LPRINTF(( L_INFO, "welcome(%s) ..", devname ));
|
||||
if ( com_init( devname ) != OK ) {
|
||||
error( "welcome failed: com_init(%s) failed", devname );
|
||||
return ERR;
|
||||
}
|
||||
message( "welcome, start IC35 !" );
|
||||
if ( (rval = welcome( 0x40 )) != OK ) {
|
||||
error( "welcome %s", rval == ERR_intr ? "aborted"
|
||||
: "failed: no response" );
|
||||
return ERR;
|
||||
}
|
||||
message( "connected" );
|
||||
LPRINTF(( L_INFO, "welcome(%s) OK", devname ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* identify
|
||||
* --------
|
||||
* communication PC <-> IC35:
|
||||
* reset-phase -> 09
|
||||
* <- 90
|
||||
* ident-phase -> 10
|
||||
* <- 90 "DCS_SDK" 00
|
||||
*/
|
||||
static int
|
||||
identify( char rtext[7+1] )
|
||||
{
|
||||
int rlen;
|
||||
char rbuff[7+1]; /* for "DCS_SDK\x00" */
|
||||
|
||||
LPRINTF(( L_INFO, "identify .." ));
|
||||
|
||||
if ( Mcmdrsp( MCMDreset, MRSPgotcmd ) != OK ) {
|
||||
error( "identify failed: reset-phase" );
|
||||
return ERR;
|
||||
}
|
||||
if ( Mcmdrsp( MCMDident, MRSPgotcmd ) != OK
|
||||
|| (rlen = com_recv( rbuff, sizeof(rbuff) )) <= 0 ) {
|
||||
error( "identify failed: ident-phase" );
|
||||
return ERR;
|
||||
}
|
||||
if ( rtext != NULL )
|
||||
strncat( strcpy( rtext, "" ), rbuff, rlen );
|
||||
|
||||
LPRINTF(( L_INFO, "identify OK" ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* init IC35, optionally get status data
|
||||
* -------------------------------------
|
||||
* communication PC <-> IC35:
|
||||
* optional:
|
||||
* -> FF
|
||||
* <- [block of 16400 bytes]
|
||||
* mandatory:
|
||||
* -> 50
|
||||
* <- 90 or timeout 0.1 sec
|
||||
* IC35 may send response, but anyway needs time to get ready
|
||||
*/
|
||||
#define STATSIZE 16400
|
||||
|
||||
static int
|
||||
status( char * fname )
|
||||
{
|
||||
uchar cmd;
|
||||
char * rbuff;
|
||||
int rlen = -1;
|
||||
FILE * fp;
|
||||
int old_tmo;
|
||||
uchar rsp;
|
||||
|
||||
LPRINTF(( L_INFO, "status(%s) ..", fname ? fname : "NULL" ));
|
||||
|
||||
if ( fname && *fname ) {
|
||||
if ( (rbuff = malloc( STATSIZE )) != NULL ) {
|
||||
cmd = MCMDstatus;
|
||||
com_send( &cmd, 1 );
|
||||
if ( (rlen = com_recv( rbuff, STATSIZE )) < 0 ) {
|
||||
error( "status failed: receive" );
|
||||
free( rbuff );
|
||||
return ERR;
|
||||
}
|
||||
if ( (fp = fopen( fname, "w")) != NULL ) {
|
||||
fwrite( rbuff, 1, rlen, fp );
|
||||
fclose( fp );
|
||||
} else {
|
||||
message( "cannot open statfile: %s", fname );
|
||||
}
|
||||
free( rbuff );
|
||||
} else {
|
||||
message( "cannot read statdata: no memory (%d)", STATSIZE );
|
||||
}
|
||||
}
|
||||
cmd = MCMDinit;
|
||||
com_send( &cmd, 1 ); /* -> 50 */
|
||||
old_tmo = com_settimeout( 100 );
|
||||
com_recv( &rsp, 1 ); /* <- 90 or wait 100 msec */
|
||||
com_settimeout( old_tmo );
|
||||
|
||||
if ( rlen >= 0 ) /* received status block */
|
||||
LPRINTF(( L_INFO, "status received %d bytes statdata", rlen ));
|
||||
else
|
||||
LPRINTF(( L_INFO, "status OK" ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* open com-device and connect with IC35
|
||||
* -------------------------------------
|
||||
*/
|
||||
int
|
||||
mconnect( char * devname, char * statfname )
|
||||
{
|
||||
int rval;
|
||||
char idtext[8];
|
||||
|
||||
LPRINTF(( L_INFO, "mconnect(%s,%s) ..",
|
||||
devname, statfname ? statfname : "NULL" ));
|
||||
if ( (rval = mgrwelcome( devname )) == OK
|
||||
&& (rval = identify( idtext )) == OK ) {
|
||||
message( "identity \"%s\"", idtext );
|
||||
if ( statfname && *statfname )
|
||||
message( "statdata %s", statfname );
|
||||
rval = status( statfname );
|
||||
}
|
||||
if ( rval != OK )
|
||||
mdisconnect();
|
||||
LPRINTF(( L_INFO, "mconnect(%s,%s) %s",
|
||||
devname, statfname ? statfname : "NULL",
|
||||
rval == OK ? "OK" : "ERR" ));
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* disconnect from IC35 and close com-device
|
||||
* -----------------------------------------
|
||||
* communication PC <-> IC35:
|
||||
* -> 09
|
||||
* timeout
|
||||
* -> 09
|
||||
* <- 90
|
||||
* -> 01
|
||||
* timeout
|
||||
* -> 01
|
||||
* <- 90
|
||||
* until response '\x90' is received, send '\x09' or '\x01'
|
||||
* respectively will be retried up to 5 times.
|
||||
*/
|
||||
int
|
||||
mdisconnect( void )
|
||||
{
|
||||
uchar cmd, rsp;
|
||||
int rval;
|
||||
|
||||
message( "disconnect" );
|
||||
if ( (rval = Mcmdrsp( cmd = MCMDreset, rsp = MRSPgotcmd )) != OK
|
||||
|| (rval = Mcmdrsp( cmd = MCMDdisconn, rsp = MRSPgotcmd )) != OK )
|
||||
message( "disconnect sent '\\x%02X', failed receive '\\x%02X'",
|
||||
cmd, rsp );
|
||||
com_exit();
|
||||
LPRINTF(( L_INFO, "disconnect done." ));
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* IC35 MMCard info */
|
||||
/* ==================================== */
|
||||
|
||||
/* local: convert mstat to text
|
||||
* ----------------------------
|
||||
*/
|
||||
static char *
|
||||
_mstatxt( long mstat )
|
||||
{
|
||||
static char mstatxt[2+11+1]; /* "(-nnnnnnnnnn)"\0 */
|
||||
|
||||
if ( mstat >= 0 )
|
||||
sprintf( mstatxt, "(%04hX)", (ushort)mstat );
|
||||
else
|
||||
sprintf( mstatxt, "(%ld)", mstat );
|
||||
return mstatxt;
|
||||
}
|
||||
|
||||
/* get MMCard status
|
||||
* -----------------
|
||||
* returns:
|
||||
* 1 OK, MMCard found
|
||||
* 0 OK, MMCard not detected
|
||||
* -1 ERR, communication failed
|
||||
*/
|
||||
int
|
||||
mmc_status( int mmcnum )
|
||||
{
|
||||
long mstat;
|
||||
|
||||
if ( mmcnum != 1 && mmcnum != 2 ) {
|
||||
error( "mmc_status: bad MMCard number %d", mmcnum );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "mmc_status(%d) ..", mmcnum ));
|
||||
if ( (mstat = MMCgetstatus( mmcnum )) < 0
|
||||
|| !( mstat == 0xFFFF || mstat == 0x0001 ) ) {
|
||||
error( "mmc_status failed %s", _mstatxt(mstat) );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "mmc_status(%d) = %04X", mmcnum, mstat ));
|
||||
return mstat == 0xFFFF ? 0 : mstat;
|
||||
}
|
||||
|
||||
/* get MMCard label
|
||||
* ----------------
|
||||
*/
|
||||
int
|
||||
mmc_label( int mmcnum, char label[11+1] )
|
||||
{
|
||||
long mstat;
|
||||
|
||||
if ( mmcnum != 1 && mmcnum != 2 ) {
|
||||
error( "mmc_label: bad MMCard number %d", mmcnum );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "mmc_label(%d) ..", mmcnum ));
|
||||
if ( (mstat = MMCgetlabel( mmcnum, label )) != 0x0001 ) {
|
||||
error( "mmc_label failed %s", _mstatxt(mstat) );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "mmc_label(%d) = \"%s\"", mmcnum, label ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* IC35 MMCard directory ops */
|
||||
/* ==================================== */
|
||||
|
||||
struct mmcdir { /* MMC directory descriptor */
|
||||
uchar fdiden[FIDENSZ];/* MMC dir/file access ident */
|
||||
MMCDIRENT dirent; /* decoded directory entry */
|
||||
ushort ndirent; /* number of directory entries */
|
||||
ushort dirindex; /* current directory index */
|
||||
};
|
||||
|
||||
/* local: convert FILE_INFO to MMCDIRENT
|
||||
* -------------------------------------
|
||||
*/
|
||||
static void
|
||||
_mmc_finfo2dirent( FILE_INFO * finfo, MMCDIRENT * dirent )
|
||||
{
|
||||
if ( finfo == NULL || dirent == NULL )
|
||||
return;
|
||||
strncat( strcpy( dirent->name, "" ), finfo->FileName, 8 );
|
||||
if ( strlen( finfo->ExtName ) != 0 ) {
|
||||
strcat( dirent->name, "." );
|
||||
strncat( dirent->name, finfo->ExtName, 3 );
|
||||
}
|
||||
dirent->attr = finfo->Attribute;
|
||||
dirent->tstamp = finfo->ModifyDate << 16 | finfo->ModifyTime;
|
||||
dirent->size = finfo->FileSize;
|
||||
}
|
||||
|
||||
/* open MMC directory
|
||||
* ------------------
|
||||
*/
|
||||
MMCDIR *
|
||||
mmc_opendir( char * dirpath )
|
||||
{
|
||||
MMCDIR * dirp;
|
||||
long mstat;
|
||||
|
||||
if ( (dirp = malloc( sizeof(*dirp) )) == NULL ) {
|
||||
error( "mmc_opendir failed: no memory (%d)", sizeof(*dirp) );
|
||||
return NULL;
|
||||
}
|
||||
LPRINTF(( L_INFO, "mmc_opendir(%s) ..", dirpath ));
|
||||
if ( (mstat = MMCdiropen( dirpath, dirp->fdiden )) != 0x0001 ) {
|
||||
error( "mmc_opendir(%s) diropen failed %s", dirpath, _mstatxt(mstat) );
|
||||
return NULL;
|
||||
}
|
||||
if ( (mstat = MMCdirgetlen( dirp->fdiden, &dirp->ndirent )) != 0x0001 ) {
|
||||
error( "mmc_opendir(%s) dirgetlen failed %s", dirpath,_mstatxt(mstat) );
|
||||
return NULL;
|
||||
}
|
||||
dirp->dirindex = 0;
|
||||
LPRINTF(( L_INFO, "mmc_opendir(%s) OK, ndirent=%d",
|
||||
dirpath, dirp->ndirent ));
|
||||
return dirp;
|
||||
}
|
||||
/* open MMC directory
|
||||
* ------------------
|
||||
*/
|
||||
MMCDIR *
|
||||
mmc_createdir( char * dirpath )
|
||||
{
|
||||
MMCDIR * dirp;
|
||||
long mstat;
|
||||
|
||||
if ( (dirp = malloc( sizeof(*dirp) )) == NULL ) {
|
||||
error( "mmc_createdir failed: no memory (%d)", sizeof(*dirp) );
|
||||
return NULL;
|
||||
}
|
||||
LPRINTF(( L_INFO, "mmc_createdir(%s) ..", dirpath ));
|
||||
if ( (mstat = MMCdircreate( dirpath, dirp->fdiden )) != 0x0001 ) {
|
||||
error( "mmc_createdir(%s) dircreate failed %s", dirpath, _mstatxt(mstat) );
|
||||
return NULL;
|
||||
}
|
||||
if ( (mstat = MMCdirgetlen( dirp->fdiden, &dirp->ndirent )) != 0x0001 ) {
|
||||
error( "mmc_createdir(%s) dirgetlen failed %s", dirpath,_mstatxt(mstat) );
|
||||
return NULL;
|
||||
}
|
||||
dirp->dirindex = 0;
|
||||
LPRINTF(( L_INFO, "mmc_createdir(%s) OK, ndirent=%d",
|
||||
dirpath, dirp->ndirent ));
|
||||
return dirp;
|
||||
}
|
||||
|
||||
/* read MMC directory
|
||||
* ------------------
|
||||
*/
|
||||
MMCDIRENT *
|
||||
mmc_readdir( MMCDIR * dirp )
|
||||
{
|
||||
long mstat;
|
||||
FILE_INFO mmcdirent;
|
||||
|
||||
if ( dirp == NULL )
|
||||
return NULL;
|
||||
if ( dirp->dirindex >= dirp->ndirent ) {
|
||||
LPRINTF(( L_INFO, "mmc_readdir: eodir (%d)", dirp->dirindex ));
|
||||
return NULL;
|
||||
}
|
||||
++dirp->dirindex;
|
||||
LPRINTF(( L_INFO, "mmc_readdir index=%d ..", dirp->dirindex ));
|
||||
if ( (mstat = MMCdirread( dirp->fdiden, dirp->dirindex, &mmcdirent ))
|
||||
!= 0x0001 ) {
|
||||
error( "mmc_readdir failed %s", _mstatxt(mstat) );
|
||||
return NULL;
|
||||
}
|
||||
_mmc_finfo2dirent( &mmcdirent, &dirp->dirent );
|
||||
LPRINTF(( L_INFO, "mmc_readdir OK" ));
|
||||
return &dirp->dirent;
|
||||
}
|
||||
|
||||
/* close MMC directory
|
||||
* -------------------
|
||||
*/
|
||||
int
|
||||
mmc_closedir( MMCDIR * dirp )
|
||||
{
|
||||
if ( dirp == NULL )
|
||||
return OK;
|
||||
LPRINTF(( L_INFO, "mmc_closedir .." ));
|
||||
if ( MMCdirclose( dirp->fdiden ) < 0 ) {
|
||||
error( "mmc_closedir failed" );
|
||||
return ERR;
|
||||
}
|
||||
free( dirp );
|
||||
LPRINTF(( L_INFO, "mmc_closedir OK" ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* convert MMC timestamp
|
||||
* ---------------------
|
||||
* the timestamp of MMCard dir/file is encoded like DOS:
|
||||
* 3322222 2222 21111 11111 100000 00000 bit- ..
|
||||
* 1098765 4321 09876 54321 098765 43210 .. number
|
||||
* yyyyyyy mmmm ddddd hhhhh mmmmmm sssss bit fields
|
||||
* the bit field meanings are:
|
||||
* yyyyyyy years since 1980
|
||||
* mmmm month 1..12
|
||||
* ddddd day 1..31
|
||||
* hhhhh hour 00..24
|
||||
* mmmmmm minute 00..59
|
||||
* sssss second/2 00..31
|
||||
* mmctstampstr() returns:
|
||||
* (char*) timestamp string: yyyy-mm-dd hh:mm:ss
|
||||
* mmctstampunixtime() returns:
|
||||
* (time_t) timestamp converted to Unix time
|
||||
*/
|
||||
static struct tm *
|
||||
_mmctstamptm( ulong tstamp )
|
||||
{
|
||||
static struct tm mmctm;
|
||||
|
||||
mmctm.tm_year = ((tstamp & 0xFE000000) >> (4+5+5+6+5)) + 80;
|
||||
mmctm.tm_mon = ((tstamp & 0x01E00000) >> ( 5+5+6+5)) - 1;
|
||||
mmctm.tm_mday = (tstamp & 0x001F0000) >> ( 5+6+5);
|
||||
mmctm.tm_hour = (tstamp & 0x0000F800) >> ( 6+5);
|
||||
mmctm.tm_min = (tstamp & 0x000007E0) >> ( 5);
|
||||
mmctm.tm_sec = (tstamp & 0x0000001F) * 2;
|
||||
return &mmctm;
|
||||
}
|
||||
char *
|
||||
mmctstampstr( ulong tstamp )
|
||||
{
|
||||
static char ymdhms[19+1];
|
||||
struct tm * ptm;
|
||||
|
||||
ptm = _mmctstamptm( tstamp );
|
||||
sprintf( ymdhms, "%04u-%02u-%02u %02u:%02u:%02u",
|
||||
ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday,
|
||||
ptm->tm_hour, ptm->tm_min, ptm->tm_sec );
|
||||
return ymdhms;
|
||||
}
|
||||
time_t
|
||||
mmctstampunixtime( ulong tstamp )
|
||||
{
|
||||
struct tm * ptm;
|
||||
|
||||
ptm = _mmctstamptm( tstamp );
|
||||
ptm->tm_isdst = -1;
|
||||
return mktime( ptm );
|
||||
}
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* IC35 MMCard file operations */
|
||||
/* ==================================== */
|
||||
|
||||
struct mmcfile { /* MMC file descriptor */
|
||||
uchar fdiden[FIDENSZ];/* MMC dir/file access ident */
|
||||
MMCDIRENT filestat; /* decoded file status */
|
||||
ulong size; /* file size */
|
||||
ulong offset; /* current offset in file */
|
||||
};
|
||||
|
||||
/* delete MMC file
|
||||
* ---------------
|
||||
*/
|
||||
int
|
||||
mmc_delfile( char * filepath )
|
||||
{
|
||||
long mstat;
|
||||
|
||||
LPRINTF(( L_INFO, "mmc_delfile(%s) ..", filepath ));
|
||||
if ( (mstat = MMCfiledel( filepath )) != 0x0001 ) {
|
||||
error( "mmc_delfile(%s) failed %s", filepath, _mstatxt(mstat) );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "mmc_delfile(%s) OK", filepath ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* open MMC file
|
||||
* -------------
|
||||
*/
|
||||
MMCFILE *
|
||||
mmc_openfile( char * filepath, ushort mode )
|
||||
{
|
||||
MMCFILE * fp;
|
||||
long mstat;
|
||||
|
||||
if ( (fp = malloc( sizeof(*fp) )) == NULL ) {
|
||||
error( "mmc_openfile failed: no memory (%d)", sizeof(*fp) );
|
||||
return NULL;
|
||||
}
|
||||
LPRINTF(( L_INFO, "mmc_openfile(%s) ..", filepath ));
|
||||
if ( (mstat = MMCfileopen( filepath, mode, fp->fdiden, &fp->size ))
|
||||
!= 0x0001 ) {
|
||||
error( "mmc_openfile(%s) failed %s", filepath, _mstatxt(mstat) );
|
||||
return NULL;
|
||||
}
|
||||
fp->offset = 0;
|
||||
LPRINTF(( L_INFO, "mmc_openfile(%s) OK, size=%lu", filepath, fp->size ));
|
||||
return fp;
|
||||
}
|
||||
|
||||
/* get MMC file status
|
||||
* -------------------
|
||||
*/
|
||||
MMCDIRENT *
|
||||
mmc_statfile( MMCFILE * fp )
|
||||
{
|
||||
long mstat;
|
||||
FILE_INFO mmcdirent;
|
||||
|
||||
if ( fp == NULL )
|
||||
return NULL;
|
||||
LPRINTF(( L_INFO, "mmc_statfile .." ));
|
||||
if ( (mstat = MMCfilestat( fp->fdiden, &mmcdirent )) != 0x0001 ) {
|
||||
error( "mmc_statfile failed %s", _mstatxt(mstat) );
|
||||
return NULL;
|
||||
}
|
||||
_mmc_finfo2dirent( &mmcdirent, &fp->filestat );
|
||||
LPRINTF(( L_INFO, "mmc_statfile OK" ));
|
||||
return &fp->filestat;
|
||||
}
|
||||
|
||||
/* read data from MMC file
|
||||
* -----------------------
|
||||
*/
|
||||
int
|
||||
mmc_readfile( MMCFILE * fp, uchar * buff, size_t blen )
|
||||
{
|
||||
long mstat;
|
||||
ushort rlen;
|
||||
|
||||
if ( fp == NULL )
|
||||
return ERR;
|
||||
if ( fp->offset >= fp->size ) {
|
||||
LPRINTF(( L_INFO, "mmc_readfile: eofile (%d)", fp->offset ));
|
||||
return 0;
|
||||
}
|
||||
LPRINTF(( L_INFO, "mmc_readfile(buff,%d) ..", blen ));
|
||||
if ( fp->offset + blen > fp->size )
|
||||
blen = fp->size - fp->offset;
|
||||
if ( (mstat = MMCfileread( fp->fdiden, buff, blen, &rlen )) != 0x0001 ) {
|
||||
error( "mmc_readfile failed %s", _mstatxt(mstat) );
|
||||
return ERR;
|
||||
}
|
||||
fp->offset += rlen;
|
||||
LPRINTF(( L_INFO, "mmc_readfile(buff,%d) = %d", blen, rlen ));
|
||||
return rlen;
|
||||
}
|
||||
|
||||
/* write data to MMC file
|
||||
* ----------------------
|
||||
*/
|
||||
int
|
||||
mmc_writefile( MMCFILE * fp, uchar * data, size_t dlen )
|
||||
{
|
||||
long mstat;
|
||||
|
||||
if ( fp == NULL )
|
||||
return ERR;
|
||||
LPRINTF(( L_INFO, "mmc_writefile(data,%d) ..", dlen ));
|
||||
if ( (mstat = MMCfilewrite( fp->fdiden, data, dlen )) != 0x0001 ) {
|
||||
error( "mmc_writefile failed %s", _mstatxt(mstat) );
|
||||
return ERR;
|
||||
}
|
||||
if ( fp->offset == fp->size )
|
||||
fp->size += dlen;
|
||||
fp->offset += dlen;
|
||||
LPRINTF(( L_INFO, "mmc_writefile(data,%d) OK", dlen ));
|
||||
return dlen;
|
||||
}
|
||||
|
||||
/* close MMC file
|
||||
* --------------
|
||||
*/
|
||||
int
|
||||
mmc_closefile( MMCFILE * fp )
|
||||
{
|
||||
if ( fp == NULL )
|
||||
return OK;
|
||||
LPRINTF(( L_INFO, "mmc_closefile .." ));
|
||||
if ( MMCfileclose( fp->fdiden ) < 0 ) {
|
||||
error( "mmc_closefile failed" );
|
||||
return ERR;
|
||||
}
|
||||
free( fp );
|
||||
LPRINTF(( L_INFO, "mmc_closefile OK" ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* IC35 database backup,restore */
|
||||
/* ==================================== */
|
||||
|
||||
#define HEADBLKSZ 136
|
||||
#define DATABLKSZ 16384
|
||||
#define INFOBLKSZ 4
|
||||
#define NDATABLKS 26
|
||||
#define NINFOBLKS 2
|
||||
|
||||
/* get database info
|
||||
* -----------------
|
||||
*/
|
||||
static int
|
||||
_getdbinfo( uchar * buff, size_t blen )
|
||||
{
|
||||
if ( Mcmdrsp( MCMDinfo, MRSPgotcmd ) != OK )
|
||||
return ERR;
|
||||
return com_recv( buff, blen );
|
||||
}
|
||||
|
||||
/* textify protocol errorcode
|
||||
* --------------------------
|
||||
*/
|
||||
static char *
|
||||
_dbetext( int len )
|
||||
{
|
||||
static char etext[24+1];
|
||||
|
||||
switch ( len ) {
|
||||
case ERR_recv:
|
||||
return "recv.error/timeout";
|
||||
case ERR_acknak:
|
||||
return "ack/nak handshake failed";
|
||||
case ERR_chksum:
|
||||
return "checksum error";
|
||||
default:
|
||||
sprintf( etext, "%s (%d)", len < 0 ? "error" : "bad length", len );
|
||||
return etext;
|
||||
}
|
||||
}
|
||||
|
||||
/* IC35 database backup to file
|
||||
* ============================
|
||||
* communication PC <-> IC35:
|
||||
* backup command
|
||||
* -> 13 command backup
|
||||
* <- 90 response gotcmd
|
||||
* on receive error / timeout retry sending command
|
||||
* headblock
|
||||
* <- [136-byte-block] cc_cc headblock
|
||||
* -> 60 positive acknowledge
|
||||
* <- A0 response gotack
|
||||
* or on checksum mismatch:
|
||||
* -> 62 negative acknowlegde
|
||||
* <- A0 reponse gotnak
|
||||
* and receive headblock again
|
||||
* datablocks
|
||||
* <- [16384-byte-block] cc_cc datablock
|
||||
* -> 60 positive acknowledge
|
||||
* <- A0 response gotack
|
||||
* repeat receive for 26 datablocks of 16384 bytes. for each datablock
|
||||
* do retry on checksum mismatch like above for headblock.
|
||||
* database info
|
||||
* -> 18 command getinfo
|
||||
* <- 90 response gotcmd
|
||||
* <- 30 31 32 38 infoblock-1
|
||||
* -> 18 command getinfo
|
||||
* <- 90 response gotcmd
|
||||
* <- 30 31 32 38 infoblock-2
|
||||
*/
|
||||
|
||||
/* read IC35 database to file
|
||||
* --------------------------
|
||||
*/
|
||||
static int
|
||||
_readdatabase( char * fname, FILE * fp, uchar * buff )
|
||||
{
|
||||
ulong frlen;
|
||||
int rlen;
|
||||
int i;
|
||||
|
||||
LPRINTF(( L_INFO, "readdatabase %s ..", fname ));
|
||||
|
||||
/* send backup command and wait for IC35 response */
|
||||
if ( Mcmdrsp( MCMDbackup, MRSPgotcmd ) != OK ) {
|
||||
error( "readdatabase backup command failed" );
|
||||
return ERR;
|
||||
}
|
||||
/* receive head-,data-blocks from IC35 and write to file */
|
||||
frlen = 0;
|
||||
for ( i = 0; i <= NDATABLKS; ++i ) {
|
||||
char btext[24+1];
|
||||
size_t blen;
|
||||
if ( i == 0 ) {
|
||||
fprintf( stderr, "read database -> %s head ", fname );
|
||||
strcpy( btext, "headblock" );
|
||||
blen = HEADBLKSZ;
|
||||
} else {
|
||||
sprintf( btext, "datablock-%d", i );
|
||||
blen = DATABLKSZ;
|
||||
}
|
||||
if ( (rlen = Mrecvblk( buff, blen )) != blen ) {
|
||||
fprintf( stderr, "\n" );
|
||||
error( "readdatabase %s %s", btext, _dbetext( rlen ) );
|
||||
return ERR;
|
||||
}
|
||||
frlen += rlen;
|
||||
fprintf( stderr, "\rread database -> %s %ldk ",
|
||||
fname, (frlen+511)/1024 );
|
||||
if ( fwrite( buff, sizeof(buff[0]), rlen, fp ) != rlen ) {
|
||||
fprintf( stderr, "\n" );
|
||||
error( "readdatabase %s %s: write error %s (%d)",
|
||||
btext, fname, strerror(errno), errno );
|
||||
return ERR;
|
||||
}
|
||||
}
|
||||
/* receive database info from IC35 and write to file */
|
||||
fprintf( stderr, "\nread database -> %s info ", fname );
|
||||
for ( i = 1; i <= NINFOBLKS; ++i ) {
|
||||
if ( (rlen = _getdbinfo( buff, INFOBLKSZ )) != INFOBLKSZ ) {
|
||||
fprintf( stderr, "\n" );
|
||||
error( "readdatabase info-%d recv.error/timeout", i );
|
||||
return ERR;
|
||||
}
|
||||
if ( fwrite( buff, sizeof(buff[0]), rlen, fp ) != rlen ) {
|
||||
fprintf( stderr, "\n" );
|
||||
error( "readdatabase info-%d %s: write error %s (%d)",
|
||||
i, fname, strerror(errno), errno );
|
||||
return ERR;
|
||||
}
|
||||
}
|
||||
fprintf( stderr, "\n" );
|
||||
|
||||
LPRINTF(( L_INFO, "readdatabase %s OK", fname ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* read IC35 database: init,free resources
|
||||
* ---------------------------------------
|
||||
*/
|
||||
int
|
||||
readdatabase( char * fname )
|
||||
{
|
||||
uchar * buff;
|
||||
FILE * fp;
|
||||
int rval;
|
||||
|
||||
if ( (buff = malloc( DATABLKSZ )) != NULL ) {
|
||||
if ( fname && *fname
|
||||
&& (fp = fopen( fname, "w" )) != NULL ) {
|
||||
rval = _readdatabase( fname, fp, buff );
|
||||
fclose( fp );
|
||||
} else {
|
||||
error( "readdatabase cannot open %s", fname ? fname : "(NULL)" );
|
||||
rval = ERR;
|
||||
}
|
||||
free( buff );
|
||||
} else {
|
||||
error( "readdatabase failed: no memory (%d)", DATABLKSZ );
|
||||
rval = ERR;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/* IC35 database restore from file
|
||||
* ===============================
|
||||
* communication PC <-> IC35:
|
||||
* database info
|
||||
* -> 18 command getinfo
|
||||
* <- 90 response gotcmd
|
||||
* <- 30 31 32 38 infoblock-1
|
||||
* -> 18 command getinfo
|
||||
* <- 90 response gotcmd
|
||||
* <- 30 31 32 38 infoblock-2
|
||||
* check both infoblocks matching with tail of database file,
|
||||
* on mismatch abort and do not write database to IC35.
|
||||
* restore commands
|
||||
* -> 14 command restore-1
|
||||
* <- 90 response gotcmd
|
||||
* -> 70 command restore-2
|
||||
* <- C0 response restore-2
|
||||
* on receive error / timeout retry sending command-1/2.
|
||||
* headblock
|
||||
* -> [136-byte-block] headblock
|
||||
* <- cc_cc response checksum
|
||||
* -> 60 positive acknowledge
|
||||
* <- A0 response gotack
|
||||
* or on checksum mismatch:
|
||||
* -> 62 negative acknowlegde
|
||||
* <- A0 reponse gotnak
|
||||
* and send headblock again.
|
||||
* datablocks
|
||||
* -> [16384-byte-block] datablock
|
||||
* <- cc_cc response checksum
|
||||
* -> 60 positive acknowledge
|
||||
* <- A0 response gotack
|
||||
* repeat send for 26 datablocks of 16384 bytes. for each datablock do
|
||||
* retry on checksum mismatch like above for headblock.
|
||||
* after all data is written to IC35, wait 3.25 sec to
|
||||
* avoid failure in mdisconnect().
|
||||
* warning: IC35 does NOT restore phonetype and date+time,
|
||||
* they must be set manually after restore from file !
|
||||
*/
|
||||
|
||||
/* write IC35 database from file
|
||||
* -----------------------------
|
||||
*/
|
||||
static int
|
||||
_writedatabase( char * fname, FILE * fp, uchar * buff )
|
||||
{
|
||||
ulong fwlen;
|
||||
int wlen;
|
||||
int i;
|
||||
|
||||
LPRINTF(( L_INFO, "writedatabase %s ..", fname ));
|
||||
|
||||
/* check info from IC35 matching info in database file */
|
||||
fprintf( stderr, "write database <> %s info ", fname );
|
||||
fseek( fp, -2*INFOBLKSZ, SEEK_END );
|
||||
for ( i = 1; i <= NINFOBLKS; ++i ) {
|
||||
uchar info[INFOBLKSZ];
|
||||
if ( (wlen = _getdbinfo( buff, INFOBLKSZ )) != INFOBLKSZ ) {
|
||||
fprintf( stderr, "\n" );
|
||||
error( "writedatabase info-%d recv.error/timeout", i );
|
||||
return ERR;
|
||||
}
|
||||
if ( fread( info, sizeof(info[0]), INFOBLKSZ, fp ) != INFOBLKSZ ) {
|
||||
fprintf( stderr, "\n" );
|
||||
error( "writedatabase info-%d %s: read error %s (%d)",
|
||||
i, fname, strerror(errno), errno );
|
||||
return ERR;
|
||||
}
|
||||
if ( memcmp( buff, info, INFOBLKSZ ) != 0 ) {
|
||||
char * hextext;
|
||||
int j;
|
||||
fprintf( stderr, "\n" );
|
||||
if ( (hextext = malloc( INFOBLKSZ*3 + 1 )) != NULL ) {
|
||||
strcpy( hextext, "" );
|
||||
for ( j = 0; j < INFOBLKSZ; ++j )
|
||||
sprintf( hextext+strlen(hextext), "%02X ", buff[j] );
|
||||
message( "%s IC35", hextext );
|
||||
strcpy( hextext, "" );
|
||||
for ( j = 0; j < INFOBLKSZ; ++j )
|
||||
sprintf( hextext+strlen(hextext), "%02X ", info[j] );
|
||||
message( "%s %s", hextext, fname );
|
||||
free( hextext );
|
||||
}
|
||||
error( "writedatabase info-%d mismatch", i );
|
||||
}
|
||||
}
|
||||
rewind( fp );
|
||||
|
||||
/* send restore commands and wait for IC35 responses */
|
||||
fprintf( stderr, "\n" );
|
||||
if ( Mcmdrsp( MCMDrestinit, MRSPgotcmd ) < 0
|
||||
|| Mcmdrsp( MCMDrestdata, MRSPrestdata ) < 0 ) {
|
||||
error( "writedatabase restore command failed" );
|
||||
return ERR;
|
||||
}
|
||||
/* read headblock,datablocks from file and send to IC35 */
|
||||
fwlen = 0;
|
||||
for ( i = 0; i <= NDATABLKS; ++i ) {
|
||||
char btext[24+1];
|
||||
size_t blen;
|
||||
if ( i == 0 ) {
|
||||
fprintf( stderr, "write database <- %s head ", fname );
|
||||
strcpy( btext, "headblock" );
|
||||
blen = HEADBLKSZ;
|
||||
} else {
|
||||
sprintf( btext, "datablock-%d", i );
|
||||
blen = DATABLKSZ;
|
||||
}
|
||||
if ( fread( buff, sizeof(buff[0]), blen, fp ) != blen ) {
|
||||
fprintf( stderr, "\n" );
|
||||
error( "writedatabase %s %s: read error %s (%d)",
|
||||
btext, fname, strerror(errno), errno );
|
||||
return ERR;
|
||||
}
|
||||
if ( (wlen = Msendblk( buff, blen )) != blen ) {
|
||||
fprintf( stderr, "\n" );
|
||||
error( "writedatabase %s %s", btext, _dbetext( wlen ) );
|
||||
return ERR;
|
||||
}
|
||||
fwlen += wlen;
|
||||
fprintf( stderr, "\rwrite database <- %s %ldk ",
|
||||
fname, (fwlen+511)/1024 );
|
||||
}
|
||||
fprintf( stderr, "\n" );
|
||||
usleep( 3250000 ); /* wait 3.25 sec for IC35 doing restore */
|
||||
|
||||
LPRINTF(( L_INFO, "writedatabase %s OK", fname ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* write IC35 database: init,free resources
|
||||
* ----------------------------------------
|
||||
*/
|
||||
int
|
||||
writedatabase( char * fname )
|
||||
{
|
||||
uchar * buff;
|
||||
FILE * fp;
|
||||
int rval;
|
||||
|
||||
if ( (buff = malloc( DATABLKSZ )) != NULL ) {
|
||||
if ( fname && *fname
|
||||
&& (fp = fopen( fname, "r" )) != NULL ) {
|
||||
rval = _writedatabase( fname, fp, buff );
|
||||
fclose( fp );
|
||||
} else {
|
||||
error( "writedatabase cannot open %s", fname ? fname : "(NULL)" );
|
||||
rval = ERR;
|
||||
}
|
||||
free( buff );
|
||||
} else {
|
||||
error( "writedatabase failed: no memory (%d)", DATABLKSZ );
|
||||
rval = ERR;
|
||||
}
|
||||
return rval;
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2001 Thomas Schulz *
|
||||
* *
|
||||
* $Id: mgrtrans.h,v 1.7 2001/11/20 23:08:35 thosch Exp $ *
|
||||
* *
|
||||
* header for IC35 manager transactions *
|
||||
* *
|
||||
************************************************************************/
|
||||
#ifndef _MGRTRANS_H
|
||||
#define _MGRTRANS_H 1
|
||||
|
||||
#include <time.h> /* time_t */
|
||||
|
||||
#include "util.h" /* uchar,ulong, .. */
|
||||
#include "mgrproto.h" /* MMCattr*, open modes */
|
||||
|
||||
|
||||
typedef struct mmcdir MMCDIR;
|
||||
typedef struct mmcdirent { /* exported MMC directory entry */
|
||||
char name[8+1+3+1]; /* filename.ext */
|
||||
uchar attr; /* file attributes */
|
||||
ulong tstamp; /* timestamp (DOS-format) */
|
||||
ulong size; /* size in bytes */
|
||||
} MMCDIRENT;
|
||||
|
||||
typedef struct mmcfile MMCFILE;
|
||||
|
||||
|
||||
int mconnect( char * devname, char * statfname );
|
||||
int mdisconnect( void );
|
||||
|
||||
int mmc_status( int mmcnum );
|
||||
int mmc_label( int mmcnum, char label[11+1] );
|
||||
|
||||
MMCDIR * mmc_opendir( char * dirpath );
|
||||
MMCDIR * mmc_createdir( char * dirpath );
|
||||
MMCDIRENT * mmc_readdir( MMCDIR * dirp );
|
||||
int mmc_closedir( MMCDIR * dirp );
|
||||
char * mmctstampstr( ulong tstamp );
|
||||
time_t mmctstampunixtime( ulong tstamp );
|
||||
|
||||
int mmc_delfile( char * filepath );
|
||||
MMCFILE * mmc_openfile( char * filepath, ushort mode );
|
||||
MMCDIRENT * mmc_statfile( MMCFILE * fp );
|
||||
int mmc_readfile( MMCFILE * fp, uchar * buff, size_t blen );
|
||||
int mmc_writefile( MMCFILE * fp, uchar * data, size_t dlen );
|
||||
int mmc_closefile( MMCFILE * fp );
|
||||
|
||||
int readdatabase( char * fname );
|
||||
int writedatabase( char * fname );
|
||||
|
||||
#endif /*_MGRTRANS_H*/
|
|
@ -0,0 +1,94 @@
|
|||
/***************************************************************************
|
||||
(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
|
||||
Business Machines Corporation and Siemens Rolm Communications Inc.
|
||||
|
||||
modified 2000 by Thomas Schulz:
|
||||
$Id: port.h,v 1.3 2001/02/10 03:08:41 tsch Rel $
|
||||
|
||||
For purposes of this license notice, the term Licensors shall mean,
|
||||
collectively, Apple Computer, Inc., AT&T Corp., International
|
||||
Business Machines Corporation and Siemens Rolm Communications Inc.
|
||||
The term Licensor shall mean any of the Licensors.
|
||||
|
||||
Subject to acceptance of the following conditions, permission is hereby
|
||||
granted by Licensors without the need for written agreement and without
|
||||
license or royalty fees, to use, copy, modify and distribute this
|
||||
software for any purpose.
|
||||
|
||||
The above copyright notice and the following four paragraphs must be
|
||||
reproduced in all copies of this software and any software including
|
||||
this software.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
|
||||
ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
|
||||
MODIFICATIONS.
|
||||
|
||||
IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
|
||||
INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
|
||||
OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
|
||||
EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE.
|
||||
|
||||
The software is provided with RESTRICTED RIGHTS. Use, duplication, or
|
||||
disclosure by the government are subject to restrictions set forth in
|
||||
DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __PORT_H__
|
||||
#define __PORT_H__ 1
|
||||
|
||||
|
||||
#if defined(__CPLUSPLUS__) || defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* some of these #defines are commented out because */
|
||||
/* Visual C++ sets them on the compiler command line instead */
|
||||
|
||||
/* #define _DEBUG */
|
||||
/* #define WIN32 */
|
||||
/* #define WIN16 */
|
||||
/* #define _WINDOWS */
|
||||
/* #define __MWERKS__ */
|
||||
/* #define INCLUDEMFC */
|
||||
|
||||
#define vCardClipboardFormat "+//ISBN 1-887687-00-9::versit::PDI//vCard"
|
||||
#define vCalendarClipboardFormat "+//ISBN 1-887687-00-9::versit::PDI//vCalendar"
|
||||
|
||||
/* The above strings vCardClipboardFormat and vCalendarClipboardFormat
|
||||
are globally unique IDs which can be used to generate clipboard format
|
||||
ID's as per the requirements of a specific platform. For example, in
|
||||
Windows they are used as the parameter in a call to RegisterClipboardFormat.
|
||||
For example:
|
||||
|
||||
CLIPFORMAT foo = RegisterClipboardFormat(vCardClipboardFormat);
|
||||
|
||||
*/
|
||||
|
||||
#define vCardMimeType "text/x-vCard"
|
||||
#define vCalendarMimeType "text/x-vCalendar"
|
||||
|
||||
#define DLLEXPORT(t) t
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#define stricmp strcasecmp
|
||||
#ifdef __STRICT_ANSI__
|
||||
#include "util.h" /* strcasecmp() */
|
||||
#endif
|
||||
|
||||
#if defined(__CPLUSPLUS__) || defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __PORT_H__ */
|
|
@ -0,0 +1,649 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* */
|
||||
static char rcsid[] =
|
||||
"$Id: synproto.c,v 1.11 2001/06/17 23:37:36 tsch Rel $"; /*
|
||||
* *
|
||||
* IC35 synchronize protocol *
|
||||
* *
|
||||
*************************************************************************
|
||||
* *
|
||||
* ??? is "fixme" mark: sections of code needing fixes *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include <stdio.h> /* sprintf(), .. */
|
||||
#include <stdarg.h> /* va_start(), .. */
|
||||
#include <string.h> /* memcpy(), strlen() ..*/
|
||||
#include <time.h> /* struct tm, time(),.. */
|
||||
#include <sys/types.h> /* size_t, .. */
|
||||
|
||||
#include "util.h" /* ERR,OK, uchar, .. */
|
||||
#include "comio.h" /* com_send(), .. */
|
||||
#include "genproto.h" /* putxxx(),getxxx() .. */
|
||||
#include "synproto.h" /* Level-4 commands, .. */
|
||||
NOTUSED(rcsid)
|
||||
|
||||
|
||||
/* Level-1 PDU Ids */
|
||||
#define L1INIT 0x01 /* initialize 01 03 00 */
|
||||
#define L1DSEL 0x02 /* data select 02 ll ll <data> cc cc */
|
||||
#define L1DREQ 0x04 /* data request 04 03 00 */
|
||||
#define L1EXIT 0x05 /* exit 05 03 00 */
|
||||
#define L1ACK0 0xF0 /* ack to initialize */
|
||||
#define L1ACK1 0xF1 /* ack to datasel,exit */
|
||||
#define L1DATA 0xF2 /* data response F2 ll ll <data> cc cc */
|
||||
|
||||
/* Level-2 PDU Ids */
|
||||
#define L2INIT 0x80 /* cmd,rsp: identification */
|
||||
#define L2EXIT 0x81 /* cmd: disconnect */
|
||||
#define L2WMORE 0x02 /* cmd: write non-last of multiblk record */
|
||||
#define L2WLAST 0x82 /* cmd: write last of multi-block record */
|
||||
#define L2READ 0x83 /* cmd: read more of multi-block record */
|
||||
#define L2RMORE 0x20 /* rsp: non-last data of multi-block record */
|
||||
#define L2RLAST 0xA0 /* rsp: last data of multi-block record */
|
||||
#define L2RCONT 0x90 /* rsp: write more of multi-block record */
|
||||
|
||||
/* Level-3 PDU Ids */
|
||||
#define L3MORE 0x48 /* non-last of multi-block */
|
||||
#define L3LAST 0x49 /* last of multi-block or single */
|
||||
#define L3IDENT 0x4A /* identification */
|
||||
|
||||
/* Level-4 PDU definitions */
|
||||
|
||||
#define pdulenof(type,first,last) \
|
||||
( offsetof(type,last) + sizeof(((type*)0)->last) \
|
||||
- offsetof(type,first) )
|
||||
|
||||
struct hdr {
|
||||
uchar id; /* id */
|
||||
uchar len[2]; /* ll ll */
|
||||
};
|
||||
union recid {
|
||||
uchar recid[4]; /* re_cd_id fi IC35 record-ID */
|
||||
struct {
|
||||
uchar rec[3]; /* re_cd_id record-id part */
|
||||
uchar file[1]; /* fi file-id part */
|
||||
} id;
|
||||
};
|
||||
|
||||
struct cmdident {
|
||||
struct hdr l1head; /* 02 ll ll */
|
||||
struct hdr l2head; /* 80 ll ll */
|
||||
uchar magic[4]; /* 10 00 64 00 */
|
||||
struct hdr l3head; /* 4A ll ll */
|
||||
char text[28]; /* "INVENTEC CORPORATION PRODUCT" */
|
||||
};
|
||||
#define LCMDident pdulenof(struct cmdident, magic, text)
|
||||
struct rspident {
|
||||
struct hdr l1head; /* F2 ll ll */
|
||||
struct hdr l2head; /* A0 ll ll */
|
||||
uchar magic[4]; /* 10 00 D0 07 */
|
||||
struct hdr l3head; /* 4A ll ll */
|
||||
char text[31]; /* "INVENTEC CORPORATION DCS15 1.28" */
|
||||
};
|
||||
|
||||
struct cmdgetpower {
|
||||
uchar cmd[2]; /* 03 01 */
|
||||
char text[5]; /* "Power" */
|
||||
uchar zero[3]; /* 00 00 00 */
|
||||
};
|
||||
#define LCMDgetpower pdulenof(struct cmdgetpower, cmd, zero)
|
||||
struct rspgetpower {
|
||||
uchar rsp[2]; /* 03 01 */
|
||||
};
|
||||
struct cmdpassword {
|
||||
uchar cmd[2]; /* 03 00 */
|
||||
char text[8]; /* [password] */
|
||||
};
|
||||
#define LCMDpassword pdulenof(struct cmdpassword, cmd, text)
|
||||
struct rsppassword {
|
||||
uchar rsp[2]; /* 01 01 */
|
||||
};
|
||||
struct cmdcategory {
|
||||
uchar cmd[2]; /* 03 02 */
|
||||
char name[8]; /* [category] */
|
||||
};
|
||||
#define LCMDcategory pdulenof(struct cmdcategory, cmd, name)
|
||||
struct rspcategory {
|
||||
uchar rsp[2]; /* 00 01 */
|
||||
};
|
||||
struct cmdgetdtime {
|
||||
uchar cmd[2]; /* 02 00 */
|
||||
uchar zero[1]; /* 00 */
|
||||
};
|
||||
#define LCMDgetdtime pdulenof(struct cmdgetdtime, cmd, zero)
|
||||
struct rspgetdtime {
|
||||
uchar mdyhms[14]; /* [mmddyyyyhhmmss] */
|
||||
uchar zero[2]; /* 00 00 */
|
||||
};
|
||||
struct cmdsetdtime {
|
||||
uchar cmd[2]; /* 02 01 */
|
||||
uchar zero1[1]; /* 00 */
|
||||
char mdyhms[14]; /* [mmddyyyyhhmmss] */
|
||||
uchar zero2[2]; /* 00 00 */
|
||||
};
|
||||
#define LCMDsetdtime pdulenof(struct cmdsetdtime, cmd, zero2)
|
||||
/* rspsetdtime is done only */
|
||||
|
||||
struct cmdfopen {
|
||||
uchar cmd[2]; /* 00 02 */
|
||||
uchar zero[7]; /* 00 00 00 00 00 00 00 */
|
||||
uchar lf2[4]; /* length+2 (dword) */
|
||||
uchar lf[1]; /* length of filename */
|
||||
uchar fname[10+1]; /* [filename] 02 */
|
||||
};
|
||||
#define LCMDfopen (pdulenof(struct cmdfopen, cmd, lf) + 1) /* dynamic */
|
||||
struct rspfopen {
|
||||
uchar fd[2]; /* fd __ */
|
||||
};
|
||||
struct cmdfclose {
|
||||
uchar cmd[2]; /* 00 03 */
|
||||
uchar fd[2]; /* fd __ */
|
||||
uchar zero[4]; /* 00 00 00 00 */
|
||||
};
|
||||
#define LCMDfclose pdulenof(struct cmdfclose, cmd, zero)
|
||||
/* rspfclose is done only */
|
||||
|
||||
struct cmdfgetlen {
|
||||
uchar cmd[2]; /* 01 03 (or 01 04) */
|
||||
uchar fd[2]; /* fd __ */
|
||||
uchar zero[4]; /* 00 00 00 00 */
|
||||
};
|
||||
#define LCMDfgetlen pdulenof(struct cmdfgetlen, cmd, zero)
|
||||
struct rspfgetlen {
|
||||
uchar n[2]; /* n_ __ */
|
||||
};
|
||||
struct cmdfgetrec {
|
||||
uchar cmd[2]; /* 01 06 (or 01 07) */
|
||||
uchar fd[2]; /* fd __ */
|
||||
uchar index[2]; /* id x_ (not 01 07) */
|
||||
uchar zero[2]; /* 00 00 00 00 */
|
||||
};
|
||||
#define LCMDfgetrec pdulenof(struct cmdfgetrec, cmd, zero)
|
||||
struct cmdfgetirec {
|
||||
uchar cmd[2]; /* 01 05 */
|
||||
uchar fd[2]; /* fd __ */
|
||||
union recid uid; /* re c- id fi IC35 record-ID */
|
||||
};
|
||||
#define LCMDfgetirec pdulenof(struct cmdfgetirec, cmd, uid)
|
||||
struct rspfgetrec {
|
||||
union recid uid; /* re c. id fi IC35 record-ID */
|
||||
uchar fx[1]; /* fx change-flag on IC35 ? */
|
||||
uchar data[1]; /* flens,fdata.. (variable len) */
|
||||
};
|
||||
struct cmdfputrec { /* putrec or updrec */
|
||||
uchar cmd[2]; /* 01 08 01 09 */
|
||||
uchar fd[2]; /* fd __ */
|
||||
union recid uid; /* 00 00 00 00 or re c- id fi */
|
||||
uchar magic[3]; /* m1 m2 m3 */
|
||||
uchar zero2[2]; /* 00 00 */
|
||||
uchar lr[4]; /* length of record (dword) */
|
||||
uchar data[1]; /* flens,fdata.. (variable len) */
|
||||
};
|
||||
#define LCMDfputrec pdulenof(struct cmdfputrec, cmd, lr) /* dynamic */
|
||||
struct rspfputrec {
|
||||
union recid uid; /* re_cd_id fi IC35 record-ID */
|
||||
};
|
||||
struct cmdfclrchg { /* clrchg or delrec */
|
||||
uchar cmd[2]; /* 01 08 01 02 */
|
||||
uchar fd[2]; /* fd __ */
|
||||
union recid uid; /* re c- id fi IC35 record-ID */
|
||||
};
|
||||
#define LCMDfclrchg pdulenof(struct cmdfclrchg, cmd, uid)
|
||||
/* rspfclrchg is done only */
|
||||
|
||||
struct cmdpdu {
|
||||
struct hdr l1head; /* 01,02,04,05 */
|
||||
struct hdr l2head; /* 80,02,82,83,81 */
|
||||
struct hdr l3head; /* 48,49 */
|
||||
union {
|
||||
uchar cmd[2];
|
||||
struct cmdgetpower getpower;
|
||||
struct cmdpassword password;
|
||||
struct cmdcategory category;
|
||||
struct cmdgetdtime getdtime;
|
||||
struct cmdsetdtime setdtime;
|
||||
struct cmdfopen fopen;
|
||||
struct cmdfclose fclose;
|
||||
struct cmdfgetlen fgetlen;
|
||||
struct cmdfgetrec fgetrec;
|
||||
struct cmdfgetirec fgetirec;
|
||||
struct cmdfputrec fputrec;
|
||||
struct cmdfclrchg fclrchg;
|
||||
} u;
|
||||
};
|
||||
struct rsppdu {
|
||||
struct hdr l1head; /* F0,F1,F2 */
|
||||
struct hdr l2head; /* 20,A0,90 */
|
||||
struct hdr l3head; /* 48,49 */
|
||||
union {
|
||||
uchar rsp[2];
|
||||
struct rspgetpower getpower;
|
||||
struct rsppassword password;
|
||||
struct rspcategory category;
|
||||
struct rspgetdtime getdtime;
|
||||
/* rspsetdtime response done only */
|
||||
struct rspfopen fopen;
|
||||
/* rspfclose response done only */
|
||||
struct rspfgetlen fgetlen;
|
||||
struct rspfgetrec fgetrec;
|
||||
struct rspfputrec fputrec;
|
||||
/* rspfclrchg response done only */
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
/* ============================================ */
|
||||
/* utilities for PDU encode/decode */
|
||||
/* ============================================ */
|
||||
|
||||
/* encode data items to PDU
|
||||
* ------------------------
|
||||
* putbyte() etc. imported from genproto.c
|
||||
*/
|
||||
static int
|
||||
puthdr( uchar * pduptr, uchar id, int len )
|
||||
{
|
||||
putbyte( pduptr+0, id );
|
||||
putword( pduptr+1, (ushort)(len+3) );
|
||||
return len+3;
|
||||
}
|
||||
static void
|
||||
putcmd( uchar * pduptr, ushort cmd )
|
||||
{
|
||||
putbyte( pduptr+0, (cmd & 0xFF00) >> 8 ); /* MSB first .. */
|
||||
putbyte( pduptr+1, cmd & 0x00FF ); /* LSB second (!) */
|
||||
}
|
||||
|
||||
/* decode data items from PDU
|
||||
* --------------------------
|
||||
* getbyte() etc. imported from genproto.c
|
||||
*/
|
||||
static ushort
|
||||
getrsp( uchar * pduptr )
|
||||
{
|
||||
return (getbyte( pduptr+0 ) << 8) | getbyte( pduptr+1 );
|
||||
}
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* Level-1 protocol */
|
||||
/* ==================================== */
|
||||
/*
|
||||
* the Level-1 protocol transports a command to IC35 (->)
|
||||
* and receives a response from IC35 (<-):
|
||||
* L2sendcmd:
|
||||
* use default timeout (0.5 sec)
|
||||
* -> 01 03 00 init
|
||||
* <- F0 ack0
|
||||
* -> 02 ll ll <L2cmd> cc cc command to IC35
|
||||
* set timeout 2.0 sec for ack1 response
|
||||
* <- F1 ack1
|
||||
* restore previous timeout (0.5 sec)
|
||||
* L2recvrsp:
|
||||
* -> 04 03 00 request response
|
||||
* <- F2 ll ll <L2rsp> cc cc response from IC35
|
||||
* -> 05 03 00 exit
|
||||
* <- F1 ack1
|
||||
* longer timeout 2.0 sec for ack1 response to command is needed
|
||||
* e.g. for get_modflen. experiments showed ack1 response times
|
||||
* of 0.7 .. 0.9 sec for ca. 860 address records.
|
||||
*/
|
||||
|
||||
static uchar xbuff[4096]; /* PDU transmit buffer */
|
||||
|
||||
/* send Level-1 PDU
|
||||
* ----------------
|
||||
*/
|
||||
static int
|
||||
L1send( uchar id, uchar* pdu, size_t l2len )
|
||||
{
|
||||
size_t slen;
|
||||
uchar * spdu;
|
||||
uchar sbuff[3];
|
||||
|
||||
if ( pdu != NULL ) { /* long PDU with data and checksum */
|
||||
slen = puthdr( spdu = pdu, id, l2len+2 );
|
||||
putword( spdu+slen-2, chksum( spdu, slen-2 ) );
|
||||
} else { /* short PDU without data,checksum */
|
||||
slen = puthdr( spdu = sbuff, id, 0 );
|
||||
}
|
||||
return com_send( spdu, slen );
|
||||
}
|
||||
|
||||
/* receive Level-1 PDU
|
||||
* -------------------
|
||||
* returns:
|
||||
* <= 0 receive error: timeout, bad checksum of long PDU
|
||||
* == 0 short PDU received, *p_id = PDU-Id
|
||||
* > 0 long PDU received, *p_id = PDU-Id, *buff = PDU-data
|
||||
*/
|
||||
static int
|
||||
L1recv( uchar* prid, uchar * pdu, size_t blen )
|
||||
{
|
||||
int rlen, pdulen;
|
||||
|
||||
if ( prid == NULL )
|
||||
return ERR; /* semantic error */
|
||||
*prid = '\0';
|
||||
rlen = com_recv( prid, sizeof(*prid) );
|
||||
if ( rlen < 1 )
|
||||
return rlen; /* recv.ERR, timeout */
|
||||
if ( *prid != L1DATA )
|
||||
return OK; /* received ack0,ack1 */
|
||||
|
||||
if ( pdu == NULL ) {
|
||||
/*??? flush receive data */
|
||||
return ERR; /* semantic error */
|
||||
}
|
||||
pdu[0] = *prid;
|
||||
rlen = com_recv( pdu+1, 2 );
|
||||
if ( rlen < 2 )
|
||||
return ERR; /* miss length field */
|
||||
pdulen = getword( pdu+1 );
|
||||
if ( pdulen <= 3 )
|
||||
return ERR; /* too short data resp */
|
||||
rlen = com_recv( pdu+3, min(pdulen,blen)-3 );
|
||||
if ( rlen < pdulen - 3 )
|
||||
return ERR; /* length mismatch */
|
||||
if ( chksum( pdu, pdulen-2 ) != getword( pdu+pdulen-2 ) )
|
||||
return ERR; /* checksum mismatch */
|
||||
|
||||
return pdulen - 3 - 2; /* length of L2data */
|
||||
}
|
||||
|
||||
|
||||
/* send command with Level-1 protocol
|
||||
* ----------------------------------
|
||||
*/
|
||||
static int
|
||||
L2sendcmd( uchar* pdu, size_t l2len )
|
||||
{
|
||||
uchar rid;
|
||||
int old_tmo;
|
||||
int rval;
|
||||
|
||||
rval = OK;
|
||||
L1send( L1INIT, NULL, 0 ); /* -> 01 03 00 */
|
||||
L1recv( &rid, NULL, 0 ); /* <- F0 */
|
||||
if ( rid != L1ACK0 ) /* missing ack0 */
|
||||
return ERR;
|
||||
L1send( L1DSEL, pdu, l2len ); /* -> 02 ll ll <L2data> cc cc */
|
||||
old_tmo = com_settimeout( 2000 ); /* timeout 2.0 sec for ack1resp */
|
||||
L1recv( &rid, NULL, 0 ); /* <- F1 */
|
||||
com_settimeout( old_tmo ); /* restore previous timeout */
|
||||
if ( rid != L1ACK1 ) /* missing ack1 */
|
||||
return ERR;
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* receive response with Level-1 protocol
|
||||
* --------------------------------------
|
||||
*/
|
||||
static int
|
||||
L2recvrsp( uchar* rsp, size_t lrsp )
|
||||
{
|
||||
int rlen, rval;
|
||||
uchar rid;
|
||||
|
||||
rval = ERR;
|
||||
L1send( L1DREQ, NULL, 0 ); /* -> 04 03 00 */
|
||||
rlen = L1recv( &rid, rsp, lrsp ); /* <- F2 ll ll <L2data> cc cc */
|
||||
if ( rid == L1DATA )
|
||||
rval = rlen; /* return length of L2data */
|
||||
L1send( L1EXIT, NULL, 0 ); /* -> 05 03 00 */
|
||||
L1recv( &rid, NULL, 0 ); /* <- F1 */
|
||||
/*??? ignore if missing ack1 to exit */
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* Level-4 commands,responses */
|
||||
/* ==================================== */
|
||||
|
||||
/* encode command and send it
|
||||
* --------------------------
|
||||
* depending on the command-id 'cmd' zero, one or more parameters
|
||||
* are encoded.
|
||||
*/
|
||||
int
|
||||
sendcmd( ushort cmd, ... )
|
||||
{
|
||||
va_list argp;
|
||||
struct cmdpdu * pdu = (struct cmdpdu *)&xbuff[0];
|
||||
size_t pdusize = sizeof(xbuff);
|
||||
size_t pdulen;
|
||||
uchar l2id, l3id;
|
||||
|
||||
memset( pdu, 0, pdusize );
|
||||
putcmd( pdu->u.cmd, cmd );
|
||||
va_start( argp, cmd );
|
||||
switch ( cmd ) {
|
||||
default:
|
||||
return ERR; /* invalid 'cmd' */
|
||||
case CMDident:
|
||||
{ struct cmdident *idpdu = (struct cmdident *)pdu;
|
||||
char * inventec = "INVENTEC CORPORATION PRODUCT";
|
||||
putbtxt( idpdu->magic, "\x10\x00\x64\x00", sizeof(idpdu->magic) );
|
||||
puttext( idpdu->text, inventec );
|
||||
puthdr( (uchar*)&idpdu->l3head, L3IDENT, strlen(inventec) );
|
||||
pdulen = LCMDident;
|
||||
l2id = L2INIT; l3id = 0;
|
||||
} break;
|
||||
case CMDdisconn:
|
||||
pdulen = 0;
|
||||
l2id = L2EXIT; l3id = 0;
|
||||
break;
|
||||
case CMDgetpower:
|
||||
puttext( pdu->u.getpower.text, "Power" );
|
||||
pdulen = LCMDgetpower;
|
||||
l2id = L2WLAST; l3id = L3LAST;
|
||||
break;
|
||||
case CMDpassword:
|
||||
puttext( pdu->u.password.text, va_arg( argp, char* ) );
|
||||
pdulen = LCMDpassword;
|
||||
l2id = L2WLAST; l3id = L3LAST;
|
||||
break;
|
||||
case CMDcategory:
|
||||
puttext( pdu->u.category.name, va_arg( argp, char* ) );
|
||||
pdulen = LCMDcategory;
|
||||
l2id = L2WLAST; l3id = L3LAST;
|
||||
break;
|
||||
case CMDgetdtime:
|
||||
pdulen = LCMDgetdtime;
|
||||
l2id = L2READ; l3id = L3LAST;
|
||||
break;
|
||||
case CMDsetdtime:
|
||||
puttext( pdu->u.setdtime.mdyhms, va_arg( argp, char* ) );
|
||||
pdulen = LCMDsetdtime;
|
||||
l2id = L2WLAST; l3id = L3LAST;
|
||||
break;
|
||||
case CMDfopen:
|
||||
{ char * strarg = va_arg( argp, char* );
|
||||
putdword( pdu->u.fopen.lf2, (ulong)(strlen(strarg) + 2) );
|
||||
putbyte( pdu->u.fopen.lf, (uchar)strlen(strarg) );
|
||||
puttext( pdu->u.fopen.fname, strarg );
|
||||
putbyte( pdu->u.fopen.fname+strlen(strarg), '\x02' );
|
||||
pdulen = LCMDfopen + strlen(strarg);
|
||||
l2id = L2WLAST; l3id = L3LAST;
|
||||
} break;
|
||||
case CMDfclose:
|
||||
putword( pdu->u.fclose.fd, (ushort)va_arg( argp, int ) );
|
||||
pdulen = LCMDfclose;
|
||||
l2id = L2WLAST; l3id = L3LAST;
|
||||
break;
|
||||
case CMDfgetlen:
|
||||
case CMDfgetmlen:
|
||||
putword( pdu->u.fgetlen.fd, (ushort)va_arg( argp, int ) );
|
||||
pdulen = LCMDfgetlen;
|
||||
l2id = L2READ; l3id = L3LAST;
|
||||
break;
|
||||
case CMDfgetirec:
|
||||
putword( pdu->u.fgetirec.fd, (ushort)va_arg( argp, int ) );
|
||||
putdword( pdu->u.fgetirec.uid.recid, va_arg( argp, ulong ) );
|
||||
pdulen = LCMDfgetirec;
|
||||
l2id = L2READ; l3id = L3LAST;
|
||||
break;
|
||||
case CMDfgetrec:
|
||||
putword( pdu->u.fgetrec.fd, (ushort)va_arg( argp, int ) );
|
||||
putword( pdu->u.fgetrec.index, (ushort)va_arg( argp, int ) );
|
||||
pdulen = LCMDfgetrec;
|
||||
l2id = L2READ; l3id = L3LAST;
|
||||
break;
|
||||
case CMDfgetmrec:
|
||||
putword( pdu->u.fgetrec.fd, (ushort)va_arg( argp, int ) );
|
||||
pdulen = LCMDfgetrec;
|
||||
l2id = L2READ; l3id = L3LAST;
|
||||
break;
|
||||
case CMDfgetmore:
|
||||
pdulen = 0;
|
||||
l2id = L2READ; l3id = 0;
|
||||
break;
|
||||
case CMDfputrec:
|
||||
case CMDfupdrec:
|
||||
{ bool last = va_arg( argp, bool );
|
||||
uchar * bstrarg;
|
||||
size_t bstrlen;
|
||||
putword( pdu->u.fputrec.fd, (ushort)va_arg( argp, int ) );
|
||||
putdword( pdu->u.fputrec.uid.recid, va_arg( argp, ulong ) );
|
||||
putbtxt( pdu->u.fputrec.magic, va_arg( argp, uchar* ),
|
||||
sizeof(pdu->u.fputrec.magic) );
|
||||
putdword( pdu->u.fputrec.lr, va_arg( argp, size_t ) );
|
||||
bstrarg = va_arg( argp, uchar* );
|
||||
bstrlen = va_arg( argp, size_t );
|
||||
putbtxt( pdu->u.fputrec.data, bstrarg, bstrlen );
|
||||
pdulen = LCMDfputrec + bstrlen;
|
||||
if ( ! last )
|
||||
l2id = L2WMORE, l3id = L3MORE;
|
||||
else
|
||||
l2id = L2WLAST, l3id = L3LAST;
|
||||
} break;
|
||||
case CMDfputmore:
|
||||
{ bool last = va_arg( argp, bool );
|
||||
uchar * bstrarg = va_arg( argp, uchar* );
|
||||
size_t bstrlen = va_arg( argp, size_t );
|
||||
putbtxt( pdu->u.cmd, bstrarg, bstrlen );
|
||||
pdulen = bstrlen;
|
||||
if ( ! last )
|
||||
l2id = L2WMORE, l3id = L3MORE;
|
||||
else
|
||||
l2id = L2WLAST, l3id = L3LAST;
|
||||
} break;
|
||||
case CMDfdelrec:
|
||||
case CMDfclrchg:
|
||||
putword( pdu->u.fclrchg.fd, (ushort)va_arg( argp, int ) );
|
||||
putdword( pdu->u.fclrchg.uid.recid, va_arg( argp, ulong ) );
|
||||
pdulen = LCMDfclrchg;
|
||||
l2id = L2WLAST; l3id = L3LAST;
|
||||
break;
|
||||
}
|
||||
va_end( argp );
|
||||
if ( l3id )
|
||||
pdulen = puthdr( (uchar*)&pdu->l3head, l3id, pdulen );
|
||||
pdulen = puthdr( (uchar*)&pdu->l2head, l2id, pdulen );
|
||||
return L2sendcmd( (uchar*)pdu, pdulen );
|
||||
}
|
||||
|
||||
/* receive response and decode it
|
||||
* ------------------------------
|
||||
* ??? check received l2id,l3id match with cmd acc.to protocol
|
||||
*/
|
||||
int
|
||||
recvrsp( ushort cmd, ... )
|
||||
{
|
||||
va_list argp;
|
||||
uchar l2id, l3id;
|
||||
ushort rsp;
|
||||
int pdulen;
|
||||
size_t pdusize = sizeof(xbuff);
|
||||
struct rsppdu * pdu = (struct rsppdu *)&xbuff[0];
|
||||
|
||||
va_start( argp, cmd );
|
||||
memset( pdu, 0, pdusize );
|
||||
if ( (pdulen = L2recvrsp( (uchar*)pdu, pdusize )) < 0 )
|
||||
return pdulen;
|
||||
l2id = getbyte( (uchar*)&pdu->l2head );
|
||||
l3id = 0x00;
|
||||
if ( pdulen >= sizeof(pdu->l2head) ) {
|
||||
pdulen -= sizeof(pdu->l2head);
|
||||
l3id = getbyte( (uchar*)&pdu->l3head );
|
||||
if ( pdulen >= sizeof(pdu->l3head) )
|
||||
pdulen -= sizeof(pdu->l3head);
|
||||
}
|
||||
rsp = getrsp( pdu->u.rsp );
|
||||
switch ( cmd ) {
|
||||
default:
|
||||
return ERR; /* invalid 'cmd' */
|
||||
case CMDident:
|
||||
{ struct rspident *idpdu = (struct rspident *)pdu;
|
||||
char * ptext = va_arg( argp, char* );
|
||||
size_t lptext = va_arg( argp, size_t );
|
||||
pdulen -= sizeof(idpdu->magic);
|
||||
gettext( idpdu->text, ptext, min(pdulen, lptext) );
|
||||
} break;
|
||||
case CMDdisconn:
|
||||
break;
|
||||
case CMDgetpower:
|
||||
{ ushort * pstate = va_arg( argp, ushort* );
|
||||
*pstate = rsp;
|
||||
} break;
|
||||
case CMDpassword:
|
||||
{ ushort * pstate = va_arg( argp, ushort* );
|
||||
*pstate = rsp;
|
||||
} break;
|
||||
case CMDgetdtime:
|
||||
{ char * pdtime = va_arg( argp, char* );
|
||||
size_t lpdtime = va_arg( argp, size_t );
|
||||
gettext( pdu->u.getdtime.mdyhms, pdtime,
|
||||
min(sizeof(pdu->u.getdtime.mdyhms), lpdtime) );
|
||||
} break;
|
||||
case CMDsetdtime:
|
||||
break;
|
||||
case CMDcategory:
|
||||
{ ushort * pstate = va_arg( argp, ushort* );
|
||||
*pstate = rsp;
|
||||
} break;
|
||||
case CMDfopen:
|
||||
{ ushort * pfd = va_arg( argp, ushort* );
|
||||
*pfd = getword( pdu->u.fopen.fd );
|
||||
} break;
|
||||
case CMDfclose:
|
||||
break;
|
||||
case CMDfgetlen:
|
||||
case CMDfgetmlen:
|
||||
{ ushort * pflen = va_arg( argp, ushort* );
|
||||
*pflen = getword( pdu->u.fgetlen.n );
|
||||
} break;
|
||||
case CMDfgetrec:
|
||||
{ bool * plast = va_arg( argp, bool* );
|
||||
ulong * prid = va_arg( argp, ulong* );
|
||||
uchar * pchg = va_arg( argp, uchar* );
|
||||
uchar * buff = va_arg( argp, uchar* );
|
||||
size_t blen = va_arg( argp, size_t );
|
||||
*plast = (bool)( l2id == L2RLAST );
|
||||
*prid = getdword( pdu->u.fgetrec.uid.recid );
|
||||
*pchg = getbyte( pdu->u.fgetrec.fx );
|
||||
memcpy( buff, pdu->u.fgetrec.data, min(blen,pdulen) );
|
||||
pdulen -= offsetof(struct rspfgetrec, data); /* length of record data */
|
||||
} break;
|
||||
case CMDfgetmore:
|
||||
{ bool * plast = va_arg( argp, bool* );
|
||||
uchar * buff = va_arg( argp, uchar* );
|
||||
size_t blen = va_arg( argp, size_t );
|
||||
*plast = (bool)( l2id == L2RLAST );
|
||||
memcpy( buff, pdu->u.rsp, min(blen,pdulen) );
|
||||
} break;
|
||||
case CMDfputrec:
|
||||
if ( l2id == L2RLAST && l3id == L3LAST ) {
|
||||
ulong * prid = va_arg( argp, ulong* );
|
||||
*prid = getdword( pdu->u.fputrec.uid.recid );
|
||||
}
|
||||
break;
|
||||
case CMDfdelrec:
|
||||
case CMDfclrchg:
|
||||
break;
|
||||
}
|
||||
return pdulen;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* *
|
||||
* $Id: synproto.h,v 1.3 2000/12/03 07:50:44 tsch Rel $ *
|
||||
* *
|
||||
* header for IC35 synchronize protocol *
|
||||
* *
|
||||
************************************************************************/
|
||||
#ifndef _SYNPROTO_H
|
||||
#define _SYNPROTO_H 1
|
||||
|
||||
#include "util.h" /* ushort */
|
||||
|
||||
|
||||
/* Level-4 commands,responses */
|
||||
#define CMDident 0x1000
|
||||
#define CMDpassword 0x0300
|
||||
#define RSPpasswdOK 0x0101
|
||||
#define CMDgetpower 0x0301
|
||||
#define RSPpowerOK 0x0301
|
||||
#define CMDcategory 0x0302
|
||||
#define RSPcategOK 0x0001
|
||||
#define CMDgetdtime 0x0200
|
||||
#define CMDsetdtime 0x0201
|
||||
#define CMDfopen 0x0002
|
||||
#define CMDfclose 0x0003
|
||||
#define CMDfdelrec 0x0102 /* delete record */
|
||||
#define CMDfgetlen 0x0103 /* get total number of records */
|
||||
#define CMDfgetmlen 0x0104 /* get number of modified records */
|
||||
#define CMDfgetirec 0x0105 /* read record by recID */
|
||||
#define CMDfgetrec 0x0106 /* read record by index */
|
||||
#define CMDfgetmrec 0x0107 /* read next modified record */
|
||||
#define CMDfgetmore 0x83
|
||||
#define CMDfputrec 0x0108 /* write record, gets new recID */
|
||||
#define CMDfupdrec 0x0109 /* update record, keeps recID */
|
||||
#define CMDfputmore 0x90
|
||||
#define CMDfclrchg 0x010A /* commit record */
|
||||
#define CMDdisconn 0x81
|
||||
|
||||
|
||||
int sendcmd( ushort cmd, ... ); /* encode command and send */
|
||||
int recvrsp( ushort cmd, ... ); /* receive response and decode */
|
||||
|
||||
#endif /*_SYNPROTO_H*/
|
|
@ -0,0 +1,515 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* */
|
||||
static char rcsid[] =
|
||||
"$Id: syntrans.c,v 1.19 2001/03/02 02:09:59 tsch Rel $"; /*
|
||||
* *
|
||||
* IC35 synchronize transactions *
|
||||
* *
|
||||
*************************************************************************
|
||||
* *
|
||||
* ??? is "fixme" mark: sections of code needing fixes *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include <stdio.h> /* fprintf(), .. */
|
||||
#include <string.h> /* memcpy(), strlen() ..*/
|
||||
#include <stdlib.h> /* calloc(), .. */
|
||||
#include <sys/types.h> /* size_t, .. */
|
||||
|
||||
#include "util.h" /* ERR,OK, uchar, .. */
|
||||
#include "comio.h" /* com_init(), .. */
|
||||
#include "genproto.h" /* welcome() */
|
||||
#include "synproto.h" /* Level-4 commands, .. */
|
||||
#include "syntrans.h"
|
||||
#include "ic35frec.h" /* IC35REC, .. */
|
||||
NOTUSED(rcsid);
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* comunication phases */
|
||||
/* ==================================== */
|
||||
|
||||
/* welcome phase
|
||||
* -------------
|
||||
* opens comm.device and does welcome handshake
|
||||
*/
|
||||
static int
|
||||
synwelcome( char * devname )
|
||||
{
|
||||
int rval;
|
||||
|
||||
LPRINTF(( L_INFO, "welcome(%s) ..", devname ));
|
||||
if ( com_init( devname ) != OK ) {
|
||||
error( "welcome failed: com_init(%s) failed", devname );
|
||||
return ERR;
|
||||
}
|
||||
message( "welcome, start IC35 !" );
|
||||
if ( (rval = welcome( 0x41 )) != OK ) {
|
||||
error( "welcome %s", rval == ERR_intr ? "aborted"
|
||||
: "failed: no response" );
|
||||
return ERR;
|
||||
}
|
||||
message( "connected" );
|
||||
LPRINTF(( L_INFO, "welcome(%s) OK", devname ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* identify
|
||||
* --------
|
||||
*/
|
||||
static int
|
||||
identify( char * rtext )
|
||||
{
|
||||
char idtext[39+1];
|
||||
|
||||
LPRINTF(( L_INFO, "identify .." ));
|
||||
if ( sendcmd( CMDident ) < 0
|
||||
|| recvrsp( CMDident, idtext, sizeof(idtext) ) < 0 ) {
|
||||
error( "identify failed" );
|
||||
return ERR;
|
||||
}
|
||||
if ( rtext != NULL )
|
||||
strncat( strcpy( rtext, "" ), idtext, sizeof(idtext)-1 );
|
||||
LPRINTF(( L_INFO, "identify OK" ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* power
|
||||
* -----
|
||||
*/
|
||||
static int
|
||||
power( void )
|
||||
{
|
||||
ushort pstate = 0xFFFF;
|
||||
|
||||
LPRINTF(( L_INFO, "power .." ));
|
||||
if ( sendcmd( CMDgetpower ) < 0
|
||||
|| recvrsp( CMDgetpower, &pstate ) < 0
|
||||
|| pstate != RSPpowerOK ) {
|
||||
error( "power failed (%04X)", pstate );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "power OK (%04X)", pstate ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* authenticate
|
||||
* ------------
|
||||
*/
|
||||
static int
|
||||
authenticate( char * passwd )
|
||||
{
|
||||
ushort pstate = 0xFFFF;
|
||||
|
||||
LPRINTF(( L_INFO, "password .." ));
|
||||
if ( sendcmd( CMDpassword, passwd ) < 0
|
||||
|| recvrsp( CMDpassword, &pstate ) < 0
|
||||
|| pstate != RSPpasswdOK ) {
|
||||
error( "password failed (%04X)", pstate );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "password OK (%04X)", pstate ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* read/write IC35 reference info
|
||||
* ------------------------------
|
||||
* reference info can be an arbitrary string of up to 16 chars.
|
||||
* IC35sync/Windows uses mmddyyyyhhmmss to retrieve date+time of
|
||||
* last sync from IC35 or store it into IC35.
|
||||
*/
|
||||
int
|
||||
ReadSysInfo( char * infobuff )
|
||||
{
|
||||
char rinfo[16+1];
|
||||
|
||||
LPRINTF(( L_INFO, "ReadSysInfo .." ));
|
||||
if ( sendcmd( CMDgetdtime ) < 0
|
||||
|| recvrsp( CMDgetdtime, rinfo, sizeof(rinfo) ) < 0 ) {
|
||||
error( "ReadSysInfo failed" );
|
||||
return ERR;
|
||||
}
|
||||
if ( infobuff != NULL )
|
||||
strncat( strcpy( infobuff, "" ), rinfo, sizeof(rinfo)-1 );
|
||||
LPRINTF(( L_INFO, "ReadSysInfo OK (%s)", rinfo ));
|
||||
return OK;
|
||||
}
|
||||
int
|
||||
WriteSysInfo( char * infodata )
|
||||
{
|
||||
LPRINTF(( L_INFO, "WriteSysInfo %s ..", infodata ));
|
||||
if ( sendcmd( CMDsetdtime, infodata ) < 0
|
||||
|| recvrsp( CMDsetdtime ) < 0 ) {
|
||||
error( "WriteSysInfo \"%s\" failed", infodata );
|
||||
return ERR;
|
||||
}
|
||||
message( "set sysinfo \"%s\"", infodata );
|
||||
LPRINTF(( L_INFO, "WriteSysInfo OK" ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* category
|
||||
* --------
|
||||
* ??? semantics not clear
|
||||
*/
|
||||
int
|
||||
category( char * name )
|
||||
{
|
||||
ushort state = 0xFFFF;
|
||||
|
||||
LPRINTF(( L_INFO, "category(%s) ..", name ));
|
||||
if ( sendcmd( CMDcategory, name ) < 0
|
||||
|| recvrsp( CMDcategory, &state ) < 0 ) {
|
||||
error( "category(%s) failed (%04hX)", name, state );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "category(%s) OK (%04hX)", name, state ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* open com-device and connect with IC35
|
||||
* -------------------------------------
|
||||
*/
|
||||
int
|
||||
connect( char * devname, char * passwd, char * rdtime )
|
||||
{
|
||||
int rval;
|
||||
char idtext[64];
|
||||
|
||||
if ( (rval = synwelcome( devname )) == OK
|
||||
&& (rval = identify( idtext )) == OK
|
||||
&& (rval = power()) == OK
|
||||
&& (rval = authenticate( passwd )) == OK
|
||||
&& (rval = ReadSysInfo( rdtime )) == OK )
|
||||
if ( rdtime != NULL )
|
||||
message( "version \"%s\" sysinfo \"%s\"", idtext, rdtime );
|
||||
else
|
||||
message( "version \"%s\"", idtext );
|
||||
else
|
||||
disconnect();
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* disconnect from IC35 and close com-device
|
||||
* -----------------------------------------
|
||||
*/
|
||||
int
|
||||
disconnect( void )
|
||||
{
|
||||
message( "disconnect" );
|
||||
sendcmd( CMDdisconn );
|
||||
recvrsp( CMDdisconn );
|
||||
com_exit();
|
||||
LPRINTF(( L_INFO, "disconnect done." ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* access file on IC35 */
|
||||
/* ==================================== */
|
||||
|
||||
/* open file
|
||||
* ---------
|
||||
*/
|
||||
int
|
||||
open_file( char * fname )
|
||||
{
|
||||
ushort fd;
|
||||
|
||||
LPRINTF(( L_INFO, "open_file(%s) ..", fname ));
|
||||
if ( sendcmd( CMDfopen, fname ) < 0
|
||||
|| recvrsp( CMDfopen, &fd ) < 0 ) {
|
||||
error( "openfile(%s) failed", fname );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "open_file(%s) fd=%04hX", fname, fd ));
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* get filelength
|
||||
* --------------
|
||||
*/
|
||||
/* get total number of records */
|
||||
int
|
||||
get_flen( int fd )
|
||||
{
|
||||
ushort flen;
|
||||
|
||||
LPRINTF(( L_INFO, "get_flen(fd=%04hX) ..", fd ));
|
||||
if ( sendcmd( CMDfgetlen, fd ) < 0
|
||||
|| recvrsp( CMDfgetlen, &flen ) < 0 ) {
|
||||
error( "get_flen(fd=%04X) failed", fd );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "get_flen(fd=%04X) %hd records", fd, flen ));
|
||||
return flen;
|
||||
}
|
||||
/* get number of modified records */
|
||||
int
|
||||
get_mod_flen( int fd )
|
||||
{
|
||||
ushort flen;
|
||||
|
||||
LPRINTF(( L_INFO, "get_mod_flen(fd=%04X) ..", fd ));
|
||||
if ( sendcmd( CMDfgetmlen, fd ) < 0
|
||||
|| recvrsp( CMDfgetmlen, &flen ) < 0 ) {
|
||||
error( "get_mod_flen(fd=%04X) failed", fd );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "get_mod_flen(fd=%04X) %hd records", fd, flen ));
|
||||
return flen;
|
||||
}
|
||||
|
||||
/* read file record
|
||||
* ----------------
|
||||
* there are 3 methods to read records from IC35 file:
|
||||
* - read_frec read record by index
|
||||
* - read_mod_frec read next modified record
|
||||
* - read_id_frec read record by record-ID
|
||||
* return:
|
||||
* -1 ERR, communication error
|
||||
* 0 uncommitted deleted record (read_mod_frec)
|
||||
* or record does not exist (read_id_frec)
|
||||
* >0 OK, length of record data
|
||||
*/
|
||||
static int
|
||||
_read_frec( IC35REC * rec )
|
||||
{
|
||||
ulong rid; /* record-id on IC35 */
|
||||
uchar chg; /* change-flag on IC35 */
|
||||
bool last; /* last of multi-block */
|
||||
uchar * buff;
|
||||
size_t blen;
|
||||
uchar *rptr, *rend;
|
||||
int rlen;
|
||||
|
||||
if ( (buff = calloc( blen = MAXRLEN, sizeof(*buff) )) == NULL ) {
|
||||
error( "_read_frec() failed: no memory for buffer (%d)", blen );
|
||||
return -1;
|
||||
}
|
||||
rend = (rptr = buff) + blen;
|
||||
for ( ; ; ) {
|
||||
if ( rptr == buff )
|
||||
rlen = recvrsp( CMDfgetrec, &last, &rid, &chg, rptr, rend - rptr );
|
||||
else
|
||||
rlen = recvrsp( CMDfgetmore, &last, rptr, rend - rptr );
|
||||
if ( rlen < 0 ) {
|
||||
free( buff );
|
||||
error( "_read_frec() failed: recvrsp(%s)",
|
||||
rptr == buff ? "getrec" : "getmore" );
|
||||
return ERR;
|
||||
}
|
||||
rptr += rptr + rlen <= rend ? rlen : 0;
|
||||
if ( last )
|
||||
break;
|
||||
sendcmd( CMDfgetmore );
|
||||
}
|
||||
rlen = rptr - buff;
|
||||
set_ic35recid( rec, rid );
|
||||
set_ic35recchg( rec, chg );
|
||||
set_ic35recdata( rec, buff, rlen );
|
||||
free( buff );
|
||||
return rlen;
|
||||
}
|
||||
/* read file record by record-ID */
|
||||
int
|
||||
read_id_frec( int fd, ulong rid, IC35REC * rec )
|
||||
{
|
||||
int rlen;
|
||||
|
||||
LPRINTF(( L_INFO, "read_id_frec(fd=%04X,rid=%08lX) ..", fd, rid ));
|
||||
if ( sendcmd( CMDfgetirec, fd, rid ) < 0 ) {
|
||||
error( "read_id_frec(fd=%04X,rid=%08lX) failed: sendcmd", fd, rid );
|
||||
return ERR;
|
||||
}
|
||||
if ( (rlen = _read_frec( rec )) < 0 ) {
|
||||
error( "read_id_frec(fd=%04X,rid=%08lX) failed: recvrsp", fd, rid );
|
||||
return ERR;
|
||||
}
|
||||
if ( ic35recid( rec ) != rid ) {
|
||||
LPRINTF(( L_INFO, "read_id_frec(fd=%04X,rid=%08lX) non-exist", fd, rid ));
|
||||
return 0;
|
||||
}
|
||||
LPRINTF(( L_INFO, "read_id_frec(fd=%04X,rid=%08lX) len=%d", fd, rid, rlen ));
|
||||
return rlen;
|
||||
}
|
||||
/* read file record by index */
|
||||
int
|
||||
read_frec( int fd, int idx, IC35REC * rec )
|
||||
{
|
||||
int rlen;
|
||||
|
||||
LPRINTF(( L_INFO, "read_frec(fd=%04X,i=%04X) ..", fd, idx ));
|
||||
if ( sendcmd( CMDfgetrec, fd, idx ) < 0 ) {
|
||||
error( "read_frec(fd=%04X,i=%04X) failed: sendcmd", fd, idx );
|
||||
return ERR;
|
||||
}
|
||||
if ( (rlen = _read_frec( rec )) < 0 ) {
|
||||
error( "read_frec(fd=%04X,i=%04X) failed: recvrsp", fd, idx );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "read_frec(fd=%04X,i=%04X) len=%d", fd, idx, rlen ));
|
||||
return rlen;
|
||||
}
|
||||
/* read next modified file record */
|
||||
int
|
||||
read_mod_frec( int fd, IC35REC * rec )
|
||||
{
|
||||
int rlen;
|
||||
|
||||
LPRINTF(( L_INFO, "read_mod_frec(fd=%04X) ..", fd ));
|
||||
if ( sendcmd( CMDfgetmrec, fd ) < 0 ) {
|
||||
error( "read_mod_frec(fd=%04X) failed: sendcmd", fd );
|
||||
return ERR;
|
||||
}
|
||||
if ( (rlen = _read_frec( rec )) < 0 ) {
|
||||
error( "read_mod_frec(fd=%04X) failed: recvrsp", fd );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "read_mod_frec(fd=%04X) len=%d", fd, rlen ));
|
||||
return rlen;
|
||||
}
|
||||
|
||||
/* write/update file record
|
||||
* ------------------------
|
||||
* write_frec() writes new record, which gets new record-ID,
|
||||
* update_frec() writes new data into an existing record and
|
||||
* keeps same record-ID.
|
||||
* ??? the meaning of magic is unclear, perceived were:
|
||||
* IC35file bytes
|
||||
* Addresses 51 00 00
|
||||
* Memo 58 48 99
|
||||
* 60 16 99
|
||||
* Schedule 10 00 00
|
||||
* ToDoList 10 00 00
|
||||
*/
|
||||
#define DOwrite TRUE
|
||||
#define DOupdate FALSE
|
||||
|
||||
static int
|
||||
_write_frec( bool do_write, int fd, IC35REC * rec )
|
||||
{
|
||||
uchar * data;
|
||||
size_t dlen;
|
||||
uchar * wptr;
|
||||
size_t wlen;
|
||||
uchar * magic;
|
||||
bool last;
|
||||
int rval;
|
||||
ulong orecid, recid;
|
||||
|
||||
orecid = ic35recid( rec );
|
||||
get_ic35recdata( rec, &data, &dlen );
|
||||
switch ( FileId( orecid ) ) {
|
||||
case FILEADDR: magic = "\x51\x00\x00"; break;
|
||||
case FILEMEMO: magic = "\x60\x16\x99"; break;
|
||||
case FILETODO:
|
||||
case FILESCHED: magic = "\x10\x00\x00"; break;
|
||||
default: magic = "\x00\x00\x00"; break;
|
||||
}
|
||||
wptr = data;
|
||||
do {
|
||||
wlen = data+dlen - wptr;
|
||||
if ( wlen > 80 ) wlen = 80;
|
||||
last = (bool)( wptr+wlen >= data+dlen );
|
||||
if ( wptr == data )
|
||||
if ( do_write )
|
||||
rval = sendcmd( CMDfputrec, last, fd, 0L, magic, dlen,
|
||||
wptr, wlen );
|
||||
else /* update */
|
||||
rval = sendcmd( CMDfupdrec, last, fd, orecid, magic, dlen,
|
||||
wptr, wlen );
|
||||
else
|
||||
rval = sendcmd( CMDfputmore, last, wptr, wlen );
|
||||
if ( rval < 0 )
|
||||
return -1;
|
||||
if ( recvrsp( CMDfputrec, &recid ) < 0 )
|
||||
return -2;
|
||||
wptr += wlen;
|
||||
} while ( wptr < data+dlen );
|
||||
set_ic35recid( rec, recid );
|
||||
return 0;
|
||||
}
|
||||
/* write record, gets new record-ID */
|
||||
int
|
||||
write_frec( int fd, IC35REC * rec )
|
||||
{
|
||||
int rval;
|
||||
|
||||
LPRINTF(( L_INFO, "write_frec(fd=%04X) ..", fd ));
|
||||
if ( (rval = _write_frec( DOwrite, fd, rec )) < 0 ) {
|
||||
error( "write_frec(fd=%04X) failed: %s",
|
||||
fd, rval == -1 ? "sendcmd" : "recvrsp" );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "write_frec(fd=%04X) rid=%08lX", fd, ic35recid( rec ) ));
|
||||
return OK;
|
||||
}
|
||||
/* write record update, keeps record-ID */
|
||||
int
|
||||
update_frec( int fd, IC35REC * rec )
|
||||
{
|
||||
int rval;
|
||||
ulong orecid;
|
||||
|
||||
orecid = ic35recid( rec );
|
||||
LPRINTF(( L_INFO, "update_frec(fd=%04X,orid=%08lX) ..", fd, orecid ));
|
||||
if ( (rval = _write_frec( DOupdate, fd, rec )) < 0 ) {
|
||||
error( "update_frec(fd=%04X,orid=%08lX) failed: %s",
|
||||
fd, orecid, rval == -1 ? "sendcmd" : "recvrsp" );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "update_frec(fd=%04X,orid=%08lX) nrid=%08lX",
|
||||
fd, orecid, ic35recid( rec ) ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* delete file record
|
||||
* ------------------
|
||||
*/
|
||||
int
|
||||
delete_frec( int fd, ulong recid )
|
||||
{
|
||||
LPRINTF(( L_INFO, "delete_frec(fd=%04X,rid=%08lX) ..", fd, recid ));
|
||||
if ( sendcmd( CMDfdelrec, fd, recid ) < 0
|
||||
|| recvrsp( CMDfdelrec ) < 0 ) {
|
||||
error( "delete_frec(fd=%04X,rid=%08X) failed", fd, recid );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "delete_frec(fd=%04X,rid=%08lX) OK", fd, recid ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* commit file record, i.e. reset change flag
|
||||
* ------------------------------------------
|
||||
*/
|
||||
int
|
||||
commit_frec( int fd, ulong recid )
|
||||
{
|
||||
LPRINTF(( L_INFO, "commit_frec(fd=%04X,rid=%08lX) ..", fd, recid ));
|
||||
if ( sendcmd( CMDfclrchg, fd, recid ) < 0
|
||||
|| recvrsp( CMDfclrchg ) < 0 ) {
|
||||
error( "commit_frec(fd=%04hX,rid=%08X) failed", fd, recid );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "commit_frec(fd=%04hX,rid=%08lX) OK", fd, recid ));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* close file
|
||||
* ----------
|
||||
*/
|
||||
int
|
||||
close_file( int fd )
|
||||
{
|
||||
LPRINTF(( L_INFO, "close_file(fd=%04X) ..", fd ));
|
||||
if ( sendcmd( CMDfclose, fd ) < 0
|
||||
|| recvrsp( CMDfclose ) < 0 ) {
|
||||
error( "close_file(fd=%04X) failed", fd );
|
||||
return ERR;
|
||||
}
|
||||
LPRINTF(( L_INFO, "close_file(fd=%04X) OK", fd ));
|
||||
return OK;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* *
|
||||
* $Id: syntrans.h,v 1.10 2000/12/21 11:05:52 tsch Rel $ *
|
||||
* *
|
||||
* header for IC35 synchronize transactions *
|
||||
* *
|
||||
************************************************************************/
|
||||
#ifndef _SYNTRANS_H
|
||||
#define _SYNTRANS_H 1
|
||||
|
||||
#include <sys/types.h> /* size_t */
|
||||
|
||||
#include "util.h" /* uchar, .. */
|
||||
#include "ic35frec.h" /* IC35REC */
|
||||
|
||||
|
||||
int connect( char * devname, char * passwd, char * rdtime );
|
||||
int disconnect( void );
|
||||
|
||||
int ReadSysInfo( char * infobuff );
|
||||
int WriteSysInfo( char * infodata );
|
||||
int category( char * name );
|
||||
|
||||
int open_file( char * fname );
|
||||
int get_flen( int fd );
|
||||
int get_mod_flen( int fd );
|
||||
int read_id_frec( int fd, ulong rid, IC35REC * rec );
|
||||
int read_frec( int fd, int idx, IC35REC * rec );
|
||||
int read_mod_frec( int fd, IC35REC * rec );
|
||||
int write_frec( int fd, IC35REC * rec );
|
||||
int update_frec( int fd, IC35REC * rec );
|
||||
int delete_frec( int fd, ulong recid );
|
||||
int commit_frec( int fd, ulong recid );
|
||||
int close_file( int fd );
|
||||
|
||||
#endif /*_SYNTRANS_H*/
|
|
@ -0,0 +1,298 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* */
|
||||
static char rcsid[] =
|
||||
"$Id: util.c,v 1.9 2001/06/11 09:14:59 tsch Rel $"; /*
|
||||
* *
|
||||
* IC35 utilities: logging, errors, messages *
|
||||
* *
|
||||
*************************************************************************
|
||||
* *
|
||||
* conditional compile on NO_LOGSIM: if #defined, logging of the *
|
||||
* IC35 communications is NOT supported, default WITH logging. *
|
||||
* conditional compile on __STRICT_ANSI__: if #defined, substitute *
|
||||
* functions, which are not available with the ANSI C standard. *
|
||||
* (compilation with 'gcc -ansi ..' does #define __STRICT_ANSI__) *
|
||||
* *
|
||||
* logging #ifndef NO_LOGSIM *
|
||||
* log_init initialize logfile, logtag and loglevel *
|
||||
* log_close close logfile *
|
||||
* lprintf printf to logfile *
|
||||
* ldump dump data to logfile *
|
||||
* log_proginfo log program name, version and build info *
|
||||
* log_argsinfo log command line of program invocation *
|
||||
* (error-)messages *
|
||||
* vlmessage local: vprintf message *
|
||||
* message output and log L_MESG message *
|
||||
* error output and log L_ERROR message *
|
||||
* fatal output,log L_FATAL message and abort program *
|
||||
* _not_impl report unimplemented feature *
|
||||
* substitute functions #ifdef __STRICT_ANSI__ *
|
||||
* strncasecmp *
|
||||
* strcasecmp *
|
||||
* strdup *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include <stdio.h> /* fprintf(), .. */
|
||||
#include <stdarg.h> /* va_start(), .. */
|
||||
#include <stdlib.h> /* malloc(), free(), .. */
|
||||
#include <string.h> /* strcpy(), .. */
|
||||
#include <sys/types.h> /* size_t, .. */
|
||||
#include <sys/time.h> /* gettimeofday(), .. */
|
||||
#include <time.h> /* struct tm, time() .. */
|
||||
|
||||
#include "util.h"
|
||||
NOTUSED(rcsid)
|
||||
|
||||
|
||||
/* logging
|
||||
* -------
|
||||
* format of log entries:
|
||||
* hh:mm:ss.mmmm tag level message
|
||||
* hh:mm:ss.mmmm tag level addr hex... char...
|
||||
*/
|
||||
#ifndef NO_LOGSIM
|
||||
static char * logfname = NULL;
|
||||
static FILE * logfp = NULL;
|
||||
static char * logtag = "";
|
||||
static int loglevel = L_DEBUG;
|
||||
|
||||
static int
|
||||
_log_init( char * l_fname, char * l_tag, int level )
|
||||
{
|
||||
if ( l_fname && *l_fname ) {
|
||||
logfp = fopen( logfname = l_fname, "w" );
|
||||
if ( logfp == NULL )
|
||||
return ERR;
|
||||
}
|
||||
if ( l_tag && *l_tag )
|
||||
logtag = l_tag;
|
||||
if ( level )
|
||||
loglevel = level;
|
||||
return OK;
|
||||
}
|
||||
void
|
||||
log_init( char * l_fname, char * l_tag, int level )
|
||||
{
|
||||
if ( _log_init( l_fname, l_tag, level ) != OK )
|
||||
fatal( "cannot open logfile: %s", l_fname );
|
||||
}
|
||||
void
|
||||
log_close( void )
|
||||
{
|
||||
if ( logfp ) {
|
||||
fclose( logfp );
|
||||
logfp = NULL;
|
||||
}
|
||||
}
|
||||
static char *
|
||||
ltstamp( void )
|
||||
{
|
||||
static char timestamp[16];
|
||||
struct timeval tv;
|
||||
struct tm * ptm;
|
||||
|
||||
gettimeofday( &tv, NULL );
|
||||
ptm = localtime( (time_t*)&tv.tv_sec );
|
||||
sprintf( timestamp, "%02d:%02d:%02d.%04d",
|
||||
ptm->tm_hour, ptm->tm_min, ptm->tm_sec,
|
||||
(int)(tv.tv_usec/100) );
|
||||
return timestamp;
|
||||
}
|
||||
static void
|
||||
vltprintf( int level, char * tstamp, const char * format, va_list argp )
|
||||
{
|
||||
if ( logfp == NULL || level > loglevel )
|
||||
return;
|
||||
fprintf( logfp, "%s %s %d ", tstamp, logtag, level );
|
||||
vfprintf( logfp, format, argp );
|
||||
fprintf( logfp, "\n" );
|
||||
}
|
||||
static void
|
||||
vlprintf( int level, const char * format, va_list argp )
|
||||
{
|
||||
vltprintf( level, ltstamp(), format, argp );
|
||||
}
|
||||
void
|
||||
lprintf( int level, const char * format, ... )
|
||||
{
|
||||
va_list argp;
|
||||
|
||||
va_start( argp, format );
|
||||
vlprintf( level, format, argp );
|
||||
va_end( argp );
|
||||
}
|
||||
static void
|
||||
ltprintf( int level, char * tstamp, const char * format, ... )
|
||||
{
|
||||
va_list argp;
|
||||
|
||||
va_start( argp, format );
|
||||
vltprintf( level, tstamp, format, argp );
|
||||
va_end( argp );
|
||||
}
|
||||
void
|
||||
ldump( int level, void * data, size_t dlen, const char * format, ... )
|
||||
{
|
||||
va_list argp;
|
||||
char * tstamp;
|
||||
int i;
|
||||
uchar *dptr, *dend;
|
||||
char *hdptr, hdump[5+3*16+1];
|
||||
char *cdptr, cdump[16+1];
|
||||
|
||||
tstamp = ltstamp();
|
||||
va_start( argp, format );
|
||||
vltprintf( level, tstamp, format, argp );
|
||||
va_end( argp );
|
||||
dend = (dptr = (uchar*)data) + dlen;
|
||||
while ( dptr < dend ) {
|
||||
hdptr = hdump;
|
||||
cdptr = memset( cdump, 0, sizeof(cdump) );
|
||||
sprintf( hdptr, "%04lX:", dptr - (uchar*)data ); hdptr += 5;
|
||||
for ( i = 0; i < 16 && dptr < dend; ++i, ++dptr ) {
|
||||
sprintf( hdptr, " %02X", *dptr ); hdptr += 3;
|
||||
*cdptr++ = ' ' < *dptr && *dptr <= '~' ? *dptr : '.';
|
||||
}
|
||||
ltprintf( level, tstamp, " %-53s %s", hdump, cdump );
|
||||
}
|
||||
}
|
||||
|
||||
/* log program info
|
||||
* ----------------
|
||||
* current date and time, as log has only hh:mm:ss.mmmm stamps
|
||||
* program name, version and release date
|
||||
* build date+time, user, host
|
||||
*/
|
||||
void
|
||||
log_proginfo( char * name, char * version, char * date, char * bldinfo )
|
||||
{
|
||||
time_t tnow;
|
||||
struct tm * ptm;
|
||||
char dtime[24+1]; /* yyyy-mm-dd hh:mm:ss zzzz */
|
||||
|
||||
tnow = time( NULL );
|
||||
ptm = localtime( &tnow );
|
||||
strftime( dtime, sizeof(dtime), "%Y-%m-%d %T %Z", ptm );
|
||||
lprintf( L_MESG, "%s", dtime );
|
||||
lprintf( L_MESG, "%s %s (%s)", name, version, date );
|
||||
lprintf( L_MESG, "%s", bldinfo );
|
||||
}
|
||||
|
||||
/* log command line
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
log_argsinfo( int argc, char ** argv )
|
||||
{
|
||||
int i, len;
|
||||
char * cmdline;
|
||||
|
||||
for ( i = len = 0; i < argc; ++i )
|
||||
len += strlen( argv[i] ) + 1;
|
||||
if ( (cmdline = malloc( len )) != NULL ) {
|
||||
strcpy( cmdline, argv[0] );
|
||||
for ( i = 1; i < argc; ++i )
|
||||
strcat( strcat( cmdline, " " ), argv[i] );
|
||||
lprintf( L_MESG, "cmd: %s", cmdline );
|
||||
free( cmdline );
|
||||
}
|
||||
}
|
||||
#endif /*NO_LOGSIM*/
|
||||
|
||||
|
||||
/* output (error-)message
|
||||
* ----------------------
|
||||
*/
|
||||
static void
|
||||
vlmessage( int level, const char * format, va_list argp )
|
||||
{
|
||||
vfprintf( stderr, format, argp );
|
||||
fprintf( stderr, "\n" );
|
||||
#ifndef NO_LOGSIM
|
||||
vlprintf( level, format, argp );
|
||||
#endif
|
||||
}
|
||||
void
|
||||
message( const char * format, ... )
|
||||
{
|
||||
va_list argp;
|
||||
|
||||
va_start( argp, format );
|
||||
vlmessage( L_MESG, format, argp );
|
||||
va_end( argp );
|
||||
}
|
||||
void
|
||||
error( const char * format, ... )
|
||||
{
|
||||
va_list argp;
|
||||
|
||||
va_start( argp, format );
|
||||
vlmessage( L_ERROR, format, argp );
|
||||
va_end( argp );
|
||||
}
|
||||
void
|
||||
fatal( const char * format, ... )
|
||||
{
|
||||
va_list argp;
|
||||
|
||||
va_start( argp, format );
|
||||
vlmessage( L_FATAL, format, argp );
|
||||
va_end( argp );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
/* report unimplemented feature
|
||||
* ----------------------------
|
||||
*/
|
||||
int
|
||||
_not_impl( char * feature )
|
||||
{
|
||||
error( "%s NOT IMPLEMENTED", feature );
|
||||
return ERR;
|
||||
}
|
||||
|
||||
|
||||
/* substitute functions
|
||||
* --------------------
|
||||
* the functions below are unavailable on compilation with "-ansi",
|
||||
* which #defines __STRICT_ANSI__
|
||||
*/
|
||||
#ifdef __STRICT_ANSI__
|
||||
#include <ctype.h> /* toupper() */
|
||||
|
||||
int
|
||||
strncasecmp( const char * s1, const char * s2, size_t n )
|
||||
{
|
||||
int cmp;
|
||||
|
||||
for ( ; n; ++s1, ++s2, --n ) {
|
||||
cmp = toupper(*s1) - toupper(*s2);
|
||||
if ( cmp != 0 )
|
||||
return cmp;
|
||||
if ( !( *s1 && *s2 ) )
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
strcasecmp( const char * s1, const char * s2 )
|
||||
{
|
||||
size_t n;
|
||||
|
||||
if ( (n = strlen(s1)) < strlen(s2) )
|
||||
n = strlen(s2);
|
||||
return strncasecmp( s1, s2, n );
|
||||
}
|
||||
|
||||
char *
|
||||
strdup( const char * s )
|
||||
{
|
||||
char * nstr;
|
||||
|
||||
if ( (nstr = malloc( strlen(s) + 1 )) != NULL )
|
||||
strcpy( nstr, s );
|
||||
return nstr;
|
||||
}
|
||||
#endif /*__STRICT_ANSI__*/
|
|
@ -0,0 +1,96 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* *
|
||||
* $Id: util.h,v 1.9 2001/03/02 02:08:32 tsch Rel $ *
|
||||
* *
|
||||
* header for IC35 utilities *
|
||||
* *
|
||||
************************************************************************/
|
||||
#ifndef _UTIL_H
|
||||
#define _UTIL_H 1
|
||||
|
||||
#include <sys/types.h> /* size_t */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h> /* NO_LOGSIM */
|
||||
#endif
|
||||
|
||||
|
||||
#define NOTUSED(x) static void _nu_ ## x( void ) \
|
||||
{ (void)( _nu_ ## x + 0 ); (void)( x + 0 ); }
|
||||
#define UNUSED(x) (void)( x + 0 ) /* LINT: unused function arg */
|
||||
|
||||
#if !defined(OK) || !defined(ERR)
|
||||
# define OK 0
|
||||
# define ERR -1
|
||||
#endif
|
||||
#if !defined(TRUE) || !defined(FALSE)
|
||||
# define TRUE 1
|
||||
# define FALSE 0
|
||||
#endif
|
||||
|
||||
#define bool int
|
||||
#define uchar unsigned char
|
||||
#define ushort unsigned short
|
||||
#define uint unsigned int
|
||||
#define ulong unsigned long
|
||||
|
||||
#if !defined(min) || !defined(max)
|
||||
# define min(a,b) ( (a) < (b) ? (a) : (b) )
|
||||
# define max(a,b) ( (a) < (b) ? (b) : (a) )
|
||||
#endif
|
||||
#ifndef offsetof
|
||||
# define offsetof(type,fld) (size_t)&( ((type*)0)->fld )
|
||||
#endif
|
||||
#ifndef alenof
|
||||
# define alenof(array) ( sizeof(array) / sizeof(array[0]) )
|
||||
#endif
|
||||
|
||||
|
||||
/* log levels */
|
||||
#define L_FATAL 0 /* program will end, SYSLOG LOG_ALERT */
|
||||
#define L_ERROR 1 /* action should be taken, SYSLOG LOG_ERR */
|
||||
#define L_AUDIT 2 /* serious info, SYSLOG LOG_NOTICE */
|
||||
#define L_WARN 3 /* something goes wrong ? */
|
||||
#define L_MESG 4 /* info - level 1 */
|
||||
#define L_INFO 5 /* info - level 2 */
|
||||
#define L_NOISE 6 /* info - level 3 */
|
||||
#define L_DEBUG 7 /* debugging, very noisy */
|
||||
|
||||
#ifdef NO_LOGSIM /* log and com-simulation disabled */
|
||||
#define LOG_INIT(args)
|
||||
#define LOG_CLOSE(args)
|
||||
#define LPRINTF(args)
|
||||
#define LDUMP(args)
|
||||
#define LOG_PROGINFO(args)
|
||||
#define LOG_ARGSINFO(args)
|
||||
#else /*!NO_LOGSIM*/ /* log and com-simulation enabled */
|
||||
#define LOG_INIT(args) log_init args
|
||||
#define LOG_CLOSE(args) log_close args
|
||||
#define LPRINTF(args) lprintf args
|
||||
#define LDUMP(args) ldump args
|
||||
#define LOG_PROGINFO(args) log_proginfo args
|
||||
#define LOG_ARGSINFO(args) log_argsinfo args
|
||||
#endif /*NO_LOGSIM*/
|
||||
|
||||
|
||||
void log_init( char * l_fname, char * l_tag, int level );
|
||||
void log_close( void );
|
||||
void lprintf( int level, const char * format, ... );
|
||||
void ldump( int level, void * data, size_t dlen, const char * format, ... );
|
||||
void log_proginfo( char * name, char * version, char * date, char * bldinfo );
|
||||
void log_argsinfo( int argc, char ** argv );
|
||||
|
||||
void message( const char * format, ... );
|
||||
void error( const char * format, ... );
|
||||
void fatal( const char * format, ... );
|
||||
|
||||
int _not_impl( char * feature );
|
||||
|
||||
#ifdef __STRICT_ANSI__
|
||||
int strcasecmp( const char * s1, const char * s2 );
|
||||
int strncasecmp( const char * s1, const char * s2, size_t n );
|
||||
char * strdup( const char * s );
|
||||
#endif /*__STRICT_ANSI__*/
|
||||
|
||||
#endif /*_UTIL_H*/
|
|
@ -0,0 +1,722 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000,2001 Thomas Schulz *
|
||||
* */
|
||||
static char rcsid[] =
|
||||
"$Id: vcaconv.c,v 1.17 2001/02/17 20:56:49 tsch Rel $"; /*
|
||||
* *
|
||||
* vCard,vCalendar conversion *
|
||||
* *
|
||||
*************************************************************************
|
||||
* *
|
||||
* ??? is "fixme" mark: sections of code needing fixes *
|
||||
* *
|
||||
* for usage run vcaconv -h or see function usage() below. *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include <stdio.h> /* printf(), .. */
|
||||
#include <string.h> /* strcasecmp(), .. */
|
||||
#include <getopt.h> /* getopt(), optarg, .. */
|
||||
#include <ctype.h> /* isdigit() */
|
||||
#include <time.h> /* struct tm, time() .. */
|
||||
|
||||
#include "vcc.h" /* VObject, .. */
|
||||
#include "syntrans.h" /* FILEADDR, .. */
|
||||
#include "dataio.h" /* ic35addr_to_vcard()..*/
|
||||
#include "vcutil.h" /* vca_type(), .. */
|
||||
#include "util.h" /* uchar, .. */
|
||||
NOTUSED(rcsid)
|
||||
|
||||
|
||||
extern char * pkgvers; /* these are all */
|
||||
extern char * pkgdate; /* in versinfo.c, which is */
|
||||
extern char * bldinfo; /* auto-generated by Makefile */
|
||||
|
||||
|
||||
/* get VObject's string value (dupStr()'d)
|
||||
* --------------------------
|
||||
*/
|
||||
static char *
|
||||
dupStrValue( VObject * vobj, const char * id )
|
||||
{
|
||||
char * strval;
|
||||
|
||||
if ( (strval = dupStringValue( vobj, id )) == NULL )
|
||||
strval = dupStr( "", 0 );
|
||||
return strval;
|
||||
}
|
||||
|
||||
|
||||
/* ==================================================== */
|
||||
/* parse VObject list from vCard/vCal file */
|
||||
/* ==================================================== */
|
||||
|
||||
/* parse error handler
|
||||
* -------------------
|
||||
*/
|
||||
static bool _vca_error;
|
||||
static char * _vca_fname;
|
||||
|
||||
static void
|
||||
_vca_errmsg( char * msg ) /* mimeErrorHandler for Parse_MIME_FromFile() */
|
||||
{
|
||||
error( "vcafile \"%s\": %s", _vca_fname, msg );
|
||||
_vca_error = TRUE;
|
||||
}
|
||||
|
||||
/* parse vCard,vCal file
|
||||
* ---------------------
|
||||
*/
|
||||
static VObject *
|
||||
vca_parse( char * fname )
|
||||
{
|
||||
FILE * infp;
|
||||
VObject * vlist;
|
||||
|
||||
if ( fname && *fname && strcmp( fname, "-" ) != 0 ) {
|
||||
if ( (infp = fopen( fname, "r" )) == NULL ) {
|
||||
error( "cannot open vcafile: %s", fname );
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
fname = "(stdin)";
|
||||
infp = stdin;
|
||||
}
|
||||
registerMimeErrorHandler( _vca_errmsg );
|
||||
_vca_error = FALSE;
|
||||
_vca_fname = fname;
|
||||
vlist = Parse_MIME_FromFile( infp );
|
||||
if ( _vca_error ) {
|
||||
cleanVObjects( vlist );
|
||||
vlist = NULL;
|
||||
}
|
||||
if ( infp != stdin )
|
||||
fclose( infp );
|
||||
return vlist;
|
||||
}
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* sort list of VObjects */
|
||||
/* ==================================== */
|
||||
|
||||
/* compare property of VObjects
|
||||
* ----------------------------
|
||||
*/
|
||||
static int
|
||||
_compare_vprop( const char * id, VObject * vobj1, VObject * vobj2 )
|
||||
{
|
||||
int cmp;
|
||||
|
||||
if ( !( id && *id )
|
||||
|| (vobj1 == NULL && vobj2 == NULL) )
|
||||
return 0;
|
||||
if ( vobj1 == NULL )
|
||||
return -1;
|
||||
if ( vobj2 == NULL )
|
||||
return +1;
|
||||
|
||||
if ( strcasecmp( id, VCNameProp ) == 0 ) {
|
||||
VObject * vprop1 = isAPropertyOf( vobj1, id );
|
||||
VObject * vprop2 = isAPropertyOf( vobj2, id );
|
||||
if ( (cmp = _compare_vprop( VCFamilyNameProp, vprop1, vprop2 )) != 0 )
|
||||
return cmp;
|
||||
else
|
||||
return _compare_vprop( VCGivenNameProp, vprop1, vprop2 );
|
||||
}
|
||||
if ( strcasecmp( id, XPilotIdProp ) == 0 ) {
|
||||
ulong val1 = LongValue( vobj1, id );
|
||||
ulong val2 = LongValue( vobj2, id );
|
||||
if ( val1 < val2 )
|
||||
return -1;
|
||||
if ( val1 > val2 )
|
||||
return +1;
|
||||
return 0;
|
||||
}
|
||||
if ( strcasecmp( id, VCLastModifiedProp ) == 0
|
||||
|| strcasecmp( id, VCLastRevisedProp ) == 0
|
||||
|| strcasecmp( id, VCDTstartProp ) == 0
|
||||
|| strcasecmp( id, VCDTendProp ) == 0 ) {
|
||||
time_t time1 = isodtime_to_unixtime( vobj1, id );
|
||||
time_t time2 = isodtime_to_unixtime( vobj2, id );
|
||||
if ( time1 < time2 )
|
||||
return -1;
|
||||
if ( time1 > time2 )
|
||||
return +1;
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
char * str1 = dupStrValue( vobj1, id );
|
||||
char * str2 = dupStrValue( vobj2, id );
|
||||
cmp = strcmp( str1, str2 );
|
||||
deleteStr( str1 );
|
||||
deleteStr( str2 );
|
||||
return cmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* compare VObjects for sorting
|
||||
* ----------------------------
|
||||
*/
|
||||
static int
|
||||
_compare_vobj( const void * pvobj1, const void * pvobj2 )
|
||||
{
|
||||
VObject * vobj1 = *(VObject**)pvobj1;
|
||||
VObject * vobj2 = *(VObject**)pvobj2;
|
||||
int type1 = vca_type( vobj1 );
|
||||
int type2 = vca_type( vobj2 );
|
||||
int cmp;
|
||||
|
||||
if ( type1 < type2 )
|
||||
return -1;
|
||||
else if ( type1 > type2 )
|
||||
return +1;
|
||||
|
||||
switch ( type1 ) {
|
||||
case VCARD: /* addr: Name, REV, */
|
||||
if ( (cmp = _compare_vprop( VCNameProp, vobj1, vobj2 )) != 0 )
|
||||
return cmp;
|
||||
if ( (cmp = _compare_vprop( VCLastRevisedProp, vobj1, vobj2 )) != 0 )
|
||||
return cmp;
|
||||
break;
|
||||
case VMEMO: /* memo: subject, */
|
||||
if ( (cmp = _compare_vprop( VCSummaryProp, vobj1, vobj2 )) != 0 )
|
||||
return cmp;
|
||||
if ( (cmp = _compare_vprop( VCLastModifiedProp, vobj1, vobj2 )) != 0 )
|
||||
return cmp;
|
||||
break;
|
||||
case VEVENT: /* vcal.sched: DTSTART, subject, rev, */
|
||||
if ( (cmp = _compare_vprop( VCDTstartProp, vobj1, vobj2 )) != 0 )
|
||||
return cmp;
|
||||
if ( (cmp = _compare_vprop( VCSummaryProp, vobj1, vobj2 )) != 0 )
|
||||
return cmp;
|
||||
if ( (cmp = _compare_vprop( VCLastModifiedProp, vobj1, vobj2 )) != 0 )
|
||||
return cmp;
|
||||
break;
|
||||
case VTODO: /* vcal.todo: DTSTART, subject, rev, */
|
||||
if ( (cmp = _compare_vprop( VCDueProp, vobj1, vobj2 )) != 0 )
|
||||
return cmp;
|
||||
if ( (cmp = _compare_vprop( VCSummaryProp, vobj1, vobj2 )) != 0 )
|
||||
return cmp;
|
||||
if ( (cmp = _compare_vprop( VCLastModifiedProp, vobj1, vobj2 )) != 0 )
|
||||
return cmp;
|
||||
break;
|
||||
case VCAL: /* multiple vCAL ? VERSION, PRODID */
|
||||
if ( (cmp = _compare_vprop( VCVersionProp, vobj1, vobj2 )) != 0 )
|
||||
return cmp;
|
||||
return _compare_vprop( VCProdIdProp, vobj1, vobj2 );
|
||||
}
|
||||
/* same with above compares: X-PILOTID, UID */
|
||||
if ( (cmp = _compare_vprop( XPilotIdProp, vobj1, vobj2 )) != 0 )
|
||||
return cmp;
|
||||
return _compare_vprop( VCUniqueStringProp, vobj1, vobj2 );
|
||||
}
|
||||
|
||||
/* sort VObject's property list
|
||||
* ----------------------------
|
||||
*/
|
||||
struct propseq {
|
||||
int seq;
|
||||
char * id;
|
||||
};
|
||||
static struct propseq _propseq[] = {
|
||||
{ -6, VCNameProp },
|
||||
{ -5, VCDTstartProp },
|
||||
{ -4, VCDTendProp },
|
||||
{ -3, VCDueProp },
|
||||
{ -2, VCSummaryProp },
|
||||
{ -1, VCDescriptionProp },
|
||||
{ +1, VCCategoriesProp },
|
||||
{ +2, VCDCreatedProp },
|
||||
{ +3, VCLastModifiedProp },
|
||||
{ +4, VCLastRevisedProp },
|
||||
{ +5, VCUniqueStringProp },
|
||||
{ +6, XPilotIdProp },
|
||||
{ +7, XPilotStatusProp },
|
||||
{ 0, NULL }
|
||||
};
|
||||
static int
|
||||
_propid_seq( const char * id )
|
||||
{
|
||||
struct propseq * pseq;
|
||||
|
||||
for ( pseq = _propseq; pseq->id; ++pseq )
|
||||
if ( strcasecmp( id, pseq->id ) == 0 )
|
||||
return pseq->seq;
|
||||
return 0;
|
||||
}
|
||||
static int /* compare properties for sorting */
|
||||
_compare_props( const void * pvprop1, const void * pvprop2 )
|
||||
{
|
||||
VObject * vprop1 = *(VObject**)pvprop1;
|
||||
VObject * vprop2 = *(VObject**)pvprop2;
|
||||
const char *id1, *id2;
|
||||
int seq1, seq2;
|
||||
char *str1, *str2;
|
||||
int cmp;
|
||||
|
||||
seq1 = _propid_seq( id1 = vObjectName( vprop1 ) );
|
||||
seq2 = _propid_seq( id2 = vObjectName( vprop2 ) );
|
||||
if ( seq1 < seq2 )
|
||||
return -1;
|
||||
if ( seq1 > seq2 )
|
||||
return +1;
|
||||
if ( (cmp = strcasecmp( id1, id2 )) == 0 ) {
|
||||
cmp = strcmp( str1 = dupStrValue( vprop1, NULL ),
|
||||
str2 = dupStrValue( vprop2, NULL ) );
|
||||
deleteStr( str1 );
|
||||
deleteStr( str2 );
|
||||
}
|
||||
return cmp;
|
||||
}
|
||||
static void /* sort VObject's property list */
|
||||
vobjsort( VObject * vobj )
|
||||
{
|
||||
size_t n, i;
|
||||
VObjectIterator iter;
|
||||
VObject ** vproptab;
|
||||
VObject * vprop;
|
||||
|
||||
n = 0; /* count number of properties, alloc table */
|
||||
initPropIterator( &iter, vobj );
|
||||
while ( moreIteration( &iter ) ) {
|
||||
(void)nextVObject( &iter );
|
||||
++n;
|
||||
}
|
||||
vproptab = malloc ( n * sizeof(vproptab[0]) );
|
||||
if ( vproptab == NULL )
|
||||
return;
|
||||
/* build table of property ptrs and sort */
|
||||
i = 0;
|
||||
initPropIterator( &iter, vobj );
|
||||
while ( i < n && moreIteration( &iter ) )
|
||||
vproptab[i++] = nextVObject( &iter );
|
||||
qsort( vproptab, n, sizeof(vproptab[0]), _compare_props );
|
||||
/* rebuild property list in sorted sequ */
|
||||
for ( i = 0; i < n; ++i )
|
||||
if ( (vprop = delProp( vobj, vproptab[i] )) != NULL )
|
||||
addVObjectProp( vobj, vprop );
|
||||
|
||||
free( vproptab );
|
||||
}
|
||||
|
||||
/* sort VObject list
|
||||
* -----------------
|
||||
*/
|
||||
static int
|
||||
vca_sort( VObject ** vlist )
|
||||
{
|
||||
size_t n, i;
|
||||
VObject * vcal;
|
||||
VObject ** vobjtab;
|
||||
VObject * vobj;
|
||||
VObjectIterator iter;
|
||||
|
||||
/* count number of VObjects, alloc table */
|
||||
n = 0; vcal = NULL;
|
||||
for ( vobj = *vlist; vobj !=NULL; vobj = nextVObjectInList( vobj ) ) {
|
||||
++n;
|
||||
if ( vca_type( vobj ) == VCAL ) {
|
||||
if ( vcal == NULL )
|
||||
vcal = vobj;
|
||||
initPropIterator( &iter, vobj );
|
||||
while ( moreIteration( &iter ) ) {
|
||||
(void)nextVObject( &iter );
|
||||
++n;
|
||||
}
|
||||
}
|
||||
}
|
||||
vobjtab = malloc ( n * sizeof(vobjtab[0]) );
|
||||
if ( vobjtab == NULL )
|
||||
return ERR;
|
||||
|
||||
/* build table of VObject ptrs and sort */
|
||||
i = 0;
|
||||
for ( vobj = *vlist; vobj !=NULL; vobj = nextVObjectInList( vobj ) ) {
|
||||
vobjtab[i++] = vobj;
|
||||
if ( vca_type( vobj ) == VCAL ) {
|
||||
initPropIterator( &iter, vobj );
|
||||
while ( moreIteration( &iter ) )
|
||||
vobjtab[i++] = nextVObject( &iter );
|
||||
}
|
||||
}
|
||||
qsort( vobjtab, n, sizeof(vobjtab[0]), _compare_vobj );
|
||||
|
||||
/* rebuild VObject list in sorted sequ */
|
||||
for ( i = 0; i < n; ++i ) {
|
||||
vobj = vobjtab[i];
|
||||
switch ( vca_type( vobj ) ) {
|
||||
case VCARD:
|
||||
case VMEMO:
|
||||
vobjsort( vobj ); /* sort VObject's property list */
|
||||
/* fall thru */
|
||||
case VCAL:
|
||||
vobj = delList( vlist, vobj );
|
||||
if ( vobj != NULL )
|
||||
addList( vlist, vobj );
|
||||
break;
|
||||
case VEVENT:
|
||||
case VTODO:
|
||||
if ( vcal == NULL )
|
||||
break;
|
||||
vobjsort( vobj ); /* sort VObject's property list */
|
||||
vobj = delProp( vcal, vobj );
|
||||
if ( vobj != NULL )
|
||||
addVObjectProp( vcal, vobj );
|
||||
break;
|
||||
}
|
||||
}
|
||||
free( vobjtab );
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/* ==================================== */
|
||||
/* create telbook for handy */
|
||||
/* ==================================== */
|
||||
|
||||
static bool
|
||||
hasCategory( VObject * vobj, char * wanted )
|
||||
{
|
||||
char * categories;
|
||||
char * category;
|
||||
|
||||
if ( !( vobj && wanted && *wanted ) )
|
||||
return FALSE;
|
||||
categories = dupStrValue( vobj, VCCategoriesProp );
|
||||
for ( category = strtok( categories, ";" );
|
||||
category; category = strtok( NULL, ";" ) )
|
||||
if ( strcasecmp( category, wanted ) == 0 )
|
||||
break;
|
||||
deleteStr( categories );
|
||||
return (bool)( category != NULL );
|
||||
}
|
||||
static char *
|
||||
NameValue( VObject * vobj, const char * type )
|
||||
{
|
||||
VObject * vprop;
|
||||
char * namestr;
|
||||
|
||||
if ( !( vobj && type && *type )
|
||||
|| (vprop = isAPropertyOf( vobj, VCNameProp )) == NULL )
|
||||
return NULL;
|
||||
if ( (namestr = dupStrValue( vprop, type )) && *namestr )
|
||||
return namestr;
|
||||
deleteStr( namestr );
|
||||
if ( (namestr = dupStrValue( vprop, VCFamilyNameProp )) && *namestr )
|
||||
return namestr;
|
||||
deleteStr( namestr );
|
||||
return dupStrValue( vprop, VCGivenNameProp );
|
||||
}
|
||||
static char *
|
||||
TelnoValue( VObject * vobj, const char * type )
|
||||
{
|
||||
VObjectIterator iter, teliter;
|
||||
VObject * vprop;
|
||||
VObject * teltype;
|
||||
VObject * telpref;
|
||||
VObject * teldflt;
|
||||
char * telstr, *src, *dst;
|
||||
|
||||
if ( !( vobj && type && *type ) )
|
||||
return NULL;
|
||||
teltype = telpref = teldflt = NULL;
|
||||
initPropIterator( &iter, vobj );
|
||||
while ( moreIteration( &iter ) ) {
|
||||
vprop = nextVObject( &iter );
|
||||
if ( strcmp( vObjectName( vprop ), VCTelephoneProp ) != 0 )
|
||||
continue;
|
||||
if ( teltype == NULL
|
||||
&& isAPropertyOf( vprop, type ) )
|
||||
teltype = vprop;
|
||||
if ( telpref == NULL
|
||||
&& isAPropertyOf( vprop, VCPreferredProp ) )
|
||||
telpref = vprop;
|
||||
initPropIterator( &teliter, vprop );
|
||||
if ( teldflt == NULL
|
||||
&& ! moreIteration( &teliter ) )
|
||||
teldflt = vprop;
|
||||
}
|
||||
telstr = dupStrValue( teltype ? teltype :
|
||||
( telpref ? telpref : teldflt ), NULL );
|
||||
if ( (dst = src = telstr) && *telstr ) {
|
||||
do {
|
||||
if ( (src == telstr && *src == '+') /* international +49 */
|
||||
|| isdigit( *src ) ) /* skip separators, because */
|
||||
*dst++ = *src; /* handy does not like them */
|
||||
} while ( *src++ );
|
||||
}
|
||||
return telstr;
|
||||
}
|
||||
|
||||
/*
|
||||
* special categories for handy telbook:
|
||||
* S35SIM pre-installed entries from S35i
|
||||
* HANDY created for import into handy
|
||||
* special conversions
|
||||
* - vCards for handy have only VCNameProp.VCFamilyNameProp and
|
||||
* VCTelephoneProp with VCCellularProp attribute
|
||||
* for category "Business" and other derive from VCFamilyNameProp
|
||||
* for category "Personal" derive from VCGivenNameProp
|
||||
* - for multiple telnos make multiple vCards with append to name:
|
||||
* Business: append none, "-priv", "-mobil" for WORK, HOME, CELL
|
||||
* Personal: append "-Buero", none, "-mobil" for WORK, HOME, CELL
|
||||
* - for category "Personal" make "VIP" entries by appending "!"
|
||||
*/
|
||||
static VObject *
|
||||
new_handycard( char * name, char * suffix, char * telno )
|
||||
{
|
||||
VObject * vcard;
|
||||
char namebuff[18+1];
|
||||
time_t tnow;
|
||||
struct tm * ptm;
|
||||
char isodtime[24];
|
||||
|
||||
if ( !(name && *name)
|
||||
|| !(telno && *telno)
|
||||
|| (vcard = newVObject( VCCardProp )) == NULL )
|
||||
return NULL;
|
||||
|
||||
strncat( strcpy( namebuff, "" ), name, sizeof(namebuff)-1 );
|
||||
if ( suffix && *suffix ) {
|
||||
namebuff[ sizeof(namebuff)-1 - 4 ] = '\0';
|
||||
strncat( namebuff, suffix, sizeof(namebuff)-1 - strlen(namebuff) );
|
||||
}
|
||||
addPropValue( vcard, VCFullNameProp, namebuff );
|
||||
addPropValue( addProp( vcard, VCNameProp ), VCFamilyNameProp, namebuff );
|
||||
|
||||
addProp( addPropValue( vcard, VCTelephoneProp, telno ), VCCellularProp );
|
||||
addPropValue( vcard, VCCategoriesProp, "HANDY" );
|
||||
|
||||
tnow = time( NULL );
|
||||
ptm = localtime( &tnow );
|
||||
strftime( isodtime, sizeof(isodtime), "%Y-%m-%dT%H:%M:%S", ptm );
|
||||
addPropValue( vcard, VCLastRevisedProp, isodtime );
|
||||
|
||||
return vcard;
|
||||
}
|
||||
static int
|
||||
vcard_to_handy( VObject ** vlist )
|
||||
{
|
||||
VObject * vobj;
|
||||
VObject * vcard;
|
||||
VObject * vdel;
|
||||
VObject * handylist;
|
||||
VObject * vnext;
|
||||
char * name, *tel1, *tel2;
|
||||
|
||||
vdel = handylist = NULL;
|
||||
for ( vobj = *vlist; vobj !=NULL; vobj = nextVObjectInList( vobj ) ) {
|
||||
if ( vca_type( vobj ) != VCARD )
|
||||
continue;
|
||||
if ( hasCategory( vobj, "HANDY" ) ) {
|
||||
if ( vdel )
|
||||
cleanVObject( vdel );
|
||||
vdel = delList( vlist, vobj );
|
||||
continue;
|
||||
}
|
||||
if ( hasCategory( vobj, "NOTHANDY" ) )
|
||||
continue;
|
||||
|
||||
if ( hasCategory( vobj, "S35SIM" ) ) {
|
||||
name = NameValue( vobj, VCGivenNameProp );
|
||||
if ( (tel1 = TelnoValue( vobj, VCCellularProp )) && *tel1
|
||||
&& (vcard = new_handycard( name, NULL, tel1 )) != NULL )
|
||||
addList( &handylist, vcard );
|
||||
deleteStr( tel1 );
|
||||
deleteStr( name );
|
||||
|
||||
} else if ( hasCategory( vobj, "Personal" ) ) {
|
||||
name = NameValue( vobj, VCGivenNameProp );
|
||||
if ( (tel1 = TelnoValue( vobj, VCHomeProp )) && *tel1
|
||||
&& (vcard = new_handycard( name, "!", tel1 )) != NULL )
|
||||
addList( &handylist, vcard );
|
||||
|
||||
if ( (tel2 = TelnoValue( vobj, VCWorkProp )) && *tel2
|
||||
&& strcmp( tel1, tel2 ) != 0
|
||||
&& (vcard = new_handycard( name, "-Büro!", tel2 )) != NULL )
|
||||
addList( &handylist, vcard );
|
||||
deleteStr( tel2 );
|
||||
|
||||
if ( (tel2 = TelnoValue( vobj, VCCellularProp )) && *tel2
|
||||
&& strcmp( tel1, tel2 ) != 0
|
||||
&& (vcard = new_handycard( name, "-mobil!", tel2 )) != NULL )
|
||||
addList( &handylist, vcard );
|
||||
deleteStr( tel2 );
|
||||
deleteStr( tel1 );
|
||||
deleteStr( name );
|
||||
|
||||
} else { /* Business etc. */
|
||||
name = NameValue( vobj, VCFamilyNameProp );
|
||||
if ( (tel1 = TelnoValue( vobj, VCWorkProp )) && *tel1
|
||||
&& (vcard = new_handycard( name, NULL, tel1 )) != NULL )
|
||||
addList( &handylist, vcard );
|
||||
|
||||
if ( (tel2 = TelnoValue( vobj, VCHomeProp )) && *tel2
|
||||
&& strcmp( tel1, tel2 ) != 0
|
||||
&& (vcard = new_handycard( name, "-priv", tel2 )) != NULL )
|
||||
addList( &handylist, vcard );
|
||||
deleteStr( tel2 );
|
||||
|
||||
if ( (tel2 = TelnoValue( vobj, VCCellularProp )) && *tel2
|
||||
&& strcmp( tel1, tel2 ) != 0
|
||||
&& (vcard = new_handycard( name, "-mobil", tel2 )) != NULL )
|
||||
addList( &handylist, vcard );
|
||||
deleteStr( tel2 );
|
||||
deleteStr( tel1 );
|
||||
deleteStr( name );
|
||||
}
|
||||
}
|
||||
if ( vdel )
|
||||
cleanVObject( vdel );
|
||||
|
||||
vobj = handylist;
|
||||
while ( vobj ) {
|
||||
vnext = nextVObjectInList( vobj );
|
||||
addList( vlist, vobj );
|
||||
vobj = vnext;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------- M A I N - program ----------------------------- */
|
||||
static void
|
||||
versinfo( void )
|
||||
{
|
||||
printf( "vCard/vCalendar converter %s (%s)\n", pkgvers, pkgdate );
|
||||
printf( "%s\n", bldinfo );
|
||||
printf(
|
||||
"Copyright (C) 2000,2001 Thomas Schulz\n"
|
||||
"This is free software; see the GNU General Public Licence version 2 in\n"
|
||||
"the file named COPYING for copying conditions. There is NO warranty.\n"
|
||||
);
|
||||
}
|
||||
static void
|
||||
usage( void )
|
||||
{
|
||||
static char * usetext[] = {
|
||||
"usage:",
|
||||
" vcaconv bin2vca binfile vcafile",
|
||||
" convert IC35 binary data to vCard,vCalendar format",
|
||||
" vcaconv bin2txt binfile txtfile",
|
||||
" convert IC35 binary data to plain text format",
|
||||
" vcaconv vca2bin vcafile binfile",
|
||||
" convert vCard,vCalendar file to IC35 binary data",
|
||||
" vcaconv prvca vcafile",
|
||||
" pretty print vCard/vCalendar format 'vcafile'",
|
||||
" vcaconv sortvca vcafile",
|
||||
" sort vCard,vCalendar file to standard output",
|
||||
" vcaconv imphandy vcafile",
|
||||
" create vCards in HANDY category for upload to mobile phone",
|
||||
" if inputfile or outputfile is absent or -, standard input",
|
||||
" or standard output will be used",
|
||||
"options:",
|
||||
" -V --version show version information and exit",
|
||||
" -h --help show this help and exit",
|
||||
NULL
|
||||
};
|
||||
char ** lptr;
|
||||
|
||||
for ( lptr = usetext; *lptr != NULL; ++lptr )
|
||||
printf( "%s\n", *lptr );
|
||||
}
|
||||
|
||||
int
|
||||
main( int argc, char *argv[] )
|
||||
{
|
||||
static struct option const long_opts[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
for ( ; ; ) {
|
||||
switch ( getopt_long( argc, argv, "hV", long_opts, NULL ) ) {
|
||||
default: /* invalid option */
|
||||
fprintf( stderr, "use 'vcaconv --help' for more information\n" );
|
||||
return 1;
|
||||
case 'h': /* show Help and exit */
|
||||
usage();
|
||||
return 0;
|
||||
case 'V': /* show Version and exit */
|
||||
versinfo();
|
||||
return 0;
|
||||
case -1: /* end of options */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( argc < 2 ) {
|
||||
error( "missing conversion\n"
|
||||
"use 'vcaconv --help' for more information" );
|
||||
return 1;
|
||||
}
|
||||
if ( ( strcmp( argv[1], "bin2vca" ) == 0
|
||||
|| strcmp( argv[1], "bin2txt" ) == 0
|
||||
|| strcmp( argv[1], "vca2bin" ) == 0 )
|
||||
&& 2 <= argc && argc <= 4 ) {
|
||||
void * rec;
|
||||
|
||||
argv[1][3] = '\0'; /* split input,output format */
|
||||
if ( pim_openinp( argv[1]+0, argc >= 3 ? argv[2] : "-" ) != OK ) {
|
||||
error( "bad input format/file: %s %s\n", argv[1]+0, argv[2] );
|
||||
return 1;
|
||||
}
|
||||
if ( pim_openout( argv[1]+4, argc >= 4 ? argv[3] : "-" ) != OK ) {
|
||||
error( "bad output format/file: %s %s\n", argv[1]+4, argv[3] );
|
||||
return 1;
|
||||
}
|
||||
while ( (rec = pim_getrec( FILE_ANY )) != NULL )
|
||||
pim_putrec( rec );
|
||||
pim_close();
|
||||
|
||||
} else if ( strcmp( argv[1], "prvca" ) == 0
|
||||
&& 2 <= argc && argc <= 3 ) {
|
||||
VObject * vlist;
|
||||
VObject * vdel;
|
||||
|
||||
if ( (vlist = vca_parse( argc >= 3 ? argv[2] : "-" )) == NULL )
|
||||
return 1;
|
||||
while ( vlist ) {
|
||||
printVObject( stdout, vlist );
|
||||
vlist = nextVObjectInList( vdel = vlist );
|
||||
cleanVObject( vdel );
|
||||
}
|
||||
|
||||
} else if ( strcmp( argv[1], "sortvca" ) == 0
|
||||
&& 2 <= argc && argc <= 3 ) {
|
||||
VObject * vlist;
|
||||
VObject * vdel;
|
||||
|
||||
if ( (vlist = vca_parse( argc >= 3 ? argv[2] : "-" )) == NULL )
|
||||
return 1;
|
||||
vca_sort( &vlist );
|
||||
while ( vlist ) {
|
||||
writeVObject( stdout, vlist );
|
||||
vlist = nextVObjectInList( vdel = vlist );
|
||||
cleanVObject( vdel );
|
||||
}
|
||||
|
||||
} else if ( strcmp( argv[1], "imphandy" ) == 0
|
||||
&& 2 <= argc && argc <= 3 ) {
|
||||
VObject * vlist;
|
||||
VObject * vdel;
|
||||
|
||||
if ( (vlist = vca_parse( argc >= 3 ? argv[2] : "-" )) == NULL )
|
||||
return 1;
|
||||
vcard_to_handy( &vlist );
|
||||
while ( vlist ) {
|
||||
writeVObject( stdout, vlist );
|
||||
vlist = nextVObjectInList( vdel = vlist );
|
||||
cleanVObject( vdel );
|
||||
}
|
||||
|
||||
} else {
|
||||
error( "unknown conversion: %s\n"
|
||||
"use 'vcaconv --help' for more information", argv[1] );
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/***************************************************************************
|
||||
(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
|
||||
Business Machines Corporation and Siemens Rolm Communications Inc.
|
||||
|
||||
modified 2000 by Thomas Schulz:
|
||||
$Id: vcc.h,v 1.2 2000/11/19 18:14:45 tsch Rel $
|
||||
|
||||
For purposes of this license notice, the term Licensors shall mean,
|
||||
collectively, Apple Computer, Inc., AT&T Corp., International
|
||||
Business Machines Corporation and Siemens Rolm Communications Inc.
|
||||
The term Licensor shall mean any of the Licensors.
|
||||
|
||||
Subject to acceptance of the following conditions, permission is hereby
|
||||
granted by Licensors without the need for written agreement and without
|
||||
license or royalty fees, to use, copy, modify and distribute this
|
||||
software for any purpose.
|
||||
|
||||
The above copyright notice and the following four paragraphs must be
|
||||
reproduced in all copies of this software and any software including
|
||||
this software.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
|
||||
ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
|
||||
MODIFICATIONS.
|
||||
|
||||
IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
|
||||
INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
|
||||
OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
|
||||
EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE.
|
||||
|
||||
The software is provided with RESTRICTED RIGHTS. Use, duplication, or
|
||||
disclosure by the government are subject to restrictions set forth in
|
||||
DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __VCC_H__
|
||||
#define __VCC_H__ 1
|
||||
|
||||
#include "vobject.h"
|
||||
|
||||
|
||||
#if defined(__CPLUSPLUS__) || defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*MimeErrorHandler)(char *);
|
||||
|
||||
extern DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler);
|
||||
|
||||
extern DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len);
|
||||
extern DLLEXPORT(VObject*) Parse_MIME_FromFileName(char* fname);
|
||||
|
||||
|
||||
/* NOTE regarding Parse_MIME_FromFile
|
||||
The function above, Parse_MIME_FromFile, comes in two flavors,
|
||||
neither of which is exported from the DLL. Each version takes
|
||||
a CFile or FILE* as a parameter, neither of which can be
|
||||
passed across a DLL interface (at least that is my experience).
|
||||
If you are linking this code into your build directly then
|
||||
you may find them a more convenient API that the other flavors
|
||||
that take a file name. If you use them with the DLL LIB you
|
||||
will get a link error.
|
||||
*/
|
||||
|
||||
|
||||
#if INCLUDEMFC
|
||||
extern VObject* Parse_MIME_FromFile(CFile *file);
|
||||
#else
|
||||
extern VObject* Parse_MIME_FromFile(FILE *file);
|
||||
#endif
|
||||
|
||||
#if defined(__CPLUSPLUS__) || defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __VCC_H__ */
|
||||
|
|
@ -0,0 +1,762 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* */
|
||||
static char rcsid[] =
|
||||
"$Id: vcutil.c,v 1.44 2000/12/28 02:26:31 tsch Rel $"; /*
|
||||
* *
|
||||
* IC35 synchronize data import/export: vCard,vCalendar utilities *
|
||||
* *
|
||||
*************************************************************************
|
||||
* *
|
||||
* ??? is "fixme" mark: sections of code needing fixes *
|
||||
* *
|
||||
* vca_type determine vCard,vCal record type *
|
||||
* dupSubst substitute in string, dupStr()'d result *
|
||||
* dupSubstNL translate NL to CRLF, dupStr()'d result *
|
||||
* dupSubstCRLF translate CRLF to NL, dupStr()'d result *
|
||||
* utilities for IC35 to/from vCard,vCal *
|
||||
* clr_vobjdirty clear vCard,vCal record modified status
|
||||
* SetModtimeIfdirty modified date+time to vCard,vCal record
|
||||
* _ChangeString set property string, note if changed
|
||||
* SetProp
|
||||
* SetString
|
||||
* StringValue
|
||||
* SetLong set property long integer value
|
||||
* LongValue
|
||||
* _NoteId NOTE/DESCRIPTION for vCard/vCal
|
||||
* _NotePropsLen
|
||||
* SetNotes
|
||||
* NotesValue
|
||||
* SetNoteProp
|
||||
* NotePropValue
|
||||
* _is_stdCategory standard categories Personal,Business..
|
||||
* SetCategory
|
||||
* CategoryValue
|
||||
* SetTel set telephone HOME/WORK/CELL/FAX
|
||||
* SetEmail set Email1,Email2
|
||||
* utilities for date+time conversion *
|
||||
* isodtstr_to_unixtime
|
||||
* isodtstr_to_ymd_or_today
|
||||
* isodtime_to_unixtime
|
||||
* isodtime_to_ymd
|
||||
* isodtime_to_ymd_or_today
|
||||
* isodtime_to_hms_or_now
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include <stdio.h> /* sprintf(), .. */
|
||||
#include <stdlib.h> /* atol() */
|
||||
#include <string.h> /* strcpy(), .. */
|
||||
#include <ctype.h> /* isprint(), .. */
|
||||
#include <sys/types.h> /* size_t, .. */
|
||||
#include <time.h> /* struct tm, time() .. */
|
||||
|
||||
#include "util.h" /* bool */
|
||||
#include "dataio.h" /* newic35dt() */
|
||||
#include "vcc.h" /* VObject, .. */
|
||||
#include "vcutil.h"
|
||||
NOTUSED(rcsid);
|
||||
|
||||
|
||||
/* map vCard,vCal record name to numeric type
|
||||
* ------------------------------------------
|
||||
*/
|
||||
int
|
||||
vca_type( VObject * vobj )
|
||||
{
|
||||
const char * name;
|
||||
|
||||
if ( vobj == NULL )
|
||||
return 0;
|
||||
name = vObjectName( vobj );
|
||||
if ( strcasecmp( name, VCCardProp ) == 0 ) return VCARD;
|
||||
if ( strcasecmp( name, VCMemoProp ) == 0 ) return VMEMO;
|
||||
if ( strcasecmp( name, VCCalProp ) == 0 ) return VCAL;
|
||||
if ( strcasecmp( name, VCEventProp ) == 0 ) return VEVENT;
|
||||
if ( strcasecmp( name, VCTodoProp ) == 0 ) return VTODO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* string substitutions
|
||||
* --------------------
|
||||
*/
|
||||
/* substitutes 'new' for sub-string 'old' in 'str' */
|
||||
char * /* and returns dupStr()'sd resulting string */
|
||||
dupSubst( char * str, char * old, char * new )
|
||||
{ /* substitutes 'new' for sub-string 'old' in 'str' */
|
||||
char *match, *nstr;
|
||||
char *pdst, *psrc;
|
||||
|
||||
if ( str == NULL )
|
||||
return NULL; /* marginal .. */
|
||||
if ( ! (old && *old && new ) /* .. parameters */
|
||||
|| (match = strstr( str, old )) == NULL ) /* or no match */
|
||||
return dupStr( str, 0 );
|
||||
nstr = dupStr( "", strlen(str) + strlen(new) - strlen(old) );
|
||||
pdst = nstr; psrc = str;
|
||||
while ( *psrc )
|
||||
if ( psrc == match ) {
|
||||
strcpy( pdst, new );
|
||||
psrc += strlen( old );
|
||||
pdst += strlen( new );
|
||||
} else
|
||||
*pdst++ = *psrc++;
|
||||
return nstr;
|
||||
}
|
||||
char * /* substitute vCard,vCal NewLine with IC35 CRLF */
|
||||
dupSubstNL( char * src )
|
||||
{
|
||||
char *psrc, *dst, *pdst;
|
||||
size_t len;
|
||||
|
||||
len = strlen( src );
|
||||
for ( psrc = src; *psrc; ++psrc )
|
||||
if ( *psrc == '\n' )
|
||||
++len;
|
||||
pdst = dst = dupStr( "", len );
|
||||
psrc = src, pdst = dst;
|
||||
while ( *psrc ) {
|
||||
if ( *psrc == '\n'
|
||||
&& !( psrc > src && *(psrc-1) == '\r' ) )
|
||||
*pdst++ = '\r';
|
||||
*pdst++ = *psrc++;
|
||||
}
|
||||
*pdst = '\0';
|
||||
return dst;
|
||||
}
|
||||
char * /* substitute IC35 CRLF with vCard,vCal NewLine */
|
||||
dupSubstCRLF( char * src )
|
||||
{
|
||||
|
||||
char *dst, *pdst;
|
||||
|
||||
dst = pdst = dupStr( src, 0 );
|
||||
while ( *src )
|
||||
if ( (*pdst = *src++) != '\r' && *src != '\n' )
|
||||
++pdst;
|
||||
*pdst = '\0';
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
/* ============================================ */
|
||||
/* utilities for IC35 to/from vCard,vCal */
|
||||
/* ============================================ */
|
||||
|
||||
static bool _vobj_dirty; /* VObject changed in ic35xxx_to_vyyy() */
|
||||
static char ic35fld[511+1]; /* field buffer used by SetXxx() */
|
||||
|
||||
/* clear vCard,vCal modified status
|
||||
* --------------------------------
|
||||
*/
|
||||
void
|
||||
clr_vobjdirty( void )
|
||||
{
|
||||
_vobj_dirty = FALSE;
|
||||
}
|
||||
|
||||
/* revised date+time for vCard,vCal records
|
||||
* ----------------------------------------
|
||||
*/
|
||||
static char *
|
||||
_iso_ic35dt( const char * format )
|
||||
{
|
||||
time_t ic35dt;
|
||||
struct tm * ptm;
|
||||
static char isodtime[24];
|
||||
|
||||
ic35dt = newic35dt();
|
||||
ptm = localtime( &ic35dt );
|
||||
strftime( isodtime, sizeof(isodtime), format, ptm );
|
||||
return isodtime;
|
||||
}
|
||||
void
|
||||
SetModtimeIfdirty( VObject * vobj )
|
||||
{
|
||||
if ( ! _vobj_dirty )
|
||||
return;
|
||||
switch ( vca_type( vobj ) ) {
|
||||
case VCARD: /* yyyy-mm-ddThh:mm:ss for VCARRD */
|
||||
SetString( vobj, VCLastRevisedProp, _iso_ic35dt("%Y-%m-%dT%H:%M:%S") );
|
||||
break;
|
||||
case VEVENT:
|
||||
case VTODO: /* also create-time for VEVENT,VTODO */
|
||||
if ( ! isAPropertyOf( vobj, VCDCreatedProp ) )
|
||||
SetString( vobj, VCDCreatedProp, _iso_ic35dt("%Y%m%dT%H%M%S") );
|
||||
/* fall through */
|
||||
case VMEMO: /* yyyymmddThhmmss for VEVENT,VTODO,memo */
|
||||
SetString( vobj, VCLastModifiedProp, _iso_ic35dt("%Y%m%dT%H%M%S") );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* set,get property string value
|
||||
* -----------------------------
|
||||
* handle VObject value types StringZ, UStringZ, Integer, Long
|
||||
* determine need for QUOTED-PRINTABLE and CHARSET
|
||||
* note if property / string changed in _vobj_dirty
|
||||
*/
|
||||
static void /* set property string, check and note if changed */
|
||||
_ChangeString( VObject * vobj, char * str )
|
||||
{
|
||||
const char * oldstr;
|
||||
|
||||
switch ( vObjectValueType( vobj ) ) {
|
||||
case VCVT_STRINGZ:
|
||||
oldstr = dupStr( vObjectStringZValue( vobj ), 0 );
|
||||
break;
|
||||
case VCVT_USTRINGZ:
|
||||
oldstr = fakeCString( vObjectUStringZValue( vobj ) );
|
||||
break;
|
||||
default:
|
||||
oldstr = NULL;
|
||||
}
|
||||
if ( oldstr == NULL || strcmp( oldstr, str ) != 0 ) {
|
||||
_vobj_dirty = TRUE;
|
||||
setVObjectStringZValue( vobj, str );
|
||||
}
|
||||
deleteStr( oldstr );
|
||||
}
|
||||
VObject * /* add property if not yet there */
|
||||
SetProp( VObject * vobj, const char * id )
|
||||
{
|
||||
VObject * vprop;
|
||||
|
||||
if ( (vprop = isAPropertyOf( vobj, id )) )
|
||||
return vprop;
|
||||
_vobj_dirty = TRUE;
|
||||
return addProp( vobj, id );
|
||||
}
|
||||
void /* delete property */
|
||||
DelProp( VObject * vobj, const char * id )
|
||||
{
|
||||
VObject * vprop;
|
||||
|
||||
if ( vobj && id && *id
|
||||
&& (vprop = isAPropertyOf( vobj, id )) ) {
|
||||
vprop = delProp( vobj, vprop );
|
||||
cleanVObject( vprop );
|
||||
_vobj_dirty = TRUE;
|
||||
}
|
||||
}
|
||||
VObject * /* set string, check if need QUOTED-PRINTABLE or CHARSET */
|
||||
SetString( VObject * vobj, const char * id, char * str )
|
||||
{
|
||||
VObject * vprop;
|
||||
char * pstr;
|
||||
bool prop_charset;
|
||||
bool prop_quoted;
|
||||
VObject * vpropchars;
|
||||
|
||||
if ( !( vobj && id && *id ) )
|
||||
return NULL;
|
||||
if ( !( str && *str ) ) {
|
||||
DelProp( vobj, id );
|
||||
return NULL;
|
||||
}
|
||||
if ( (vprop = isAPropertyOf( vobj, id )) == NULL )
|
||||
vprop = addProp( vobj, id );
|
||||
prop_quoted = prop_charset = FALSE;
|
||||
for ( pstr = str; *pstr; ++pstr ) {
|
||||
if ( *pstr & 0x80 )
|
||||
prop_charset = TRUE;
|
||||
if ( ! isprint( *pstr ) )
|
||||
prop_quoted = TRUE;
|
||||
}
|
||||
if ( prop_quoted || prop_charset ) {
|
||||
/*
|
||||
* single-field property like VCARD:FN needs charset,quoted property
|
||||
* attached to the property 'vprop'
|
||||
* multi-field sub-property like VCARD:ADR:VCCityProp needs charset
|
||||
* prop attached to the toplevel property 'vobj'
|
||||
* multi-field property must not use QUOTED-PRINTABLE due to problem
|
||||
* with vcc.y parser. fixing the parser would not help, because other
|
||||
* programs using the vCard,vCal output do not have the fixed parser.
|
||||
*/
|
||||
switch ( vca_type( vobj ) ) {
|
||||
case VCARD:
|
||||
case VMEMO:
|
||||
case VEVENT:
|
||||
case VTODO:
|
||||
vpropchars = vprop; /* single-field property */
|
||||
break;
|
||||
default:
|
||||
vpropchars = vobj; /* multi-field sub-property */
|
||||
}
|
||||
if ( prop_quoted /* QUOTED-PRINTABLE must not */
|
||||
&& vpropchars != vobj ) /* be used with multi-field */
|
||||
SetProp( vpropchars, VCQuotedPrintableProp );
|
||||
if ( prop_charset )
|
||||
SetString( vpropchars, VCCharacterSetProp, "ISO-8859-1" );
|
||||
}
|
||||
_ChangeString( vprop, str );
|
||||
return vprop;
|
||||
}
|
||||
char * /* dupStr()'d property's string value or NULL */
|
||||
dupStringValue( VObject * vobj, const char * id )
|
||||
{
|
||||
VObject * vprop;
|
||||
char vtext[1+10+1];
|
||||
|
||||
if ( vobj == NULL )
|
||||
return NULL;
|
||||
if ( id && *id ) {
|
||||
if ( (vprop = isAPropertyOf( vobj, id )) == NULL )
|
||||
return NULL;
|
||||
} else
|
||||
vprop = vobj;
|
||||
switch ( vObjectValueType( vprop ) ) {
|
||||
case VCVT_STRINGZ:
|
||||
return dupStr( vObjectStringZValue( vprop ), 0 );
|
||||
case VCVT_USTRINGZ:
|
||||
return fakeCString( vObjectUStringZValue( vprop ) );
|
||||
case VCVT_UINT:
|
||||
sprintf( vtext, "%+010d", vObjectIntegerValue( vprop ) );
|
||||
return dupStr( vtext, 0 );
|
||||
case VCVT_ULONG:
|
||||
sprintf( vtext, "%+010ld", vObjectLongValue( vprop ) );
|
||||
return dupStr( vtext, 0 );
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
char * /* property's string value or "" */
|
||||
StringValue( VObject * vobj, const char * id )
|
||||
{
|
||||
char * strval;
|
||||
|
||||
if ( (strval = dupStringValue( vobj, id )) == NULL )
|
||||
return "";
|
||||
strncat( strcpy( ic35fld, "" ), strval, sizeof(ic35fld)-1 );
|
||||
deleteStr( strval );
|
||||
return ic35fld;
|
||||
}
|
||||
|
||||
/* set,get property long integer value
|
||||
* -----------------------------------
|
||||
*/
|
||||
void
|
||||
SetLong( VObject * vobj, const char * id, long value )
|
||||
{
|
||||
VObject * vprop;
|
||||
|
||||
if ( (vprop = isAPropertyOf( vobj, id )) == NULL )
|
||||
vprop = addProp( vobj, id );
|
||||
setVObjectLongValue( vprop, value );
|
||||
}
|
||||
long /* property's long value or -1 if unknown */
|
||||
LongValue( VObject * vobj, const char * id )
|
||||
{
|
||||
VObject * vprop;
|
||||
char * strval;
|
||||
long value;
|
||||
|
||||
if ( !( vobj && id && *id )
|
||||
|| (vprop = isAPropertyOf( vobj, id )) == NULL )
|
||||
return -1;
|
||||
switch ( vObjectValueType( vprop ) ) {
|
||||
case VCVT_STRINGZ:
|
||||
return atol( vObjectStringZValue( vprop ) );
|
||||
case VCVT_USTRINGZ:
|
||||
strval = fakeCString( vObjectUStringZValue( vprop ) );
|
||||
value = atol( strval );
|
||||
deleteStr( strval );
|
||||
return value;
|
||||
case VCVT_UINT:
|
||||
return vObjectIntegerValue( vprop );
|
||||
case VCVT_ULONG:
|
||||
return vObjectLongValue( vprop );
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set,get VObject NOTE/DESCRIPTION
|
||||
* --------------------------------
|
||||
* some properties are not supported by e.g. korganizer, gnomecal,
|
||||
* as workaround they are kept is marked lines in NOTE/DESCRIPTION.
|
||||
*/
|
||||
static const char *
|
||||
_NoteId( VObject * vobj )
|
||||
{
|
||||
switch( vca_type( vobj ) ) {
|
||||
case VCARD:
|
||||
case VMEMO: return VCNoteProp;
|
||||
case VEVENT:
|
||||
case VTODO: return VCDescriptionProp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
static size_t
|
||||
_NotePropsLen( char * str, int vtype )
|
||||
{
|
||||
static struct {
|
||||
int type;
|
||||
const char * id;
|
||||
} proptab[] = {
|
||||
{ VCARD, DEF1PROP },
|
||||
{ VCARD, DEF2PROP },
|
||||
{ VTODO, VCDTstartProp },
|
||||
{ VTODO, VCDueProp },
|
||||
{ VTODO, VCCategoriesProp },
|
||||
{ 0, NULL }
|
||||
},
|
||||
*ptab;
|
||||
char * pline;
|
||||
size_t lid;
|
||||
|
||||
for ( pline = str; pline; pline = strchr( pline, '\n' ) ) {
|
||||
if ( *pline == '\n' )
|
||||
++pline;
|
||||
for ( ptab = proptab; ptab->id != NULL; ++ptab )
|
||||
if ( ptab->type == vtype ) {
|
||||
lid = strlen( ptab->id );
|
||||
if ( strncmp( pline, ptab->id, lid ) == 0
|
||||
&& *(pline+lid) == ':' )
|
||||
break;
|
||||
}
|
||||
if ( ptab->id == NULL )
|
||||
break;
|
||||
}
|
||||
return pline ? pline - str : 0;
|
||||
}
|
||||
void
|
||||
SetNotes( VObject * vobj, char * value )
|
||||
{
|
||||
/* preserve property values stored in NOTE,DESCRIPTION */
|
||||
/* translate CRLF to NL to avoid confusing korganizer */
|
||||
char * onote;
|
||||
char * nnote;
|
||||
size_t lprops;
|
||||
const char *id;
|
||||
|
||||
if ( (id = _NoteId( vobj )) == NULL )
|
||||
return;
|
||||
value = dupSubstCRLF( value ? value : "" );
|
||||
if ( (onote = StringValue( vobj, id )) != NULL && *onote ) {
|
||||
lprops = _NotePropsLen( onote, vca_type( vobj ) );
|
||||
nnote = dupStr( "", lprops + strlen(value) );
|
||||
strcat( strncat( strcpy( nnote, "" ), onote, lprops ), value );
|
||||
deleteStr( value );
|
||||
} else {
|
||||
nnote = value;
|
||||
}
|
||||
SetString( vobj, id, nnote );
|
||||
deleteStr( nnote );
|
||||
}
|
||||
char *
|
||||
NotesValue( VObject * vobj )
|
||||
{
|
||||
/* skip property values stored in NOTE,DESCRIPTION */
|
||||
/* translate NL to CRLF to avoid confusing IC35 */
|
||||
char * note;
|
||||
size_t lprops;
|
||||
|
||||
if ( (note = StringValue( vobj, _NoteId( vobj ) )) == NULL
|
||||
|| strlen( note ) == 0 )
|
||||
return "";
|
||||
lprops = _NotePropsLen( note, vca_type( vobj ) );
|
||||
note = dupSubstNL( note+lprops );
|
||||
strcat( strcpy( ic35fld, "" ), note );
|
||||
deleteStr( note );
|
||||
return ic35fld;
|
||||
}
|
||||
void
|
||||
SetNoteProp( VObject * vobj, const char * id, char * value )
|
||||
{
|
||||
/* replace or prepend property value in NOTE/DESCRIPTION */
|
||||
/* as marked line "<id>:<value>\n" */
|
||||
char *onote, *oprop, *oldstr;
|
||||
char *nnote, *nprop;
|
||||
const char *noteid;
|
||||
|
||||
if ( !((noteid = _NoteId( vobj )) && id && *id ) )
|
||||
return;
|
||||
onote = dupSubstNL( StringValue( vobj, noteid ) );
|
||||
if ( value && *value ) {
|
||||
nprop = dupStr( "", strlen(id)+1+strlen(value)+2 );
|
||||
sprintf( nprop, "%s:%s\r\n", id, value );
|
||||
} else
|
||||
nprop = dupStr( "", 0 );
|
||||
if ( (oldstr = NotePropValue( vobj, id )) != NULL && *oldstr ) {
|
||||
oprop = dupStr( "", strlen(id)+1+strlen(oldstr)+2 );
|
||||
sprintf( oprop, "%s:%s\r\n", id, oldstr );
|
||||
nnote = dupSubst( onote, oprop, nprop );
|
||||
deleteStr( oprop );
|
||||
} else {
|
||||
nnote = dupStr( "", strlen(nprop)+strlen(onote) );
|
||||
strcat( strcpy( nnote, nprop ), onote );
|
||||
}
|
||||
deleteStr( onote );
|
||||
deleteStr( nprop );
|
||||
nnote = dupSubstCRLF( oldstr = nnote ); deleteStr( oldstr );
|
||||
SetString( vobj, noteid, nnote );
|
||||
deleteStr( nnote );
|
||||
}
|
||||
char *
|
||||
NotePropValue( VObject * vobj, const char * id )
|
||||
{
|
||||
/* retrieve property value stored in NOTE/DESCRIPTION */
|
||||
/* from marked line "<id>:<value>\n" */
|
||||
char * note;
|
||||
char * linetag;
|
||||
char * pprop;
|
||||
char * ptr;
|
||||
|
||||
if ( (note = StringValue( vobj, _NoteId( vobj ) )) == NULL
|
||||
|| strlen( note ) == 0 ) {
|
||||
return "";
|
||||
}
|
||||
sprintf( ptr = dupStr( "", strlen(note)+1 ), "\n%s", note );
|
||||
note = dupSubstNL( ptr );
|
||||
deleteStr( ptr );
|
||||
sprintf( linetag = dupStr( "", strlen(id)+3 ), "\r\n%s:", id );
|
||||
if ( (pprop = strstr( note, linetag )) != NULL ) {
|
||||
pprop += strlen( linetag );
|
||||
if ( (ptr = strstr( pprop, "\r\n" )) != NULL )
|
||||
*ptr = '\0';
|
||||
strncat( strcpy( ic35fld, "" ), pprop, sizeof(ic35fld) );
|
||||
}
|
||||
deleteStr( linetag );
|
||||
deleteStr( note );
|
||||
return pprop ? ic35fld : "";
|
||||
}
|
||||
|
||||
/* categories
|
||||
* ----------
|
||||
*/
|
||||
static char *
|
||||
_is_stdCategory( char * category )
|
||||
{
|
||||
char * Address = "Address";
|
||||
char * Business = "Business";
|
||||
char * Personal = "Personal";
|
||||
char * Unfiled = "Unfiled";
|
||||
|
||||
if ( strcasecmp( category, Address ) == 0 )
|
||||
return Address;
|
||||
else if ( strcasecmp( category, Business ) == 0 )
|
||||
return Business;
|
||||
else if ( strcasecmp( category, Personal ) == 0 )
|
||||
return Personal;
|
||||
else if ( strcasecmp( category, Unfiled ) == 0 )
|
||||
return Unfiled;
|
||||
return NULL;
|
||||
}
|
||||
VObject *
|
||||
SetCategory( VObject * vobj, char * newcategory )
|
||||
{
|
||||
char * categories;
|
||||
char * oldcategories;
|
||||
char * category;
|
||||
VObject * vprop;
|
||||
|
||||
if ( (oldcategories = StringValue( vobj, VCCategoriesProp )) == NULL
|
||||
|| strlen( oldcategories ) == 0 /* no categories or */
|
||||
|| strchr( oldcategories, ';' ) == NULL ) /* single category */
|
||||
return SetString( vobj, VCCategoriesProp, newcategory );
|
||||
categories = dupStr( oldcategories, strlen( oldcategories )
|
||||
+ 1 + strlen( newcategory ) );
|
||||
for ( category = strtok( categories, ";" );
|
||||
category != NULL; category = strtok( NULL, ";" ) ) {
|
||||
if ( strcmp( category, newcategory ) == 0 )
|
||||
return isAPropertyOf( vobj, VCCategoriesProp );
|
||||
if ( _is_stdCategory( category ) )
|
||||
break;
|
||||
}
|
||||
if ( category != NULL ) { /* replace standard category */
|
||||
category = dupStr( category, 0 );
|
||||
deleteStr( categories );
|
||||
categories = dupSubst( oldcategories, category, newcategory );
|
||||
deleteStr( category );
|
||||
} else /* else prepend new category */
|
||||
sprintf( categories, "%s;%s", newcategory, oldcategories );
|
||||
vprop = SetString( vobj, VCCategoriesProp, categories );
|
||||
deleteStr( categories );
|
||||
return vprop;
|
||||
}
|
||||
char * /* single, first standard or "Unfiled" */
|
||||
CategoryValue( VObject * vobj )
|
||||
{
|
||||
char * Unfiled = "Unfiled";
|
||||
char * categories;
|
||||
char * category;
|
||||
char * firstcategory;
|
||||
char * firststdcategory;
|
||||
|
||||
if ( (categories = StringValue( vobj, VCCategoriesProp )) == NULL
|
||||
|| strlen( categories ) == 0 )
|
||||
return Unfiled;
|
||||
firstcategory = firststdcategory = NULL;
|
||||
for ( category = strtok( categories, ";" );
|
||||
category; category = strtok( NULL, ";" ) ) {
|
||||
if ( firstcategory == NULL )
|
||||
firstcategory = dupStr( category, 0 );
|
||||
if ( firststdcategory == NULL )
|
||||
firststdcategory = _is_stdCategory( category );
|
||||
}
|
||||
if ( (category = firststdcategory) == NULL ) {
|
||||
if ( firstcategory )
|
||||
category = strncat( strcpy( ic35fld, "" ),
|
||||
firstcategory, sizeof(ic35fld)-1 );
|
||||
else
|
||||
category = Unfiled;
|
||||
}
|
||||
deleteStr( firstcategory );
|
||||
return category;
|
||||
}
|
||||
|
||||
/* telephone numbers
|
||||
* -----------------
|
||||
*/
|
||||
VObject *
|
||||
SetTel( VObject * vobj, const char * type, char * str )
|
||||
{
|
||||
VObject * vprop;
|
||||
VObjectIterator iter;
|
||||
|
||||
initPropIterator( &iter, vobj );
|
||||
while ( moreIteration( &iter ) ) {
|
||||
vprop = nextVObject( &iter );
|
||||
if ( strcmp( vObjectName( vprop ), VCTelephoneProp ) == 0
|
||||
&& isAPropertyOf( vprop, type ) ) {
|
||||
if ( str && *str ) {
|
||||
_ChangeString( vprop, str );
|
||||
return vprop;
|
||||
} else {
|
||||
cleanVObject( delProp( vobj, vprop ) );
|
||||
_vobj_dirty = TRUE;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !( str && *str ) )
|
||||
return NULL;
|
||||
_vobj_dirty = TRUE;
|
||||
vprop = addPropValue( vobj, VCTelephoneProp, str );
|
||||
addProp( vprop, type );
|
||||
return vprop;
|
||||
}
|
||||
|
||||
/* email addresses
|
||||
* ---------------
|
||||
*/
|
||||
VObject *
|
||||
SetEmail( VObject * vobj, int num, char * str )
|
||||
{
|
||||
VObject * vprop;
|
||||
VObjectIterator iter;
|
||||
int index;
|
||||
|
||||
index = 0;
|
||||
initPropIterator( &iter, vobj );
|
||||
while ( moreIteration( &iter ) ) {
|
||||
vprop = nextVObject( &iter );
|
||||
if ( strcmp( vObjectName( vprop ), VCEmailAddressProp ) == 0
|
||||
&& ++index == num ) {
|
||||
if ( str && *str ) {
|
||||
_ChangeString( vprop, str );
|
||||
return vprop;
|
||||
} else {
|
||||
cleanVObject( delProp( vobj, vprop ) );
|
||||
_vobj_dirty = TRUE;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !( str && *str ) )
|
||||
return NULL;
|
||||
_vobj_dirty = TRUE;
|
||||
vprop = addPropValue( vobj, VCEmailAddressProp, str );
|
||||
addProp( vprop, VCInternetProp );
|
||||
return vprop;
|
||||
}
|
||||
|
||||
|
||||
/* ============================================ */
|
||||
/* ISO date+time conversions */
|
||||
/* ============================================ */
|
||||
|
||||
static time_t /* convert ISO date+time to Unix-time */
|
||||
isodtstr_to_unixtime( char * dtstr )
|
||||
{
|
||||
char * format;
|
||||
struct tm dtm;
|
||||
time_t dtime;
|
||||
|
||||
if ( !( dtstr && *dtstr ) )
|
||||
return -1;
|
||||
|
||||
if ( strspn( dtstr, "0123456789" ) == 8 )
|
||||
format = "%4d" "%2d" "%2d%*[^0-9]%2d" "%2d" "%2d";
|
||||
else
|
||||
format = "%4d%*[^0-9]%2d%*[^0-9]%2d%*[^0-9]%2d%*[^0-9]%2d%*[^0-9]%2d";
|
||||
dtime = time( NULL );
|
||||
memcpy( &dtm, localtime( &dtime ), sizeof(dtm) ); /* default: today,now */
|
||||
sscanf( dtstr, format, &dtm.tm_year, &dtm.tm_mon, &dtm.tm_mday,
|
||||
&dtm.tm_hour, &dtm.tm_min, &dtm.tm_sec );
|
||||
dtm.tm_year -= 1900;
|
||||
dtm.tm_mon -= 1;
|
||||
dtm.tm_isdst = -1;
|
||||
dtime = mktime( &dtm );
|
||||
/*??? ymdhms_from_isodtime() does not respect timezone/Zulu in isodtime ???*/
|
||||
|
||||
return dtime;
|
||||
}
|
||||
char *
|
||||
isodtstr_to_ymd_or_today( char * dtstr )
|
||||
{
|
||||
static char ymd[8+1];
|
||||
time_t utsec;
|
||||
|
||||
if ( (utsec = isodtstr_to_unixtime( dtstr )) == -1 )
|
||||
utsec = time( NULL );
|
||||
strftime( ymd, sizeof(ymd), "%Y%m%d", localtime( &utsec ) );
|
||||
return ymd;
|
||||
}
|
||||
time_t /* convert ISO date+time to Unix-time */
|
||||
isodtime_to_unixtime( VObject * vobj, const char * id )
|
||||
{
|
||||
VObject * vprop;
|
||||
char * dtstr;
|
||||
time_t dtime;
|
||||
|
||||
if ( (vprop = isAPropertyOf( vobj, id )) == NULL )
|
||||
return -1;
|
||||
dtstr = fakeCString( vObjectUStringZValue( vprop ) );
|
||||
dtime = isodtstr_to_unixtime( dtstr );
|
||||
deleteStr( dtstr );
|
||||
return dtime;
|
||||
}
|
||||
char *
|
||||
isodtime_to_ymd( VObject * vobj, const char * id )
|
||||
{
|
||||
static char ymd[8+1];
|
||||
time_t utsec;
|
||||
|
||||
if ( (utsec = isodtime_to_unixtime( vobj, id )) == -1 )
|
||||
return "";
|
||||
strftime( ymd, sizeof(ymd), "%Y%m%d", localtime( &utsec ) );
|
||||
return ymd;
|
||||
}
|
||||
char *
|
||||
isodtime_to_ymd_or_today( VObject * vobj, const char * id )
|
||||
{
|
||||
static char ymd[8+1];
|
||||
time_t utsec;
|
||||
|
||||
if ( (utsec = isodtime_to_unixtime( vobj, id )) == -1 )
|
||||
utsec = time( NULL );
|
||||
strftime( ymd, sizeof(ymd), "%Y%m%d", localtime( &utsec ) );
|
||||
return ymd;
|
||||
}
|
||||
char *
|
||||
isodtime_to_hms_or_now( VObject * vobj, const char * id )
|
||||
{
|
||||
static char hms[6+1];
|
||||
time_t utsec;
|
||||
|
||||
if ( (utsec = isodtime_to_unixtime( vobj, id )) == -1 )
|
||||
utsec = time( NULL );
|
||||
strftime( hms, sizeof(hms), "%H%M%S", localtime( &utsec ) );
|
||||
return hms;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/************************************************************************
|
||||
* Copyright (C) 2000 Thomas Schulz *
|
||||
* *
|
||||
* $Id: vcutil.h,v 1.44 2000/12/27 22:26:52 tsch Rel $ *
|
||||
* *
|
||||
* header for IC35 data import/export: vCard,vCalendar utilities *
|
||||
* *
|
||||
************************************************************************/
|
||||
#ifndef _VCUTIL_H
|
||||
#define _VCUTIL_H 1
|
||||
|
||||
#include "vcc.h" /* VObject, .. */
|
||||
|
||||
|
||||
/* vCard,vCal record types */
|
||||
#define VCARD 1
|
||||
#define VMEMO 2
|
||||
#define VCAL 3
|
||||
#define VEVENT 4
|
||||
#define VTODO 5
|
||||
/* markers for (def.) in IC35 address */
|
||||
#define DEF1PROP "(def1)"
|
||||
#define DEF2PROP "(def2)"
|
||||
|
||||
|
||||
int vca_type( VObject * vobj );
|
||||
|
||||
char * dupSubst( char * str, char * old, char * new );
|
||||
char * dupSubstNL( char * src );
|
||||
char * dupSubstCRLF( char * src );
|
||||
|
||||
void clr_vobjdirty( void );
|
||||
void SetModtimeIfdirty( VObject * vobj );
|
||||
|
||||
VObject * SetProp( VObject * vobj, const char * id );
|
||||
void DelProp( VObject * vobj, const char * id );
|
||||
VObject * SetString( VObject * vobj, const char * id, char * str );
|
||||
char * dupStringValue( VObject * vobj, const char * id );
|
||||
char * StringValue( VObject * vobj, const char * id );
|
||||
|
||||
void SetLong( VObject * vobj, const char * id, long value );
|
||||
long LongValue( VObject * vobj, const char * id );
|
||||
|
||||
void SetNotes( VObject * vobj, char * value );
|
||||
void SetNoteProp( VObject * vobj, const char * id, char * value );
|
||||
char * NotesValue( VObject * vobj );
|
||||
char * NotePropValue( VObject * vobj, const char * id );
|
||||
|
||||
VObject * SetCategory( VObject * vobj, char * newcategory );
|
||||
char * CategoryValue( VObject * vobj );
|
||||
|
||||
VObject * SetTel( VObject * vobj, const char * type, char * str );
|
||||
VObject * SetEmail( VObject * vobj, int num, char * str );
|
||||
|
||||
char * isodtstr_to_ymd_or_today( char * dtstr );
|
||||
time_t isodtime_to_unixtime( VObject * vobj, const char * id );
|
||||
char * isodtime_to_ymd( VObject * vobj, const char * id );
|
||||
char * isodtime_to_ymd_or_today( VObject * vobj, const char * id );
|
||||
char * isodtime_to_hms_or_now( VObject * vobj, const char * id );
|
||||
|
||||
#endif /*_VCUTIL_H*/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,380 @@
|
|||
/***************************************************************************
|
||||
(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
|
||||
Business Machines Corporation and Siemens Rolm Communications Inc.
|
||||
|
||||
modified 2000 by Thomas Schulz:
|
||||
$Id: vobject.h,v 1.6 2000/12/21 23:01:45 tsch Rel $
|
||||
|
||||
For purposes of this license notice, the term Licensors shall mean,
|
||||
collectively, Apple Computer, Inc., AT&T Corp., International
|
||||
Business Machines Corporation and Siemens Rolm Communications Inc.
|
||||
The term Licensor shall mean any of the Licensors.
|
||||
|
||||
Subject to acceptance of the following conditions, permission is hereby
|
||||
granted by Licensors without the need for written agreement and without
|
||||
license or royalty fees, to use, copy, modify and distribute this
|
||||
software for any purpose.
|
||||
|
||||
The above copyright notice and the following four paragraphs must be
|
||||
reproduced in all copies of this software and any software including
|
||||
this software.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
|
||||
ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
|
||||
MODIFICATIONS.
|
||||
|
||||
IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
|
||||
INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
|
||||
OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
|
||||
EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE.
|
||||
|
||||
The software is provided with RESTRICTED RIGHTS. Use, duplication, or
|
||||
disclosure by the government are subject to restrictions set forth in
|
||||
DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
|
||||
The vCard/vCalendar C interface is implemented in the set
|
||||
of files as follows:
|
||||
|
||||
vcc.y, yacc source, and vcc.c, the yacc output you will use
|
||||
implements the core parser
|
||||
|
||||
vobject.c implements an API that insulates the caller from
|
||||
the parser and changes in the vCard/vCalendar BNF
|
||||
|
||||
port.h defines compilation environment dependent stuff
|
||||
|
||||
vcc.h and vobject.h are header files for their .c counterparts
|
||||
|
||||
vcaltmp.h and vcaltmp.c implement vCalendar "macro" functions
|
||||
which you may find useful.
|
||||
|
||||
test.c is a standalone test driver that exercises some of
|
||||
the features of the APIs provided. Invoke test.exe on a
|
||||
VCARD/VCALENDAR input text file and you will see the pretty
|
||||
print output of the internal representation (this pretty print
|
||||
output should give you a good idea of how the internal
|
||||
representation looks like -- there is one such output in the
|
||||
following too). Also, a file with the .out suffix is generated
|
||||
to show that the internal representation can be written back
|
||||
in the original text format.
|
||||
|
||||
For more information on this API see the readme.txt file
|
||||
which accompanied this distribution.
|
||||
|
||||
Also visit:
|
||||
|
||||
http://www.versit.com
|
||||
http://www.ralden.com
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __VOBJECT_H__
|
||||
#define __VOBJECT_H__ 1
|
||||
|
||||
|
||||
#include "port.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(__CPLUSPLUS__) || defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define VC7bitProp "7BIT"
|
||||
#define VC8bitProp "8BIT"
|
||||
#define VCAAlarmProp "AALARM"
|
||||
#define VCAdditionalNamesProp "ADDN"
|
||||
#define VCAdrProp "ADR"
|
||||
#define VCAgentProp "AGENT"
|
||||
#define VCAIFFProp "AIFF"
|
||||
#define VCAOLProp "AOL"
|
||||
#define VCAppleLinkProp "APPLELINK"
|
||||
#define VCAttachProp "ATTACH"
|
||||
#define VCAttendeeProp "ATTENDEE"
|
||||
#define VCATTMailProp "ATTMAIL"
|
||||
#define VCAudioContentProp "AUDIOCONTENT"
|
||||
#define VCAVIProp "AVI"
|
||||
#define VCBase64Prop "BASE64"
|
||||
#define VCBBSProp "BBS"
|
||||
#define VCBirthDateProp "BDAY"
|
||||
#define VCBMPProp "BMP"
|
||||
#define VCBodyProp "BODY"
|
||||
#define VCBusinessRoleProp "ROLE"
|
||||
#define VCCalProp "VCALENDAR"
|
||||
#define VCCaptionProp "CAP"
|
||||
#define VCCardProp "VCARD"
|
||||
#define VCCarProp "CAR"
|
||||
#define VCCategoriesProp "CATEGORIES"
|
||||
#define VCCellularProp "CELL"
|
||||
#define VCCGMProp "CGM"
|
||||
#define VCCharSetProp "CS"
|
||||
#define VCCIDProp "CID"
|
||||
#define VCCISProp "CIS"
|
||||
#define VCCityProp "L"
|
||||
#define VCClassProp "CLASS"
|
||||
#define VCCommentProp "NOTE"
|
||||
#define VCCompletedProp "COMPLETED"
|
||||
#define VCContentIDProp "CONTENT-ID"
|
||||
#define VCCountryNameProp "C"
|
||||
#define VCDAlarmProp "DALARM"
|
||||
#define VCDataSizeProp "DATASIZE"
|
||||
#define VCDayLightProp "DAYLIGHT"
|
||||
#define VCDCreatedProp "DCREATED"
|
||||
#define VCDeliveryLabelProp "LABEL"
|
||||
#define VCDescriptionProp "DESCRIPTION"
|
||||
#define VCDIBProp "DIB"
|
||||
#define VCDisplayStringProp "DISPLAYSTRING"
|
||||
#define VCDomesticProp "DOM"
|
||||
#define VCDTendProp "DTEND"
|
||||
#define VCDTstartProp "DTSTART"
|
||||
#define VCDueProp "DUE"
|
||||
#define VCEmailAddressProp "EMAIL"
|
||||
#define VCEncodingProp "ENCODING"
|
||||
#define VCEndProp "END"
|
||||
#define VCEventProp "VEVENT"
|
||||
#define VCEWorldProp "EWORLD"
|
||||
#define VCExNumProp "EXNUM"
|
||||
#define VCExpDateProp "EXDATE"
|
||||
#define VCExpectProp "EXPECT"
|
||||
#define VCExtAddressProp "EXT ADD"
|
||||
#define VCFamilyNameProp "F"
|
||||
#define VCFaxProp "FAX"
|
||||
#define VCFullNameProp "FN"
|
||||
#define VCGeoProp "GEO"
|
||||
#define VCGeoLocationProp "GEO"
|
||||
#define VCGIFProp "GIF"
|
||||
#define VCGivenNameProp "G"
|
||||
#define VCGroupingProp "Grouping"
|
||||
#define VCHomeProp "HOME"
|
||||
#define VCIBMMailProp "IBMMail"
|
||||
#define VCInlineProp "INLINE"
|
||||
#define VCInternationalProp "INTL"
|
||||
#define VCInternetProp "INTERNET"
|
||||
#define VCISDNProp "ISDN"
|
||||
#define VCJPEGProp "JPEG"
|
||||
#define VCLanguageProp "LANG"
|
||||
#define VCLastModifiedProp "LAST-MODIFIED"
|
||||
#define VCLastRevisedProp "REV"
|
||||
#define VCLocationProp "LOCATION"
|
||||
#define VCLogoProp "LOGO"
|
||||
#define VCMailerProp "MAILER"
|
||||
#define VCMAlarmProp "MALARM"
|
||||
#define VCMCIMailProp "MCIMAIL"
|
||||
#define VCMessageProp "MSG"
|
||||
#define VCMETProp "MET"
|
||||
#define VCModemProp "MODEM"
|
||||
#define VCMPEG2Prop "MPEG2"
|
||||
#define VCMPEGProp "MPEG"
|
||||
#define VCMSNProp "MSN"
|
||||
#define VCNamePrefixesProp "NPRE"
|
||||
#define VCNameProp "N"
|
||||
#define VCNameSuffixesProp "NSUF"
|
||||
#define VCNoteProp "NOTE"
|
||||
#define VCOrgNameProp "ORGNAME"
|
||||
#define VCOrgProp "ORG"
|
||||
#define VCOrgUnit2Prop "OUN2"
|
||||
#define VCOrgUnit3Prop "OUN3"
|
||||
#define VCOrgUnit4Prop "OUN4"
|
||||
#define VCOrgUnitProp "OUN"
|
||||
#define VCPagerProp "PAGER"
|
||||
#define VCPAlarmProp "PALARM"
|
||||
#define VCParcelProp "PARCEL"
|
||||
#define VCPartProp "PART"
|
||||
#define VCPCMProp "PCM"
|
||||
#define VCPDFProp "PDF"
|
||||
#define VCPGPProp "PGP"
|
||||
#define VCPhotoProp "PHOTO"
|
||||
#define VCPICTProp "PICT"
|
||||
#define VCPMBProp "PMB"
|
||||
#define VCPostalBoxProp "BOX"
|
||||
#define VCPostalCodeProp "PC"
|
||||
#define VCPostalProp "POSTAL"
|
||||
#define VCPowerShareProp "POWERSHARE"
|
||||
#define VCPreferredProp "PREF"
|
||||
#define VCPriorityProp "PRIORITY"
|
||||
#define VCProcedureNameProp "PROCEDURENAME"
|
||||
#define VCProdIdProp "PRODID"
|
||||
#define VCProdigyProp "PRODIGY"
|
||||
#define VCPronunciationProp "SOUND"
|
||||
#define VCPSProp "PS"
|
||||
#define VCPublicKeyProp "KEY"
|
||||
#define VCQPProp "QP"
|
||||
#define VCQuickTimeProp "QTIME"
|
||||
#define VCQuotedPrintableProp "QUOTED-PRINTABLE"
|
||||
#define VCRDateProp "RDATE"
|
||||
#define VCRegionProp "R"
|
||||
#define VCRelatedToProp "RELATED-TO"
|
||||
#define VCRepeatCountProp "REPEATCOUNT"
|
||||
#define VCResourcesProp "RESOURCES"
|
||||
#define VCRNumProp "RNUM"
|
||||
#define VCRoleProp "ROLE"
|
||||
#define VCRRuleProp "RRULE"
|
||||
#define VCRSVPProp "RSVP"
|
||||
#define VCRunTimeProp "RUNTIME"
|
||||
#define VCSequenceProp "SEQUENCE"
|
||||
#define VCSnoozeTimeProp "SNOOZETIME"
|
||||
#define VCStartProp "START"
|
||||
#define VCStatusProp "STATUS"
|
||||
#define VCStreetAddressProp "STREET"
|
||||
#define VCSubTypeProp "SUBTYPE"
|
||||
#define VCSummaryProp "SUMMARY"
|
||||
#define VCTelephoneProp "TEL"
|
||||
#define VCTIFFProp "TIFF"
|
||||
#define VCTimeZoneProp "TZ"
|
||||
#define VCTitleProp "TITLE"
|
||||
#define VCTLXProp "TLX"
|
||||
#define VCTodoProp "VTODO"
|
||||
#define VCTranspProp "TRANSP"
|
||||
#define VCUniqueStringProp "UID"
|
||||
#define VCURLProp "URL"
|
||||
#define VCURLValueProp "URLVAL"
|
||||
#define VCValueProp "VALUE"
|
||||
#define VCVersionProp "VERSION"
|
||||
#define VCVideoProp "VIDEO"
|
||||
#define VCVoiceProp "VOICE"
|
||||
#define VCWAVEProp "WAVE"
|
||||
#define VCWMFProp "WMF"
|
||||
#define VCWorkProp "WORK"
|
||||
#define VCX400Prop "X400"
|
||||
#define VCX509Prop "X509"
|
||||
#define VCXRuleProp "XRULE"
|
||||
|
||||
/* missing, although described in "vCard v2.1" vcard-21.ps */
|
||||
|
||||
#define VCCharacterSetProp "CHARSET"
|
||||
|
||||
/* Extensions */
|
||||
|
||||
#define XPilotIdProp "X-PILOTID"
|
||||
#define XPilotStatusProp "X-PILOTSTAT"
|
||||
|
||||
/* non-standard for Memo/Note */
|
||||
#define VCMemoProp "VMEMO"
|
||||
|
||||
typedef struct VObject VObject;
|
||||
|
||||
typedef struct VObjectIterator {
|
||||
VObject* start;
|
||||
VObject* next;
|
||||
} VObjectIterator;
|
||||
|
||||
extern DLLEXPORT(VObject*) newVObject(const char *id);
|
||||
extern DLLEXPORT(void) deleteVObject(VObject *p);
|
||||
extern DLLEXPORT(char*) dupStr(const char *s, unsigned int size);
|
||||
extern DLLEXPORT(void) deleteStr(const char *p);
|
||||
extern DLLEXPORT(void) unUseStr(const char *s);
|
||||
|
||||
extern DLLEXPORT(void) setVObjectName(VObject *o, const char* id);
|
||||
extern DLLEXPORT(void) setVObjectStringZValue(VObject *o, const char *s);
|
||||
extern DLLEXPORT(void) setVObjectStringZValue_(VObject *o, const char *s);
|
||||
extern DLLEXPORT(void) setVObjectUStringZValue(VObject *o, const wchar_t *s);
|
||||
extern DLLEXPORT(void) setVObjectUStringZValue_(VObject *o, const wchar_t *s);
|
||||
extern DLLEXPORT(void) setVObjectIntegerValue(VObject *o, unsigned int i);
|
||||
extern DLLEXPORT(void) setVObjectLongValue(VObject *o, unsigned long l);
|
||||
extern DLLEXPORT(void) setVObjectAnyValue(VObject *o, void *t);
|
||||
extern DLLEXPORT(VObject*) setValueWithSize(VObject *prop, void *val, unsigned int size);
|
||||
extern DLLEXPORT(VObject*) setValueWithSize_(VObject *prop, void *val, unsigned int size);
|
||||
|
||||
extern DLLEXPORT(const char*) vObjectName(VObject *o);
|
||||
extern DLLEXPORT(const char*) vObjectStringZValue(VObject *o);
|
||||
extern DLLEXPORT(const wchar_t*) vObjectUStringZValue(VObject *o);
|
||||
extern DLLEXPORT(unsigned int) vObjectIntegerValue(VObject *o);
|
||||
extern DLLEXPORT(unsigned long) vObjectLongValue(VObject *o);
|
||||
extern DLLEXPORT(void*) vObjectAnyValue(VObject *o);
|
||||
extern DLLEXPORT(VObject*) vObjectVObjectValue(VObject *o);
|
||||
extern DLLEXPORT(void) setVObjectVObjectValue(VObject *o, VObject *p);
|
||||
|
||||
extern DLLEXPORT(VObject*) addVObjectProp(VObject *o, VObject *p);
|
||||
extern DLLEXPORT(VObject*) addProp(VObject *o, const char *id);
|
||||
extern DLLEXPORT(VObject*) addProp_(VObject *o, const char *id);
|
||||
extern DLLEXPORT(VObject*) addPropValue(VObject *o, const char *p, const char *v);
|
||||
extern DLLEXPORT(VObject*) addPropSizedValue_(VObject *o, const char *p, const char *v, unsigned int size);
|
||||
extern DLLEXPORT(VObject*) addPropSizedValue(VObject *o, const char *p, const char *v, unsigned int size);
|
||||
extern DLLEXPORT(VObject*) addGroup(VObject *o, const char *g);
|
||||
extern DLLEXPORT(void) addList(VObject **o, VObject *p);
|
||||
|
||||
extern DLLEXPORT(VObject*) isAPropertyOf(VObject *o, const char *id);
|
||||
|
||||
extern DLLEXPORT(VObject*) nextVObjectInList(VObject *o);
|
||||
extern DLLEXPORT(void) initPropIterator(VObjectIterator *i, VObject *o);
|
||||
extern DLLEXPORT(int) moreIteration(VObjectIterator *i);
|
||||
extern DLLEXPORT(VObject*) nextVObject(VObjectIterator *i);
|
||||
|
||||
extern DLLEXPORT(char*) writeMemVObject(char *s, int *len, VObject *o);
|
||||
extern DLLEXPORT(char*) writeMemVObjects(char *s, int *len, VObject *list);
|
||||
|
||||
extern DLLEXPORT(const char*) lookupStr(const char *s);
|
||||
extern DLLEXPORT(void) cleanStrTbl(void);
|
||||
|
||||
extern DLLEXPORT(void) cleanVObject(VObject *o);
|
||||
extern DLLEXPORT(void) cleanVObjects(VObject *list);
|
||||
extern DLLEXPORT(VObject*) delList( VObject ** list, VObject * vobj );
|
||||
extern DLLEXPORT(VObject*) delProp( VObject * vobj, VObject * prop );
|
||||
|
||||
extern DLLEXPORT(const char*) lookupProp(const char* str);
|
||||
extern DLLEXPORT(const char*) lookupProp_(const char* str);
|
||||
|
||||
extern DLLEXPORT(wchar_t*) fakeUnicode(const char *ps, int *bytes);
|
||||
extern DLLEXPORT(int) uStrLen(const wchar_t *u);
|
||||
extern DLLEXPORT(char*) fakeCString(const wchar_t *u);
|
||||
|
||||
extern DLLEXPORT(void) printVObjectToFile(char *fname,VObject *o);
|
||||
extern DLLEXPORT(void) printVObjectsToFile(char *fname,VObject *list);
|
||||
extern DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o);
|
||||
extern DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list);
|
||||
extern DLLEXPORT(void) setCRLFmode( int mode );
|
||||
extern DLLEXPORT(int) CRLFmode( void );
|
||||
|
||||
extern DLLEXPORT(int) vObjectValueType(VObject *o);
|
||||
|
||||
/* return type of vObjectValueType: */
|
||||
#define VCVT_NOVALUE 0
|
||||
/* if the VObject has no value associated with it. */
|
||||
#define VCVT_STRINGZ 1
|
||||
/* if the VObject has value set by setVObjectStringZValue. */
|
||||
#define VCVT_USTRINGZ 2
|
||||
/* if the VObject has value set by setVObjectUStringZValue. */
|
||||
#define VCVT_UINT 3
|
||||
/* if the VObject has value set by setVObjectIntegerValue. */
|
||||
#define VCVT_ULONG 4
|
||||
/* if the VObject has value set by setVObjectLongValue. */
|
||||
#define VCVT_RAW 5
|
||||
/* if the VObject has value set by setVObjectAnyValue. */
|
||||
#define VCVT_VOBJECT 6
|
||||
/* if the VObject has value set by setVObjectVObjectValue. */
|
||||
|
||||
extern const char** fieldedProp;
|
||||
|
||||
/* NOTE regarding printVObject and writeVObject
|
||||
|
||||
The functions below are not exported from the DLL because they
|
||||
take a FILE* as a parameter, which cannot be passed across a DLL
|
||||
interface (at least that is my experience). Instead you can use
|
||||
their companion functions which take file names or pointers
|
||||
to memory. However, if you are linking this code into
|
||||
your build directly then you may find them a more convenient API
|
||||
and you can go ahead and use them. If you try to use them with
|
||||
the DLL LIB you will get a link error.
|
||||
*/
|
||||
extern void printVObject(FILE *fp,VObject *o);
|
||||
extern void writeVObject(FILE *fp, VObject *o);
|
||||
|
||||
|
||||
#if defined(__CPLUSPLUS__) || defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __VOBJECT_H__ */
|
||||
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
#! /bin/sh
|
||||
# ylwrap - wrapper for lex/yacc invocations.
|
||||
|
||||
scriptversion=2018-03-07.03; # UTC
|
||||
|
||||
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
|
||||
#
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
get_dirname ()
|
||||
{
|
||||
case $1 in
|
||||
*/*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';;
|
||||
# Otherwise, we want the empty string (not ".").
|
||||
esac
|
||||
}
|
||||
|
||||
# guard FILE
|
||||
# ----------
|
||||
# The CPP macro used to guard inclusion of FILE.
|
||||
guard ()
|
||||
{
|
||||
printf '%s\n' "$1" \
|
||||
| sed \
|
||||
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
|
||||
-e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g' \
|
||||
-e 's/__*/_/g'
|
||||
}
|
||||
|
||||
# quote_for_sed [STRING]
|
||||
# ----------------------
|
||||
# Return STRING (or stdin) quoted to be used as a sed pattern.
|
||||
quote_for_sed ()
|
||||
{
|
||||
case $# in
|
||||
0) cat;;
|
||||
1) printf '%s\n' "$1";;
|
||||
esac \
|
||||
| sed -e 's|[][\\.*]|\\&|g'
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
'')
|
||||
echo "$0: No files given. Try '$0 --help' for more information." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
--basedir)
|
||||
basedir=$2
|
||||
shift 2
|
||||
;;
|
||||
-h|--h*)
|
||||
cat <<\EOF
|
||||
Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
|
||||
|
||||
Wrapper for lex/yacc invocations, renaming files as desired.
|
||||
|
||||
INPUT is the input file
|
||||
OUTPUT is one file PROG generates
|
||||
DESIRED is the file we actually want instead of OUTPUT
|
||||
PROGRAM is program to run
|
||||
ARGS are passed to PROG
|
||||
|
||||
Any number of OUTPUT,DESIRED pairs may be used.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v|--v*)
|
||||
echo "ylwrap $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# The input.
|
||||
input=$1
|
||||
shift
|
||||
# We'll later need for a correct munging of "#line" directives.
|
||||
input_sub_rx=`get_dirname "$input" | quote_for_sed`
|
||||
case $input in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
# Absolute path; do nothing.
|
||||
;;
|
||||
*)
|
||||
# Relative path. Make it absolute.
|
||||
input=`pwd`/$input
|
||||
;;
|
||||
esac
|
||||
input_rx=`get_dirname "$input" | quote_for_sed`
|
||||
|
||||
# Since DOS filename conventions don't allow two dots,
|
||||
# the DOS version of Bison writes out y_tab.c instead of y.tab.c
|
||||
# and y_tab.h instead of y.tab.h. Test to see if this is the case.
|
||||
y_tab_nodot=false
|
||||
if test -f y_tab.c || test -f y_tab.h; then
|
||||
y_tab_nodot=true
|
||||
fi
|
||||
|
||||
# The parser itself, the first file, is the destination of the .y.c
|
||||
# rule in the Makefile.
|
||||
parser=$1
|
||||
|
||||
# A sed program to s/FROM/TO/g for all the FROM/TO so that, for
|
||||
# instance, we rename #include "y.tab.h" into #include "parse.h"
|
||||
# during the conversion from y.tab.c to parse.c.
|
||||
sed_fix_filenames=
|
||||
|
||||
# Also rename header guards, as Bison 2.7 for instance uses its header
|
||||
# guard in its implementation file.
|
||||
sed_fix_header_guards=
|
||||
|
||||
while test $# -ne 0; do
|
||||
if test x"$1" = x"--"; then
|
||||
shift
|
||||
break
|
||||
fi
|
||||
from=$1
|
||||
# Handle y_tab.c and y_tab.h output by DOS
|
||||
if $y_tab_nodot; then
|
||||
case $from in
|
||||
"y.tab.c") from=y_tab.c;;
|
||||
"y.tab.h") from=y_tab.h;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
to=$1
|
||||
shift
|
||||
sed_fix_filenames="${sed_fix_filenames}s|"`quote_for_sed "$from"`"|$to|g;"
|
||||
sed_fix_header_guards="${sed_fix_header_guards}s|"`guard "$from"`"|"`guard "$to"`"|g;"
|
||||
done
|
||||
|
||||
# The program to run.
|
||||
prog=$1
|
||||
shift
|
||||
# Make any relative path in $prog absolute.
|
||||
case $prog in
|
||||
[\\/]* | ?:[\\/]*) ;;
|
||||
*[\\/]*) prog=`pwd`/$prog ;;
|
||||
esac
|
||||
|
||||
dirname=ylwrap$$
|
||||
do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
mkdir $dirname || exit 1
|
||||
|
||||
cd $dirname
|
||||
|
||||
case $# in
|
||||
0) "$prog" "$input" ;;
|
||||
*) "$prog" "$@" "$input" ;;
|
||||
esac
|
||||
ret=$?
|
||||
|
||||
if test $ret -eq 0; then
|
||||
for from in *
|
||||
do
|
||||
to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"`
|
||||
if test -f "$from"; then
|
||||
# If $2 is an absolute path name, then just use that,
|
||||
# otherwise prepend '../'.
|
||||
case $to in
|
||||
[\\/]* | ?:[\\/]*) target=$to;;
|
||||
*) target=../$to;;
|
||||
esac
|
||||
|
||||
# Do not overwrite unchanged header files to avoid useless
|
||||
# recompilations. Always update the parser itself: it is the
|
||||
# destination of the .y.c rule in the Makefile. Divert the
|
||||
# output of all other files to a temporary file so we can
|
||||
# compare them to existing versions.
|
||||
if test $from != $parser; then
|
||||
realtarget=$target
|
||||
target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'`
|
||||
fi
|
||||
|
||||
# Munge "#line" or "#" directives. Don't let the resulting
|
||||
# debug information point at an absolute srcdir. Use the real
|
||||
# output file name, not yy.lex.c for instance. Adjust the
|
||||
# include guards too.
|
||||
sed -e "/^#/!b" \
|
||||
-e "s|$input_rx|$input_sub_rx|" \
|
||||
-e "$sed_fix_filenames" \
|
||||
-e "$sed_fix_header_guards" \
|
||||
"$from" >"$target" || ret=$?
|
||||
|
||||
# Check whether files must be updated.
|
||||
if test "$from" != "$parser"; then
|
||||
if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
|
||||
echo "$to is unchanged"
|
||||
rm -f "$target"
|
||||
else
|
||||
echo "updating $to"
|
||||
mv -f "$target" "$realtarget"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# A missing file is only an error for the parser. This is a
|
||||
# blatant hack to let us support using "yacc -d". If -d is not
|
||||
# specified, don't fail when the header file is "missing".
|
||||
if test "$from" = "$parser"; then
|
||||
ret=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Remove the directory.
|
||||
cd ..
|
||||
rm -rf $dirname
|
||||
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
Loading…
Reference in New Issue