gsmopen: re-added gsmlib

This commit is contained in:
Giovanni Maruzzelli 2012-04-17 18:40:32 +02:00
parent 61894c23ae
commit 3747375196
200 changed files with 156102 additions and 0 deletions

View File

@ -0,0 +1,8 @@
For Linux distros without gsmlib (eg: CentOS):
Here are the original (ancient) sources for gsmlib, and the patch made by Ubuntu for modern compilers.
In the directory gsmlib-1.10-patched-13ubuntu are the patched sources, ready for (no need to patch them again):
./configure
make
make install

View File

@ -0,0 +1,226 @@
Notes on the Free Translation Project
*************************************
Free software is going international! The Free Translation Project
is a way to get maintainers of free software, translators, and users all
together, so that will gradually become able to speak many languages.
A few packages already provide translations for their messages.
If you found this `ABOUT-NLS' file inside a distribution, you may
assume that the distributed package does use GNU `gettext' internally,
itself available at your nearest GNU archive site. But you do *not*
need to install GNU `gettext' prior to configuring, installing or using
this package with messages translated.
Installers will find here some useful hints. These notes also
explain how users should proceed for getting the programs to use the
available translations. They tell how people wanting to contribute and
work at translations should contact the appropriate team.
When reporting bugs in the `intl/' directory or bugs which may be
related to internationalization, you should tell about the version of
`gettext' which is used. The information can be found in the
`intl/VERSION' file, in internationalized packages.
One advise in advance
=====================
If you want to exploit the full power of internationalization, you
should configure it using
./configure --with-included-gettext
to force usage of internationalizing routines provided within this
package, despite the existence of internationalizing capabilities in the
operating system where this package is being installed. So far, only
the `gettext' implementation in the GNU C library version 2 provides as
many features (such as locale alias or message inheritance) as the
implementation here. It is also not possible to offer this additional
functionality on top of a `catgets' implementation. Future versions of
GNU `gettext' will very likely convey even more functionality. So it
might be a good idea to change to GNU `gettext' as soon as possible.
So you need not provide this option if you are using GNU libc 2 or
you have installed a recent copy of the GNU gettext package with the
included `libintl'.
INSTALL Matters
===============
Some packages are "localizable" when properly installed; the
programs they contain can be made to speak your own native language.
Most such packages use GNU `gettext'. Other packages have their own
ways to internationalization, predating GNU `gettext'.
By default, this package will be installed to allow translation of
messages. It will automatically detect whether the system provides
usable `catgets' (if using this is selected by the installer) or
`gettext' functions. If neither is available, the GNU `gettext' own
library will be used. This library is wholly contained within this
package, usually in the `intl/' subdirectory, so prior installation of
the GNU `gettext' package is *not* required. Installers may use
special options at configuration time for changing the default
behaviour. The commands:
./configure --with-included-gettext
./configure --with-catgets
./configure --disable-nls
will respectively bypass any pre-existing `catgets' or `gettext' to use
the internationalizing routines provided within this package, enable
the use of the `catgets' functions (if found on the locale system), or
else, *totally* disable translation of messages.
When you already have GNU `gettext' installed on your system and run
configure without an option for your new package, `configure' will
probably detect the previously built and installed `libintl.a' file and
will decide to use this. This might be not what is desirable. You
should use the more recent version of the GNU `gettext' library. I.e.
if the file `intl/VERSION' shows that the library which comes with this
package is more recent, you should use
./configure --with-included-gettext
to prevent auto-detection.
By default the configuration process will not test for the `catgets'
function and therefore they will not be used. The reasons are already
given above: the emulation on top of `catgets' cannot provide all the
extensions provided by the GNU `gettext' library. If you nevertheless
want to use the `catgets' functions use
./configure --with-catgets
to enable the test for `catgets' (this causes no harm if `catgets' is
not available on your system). If you really select this option we
would like to hear about the reasons because we cannot think of any
good one ourself.
Internationalized packages have usually many `po/LL.po' files, where
LL gives an ISO 639 two-letter code identifying the language. Unless
translations have been forbidden at `configure' time by using the
`--disable-nls' switch, all available translations are installed
together with the package. However, the environment variable `LINGUAS'
may be set, prior to configuration, to limit the installed set.
`LINGUAS' should then contain a space separated list of two-letter
codes, stating which languages are allowed.
Using This Package
==================
As a user, if your language has been installed for this package, you
only have to set the `LANG' environment variable to the appropriate
ISO 639 `LL' two-letter code prior to using the programs in the
package. For example, let's suppose that you speak German. At the
shell prompt, merely execute `setenv LANG de' (in `csh'),
`export LANG; LANG=de' (in `sh') or `export LANG=de' (in `bash'). This
can be done from your `.login' or `.profile' file, once and for all.
An operating system might already offer message localization for
many of its programs, while other programs have been installed locally
with the full capabilities of GNU `gettext'. Just using `gettext'
extended syntax for `LANG' would break proper localization of already
available operating system programs. In this case, users should set
both `LANGUAGE' and `LANG' variables in their environment, as programs
using GNU `gettext' give preference to `LANGUAGE'. For example, some
Swedish users would rather read translations in German than English for
when Swedish is not available. This is easily accomplished by setting
`LANGUAGE' to `sv:de' while leaving `LANG' to `sv'.
Translating Teams
=================
For the Free Translation Project to be a success, we need interested
people who like their own language and write it well, and who are also
able to synergize with other translators speaking the same language.
Each translation team has its own mailing list, courtesy of Linux
International. You may reach your translation team at the address
`LL@li.org', replacing LL by the two-letter ISO 639 code for your
language. Language codes are *not* the same as the country codes given
in ISO 3166. The following translation teams exist, as of December
1997:
Chinese `zh', Czech `cs', Danish `da', Dutch `nl', English `en',
Esperanto `eo', Finnish `fi', French `fr', German `de', Hungarian
`hu', Irish `ga', Italian `it', Indonesian `id', Japanese `ja',
Korean `ko', Latin `la', Norwegian `no', Persian `fa', Polish
`pl', Portuguese `pt', Russian `ru', Slovenian `sl', Spanish `es',
Swedish `sv', and Turkish `tr'.
For example, you may reach the Chinese translation team by writing to
`zh@li.org'.
If you'd like to volunteer to *work* at translating messages, you
should become a member of the translating team for your own language.
The subscribing address is *not* the same as the list itself, it has
`-request' appended. For example, speakers of Swedish can send a
message to `sv-request@li.org', having this message body:
subscribe
Keep in mind that team members are expected to participate
*actively* in translations, or at solving translational difficulties,
rather than merely lurking around. If your team does not exist yet and
you want to start one, or if you are unsure about what to do or how to
get started, please write to `translation@iro.umontreal.ca' to reach the
coordinator for all translator teams.
The English team is special. It works at improving and uniformizing
the terminology in use. Proven linguistic skill are praised more than
programming skill, here.
Available Packages
==================
Languages are not equally supported in all packages. The following
matrix shows the current state of internationalization, as of December
1997. The matrix shows, in regard of each package, for which languages
PO files have been submitted to translation coordination.
Ready PO files cs da de en es fi fr it ja ko nl no pl pt ru sl sv
.----------------------------------------------------.
bash | [] [] [] | 3
bison | [] [] [] | 3
clisp | [] [] [] [] | 4
cpio | [] [] [] [] [] [] | 6
diffutils | [] [] [] [] [] | 5
enscript | [] [] [] [] [] [] | 6
fileutils | [] [] [] [] [] [] [] [] [] [] | 10
findutils | [] [] [] [] [] [] [] [] [] | 9
flex | [] [] [] [] | 4
gcal | [] [] [] [] [] | 5
gettext | [] [] [] [] [] [] [] [] [] [] [] | 12
grep | [] [] [] [] [] [] [] [] [] [] | 10
hello | [] [] [] [] [] [] [] [] [] [] [] | 11
id-utils | [] [] [] | 3
indent | [] [] [] [] [] | 5
libc | [] [] [] [] [] [] [] | 7
m4 | [] [] [] [] [] [] | 6
make | [] [] [] [] [] [] | 6
music | [] [] | 2
ptx | [] [] [] [] [] [] [] [] | 8
recode | [] [] [] [] [] [] [] [] [] | 9
sh-utils | [] [] [] [] [] [] [] [] | 8
sharutils | [] [] [] [] [] [] | 6
tar | [] [] [] [] [] [] [] [] [] [] [] | 11
texinfo | [] [] [] | 3
textutils | [] [] [] [] [] [] [] [] [] | 9
wdiff | [] [] [] [] [] [] [] [] | 8
`----------------------------------------------------'
17 languages cs da de en es fi fr it ja ko nl no pl pt ru sl sv
27 packages 6 4 25 1 18 1 26 2 1 12 20 9 19 7 4 7 17 179
Some counters in the preceding matrix are higher than the number of
visible blocks let us expect. This is because a few extra PO files are
used for implementing regional variants of languages, or language
dialects.
For a PO file in the matrix above to be effective, the package to
which it applies should also have been internationalized and
distributed as such by its maintainer. There might be an observable
lag between the mere existence a PO file and its wide availability in a
distribution.
If December 1997 seems to be old, you may fetch a more recent copy
of this `ABOUT-NLS' file on most GNU archive sites.

View File

@ -0,0 +1,482 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 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.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, 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 library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, 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 companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the 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.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307 USA.
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@ -0,0 +1,386 @@
gsmlib-1.10
- reactivated code in gsm_at to retry sending PDU after
unsolicited result code
- added description of unicode handling to FAQ
- compilation fixes for gcc-3.0.4
- added quick exit for ATZ in UnixSerialPort constructor
if phone gives ERROR
- added fix for phones that return +CLIP: "Number not available."
instead of giving caller ID
- added get/setCLIRPresentation() functions to MeTa (contribution by
ivan)
- added "NO CARRIER" event to the event mechanism (contribution by
clock)
- added Win32 port of gsmsmsd (thanks to Konstantin Forostyan)
- further extented Win32 port of gsmsmsd to handle outgoing messages
- fixed problem with Ericsson T39m SMS sending (zero bytes in handshake)
- added capability to send concatenated SMSs in gsmsmsd and gsmsendsms
- fixed unsigned/signed char problems in Unix/Win32 serial port
implementations
- added capability to send multiple SMSs to gsmsendsms/gsmsmsd
gsmlib-1.9
- fixed decoding of alphanumeric addresses in gsm_sms_codec.
- fixed bug in gsm_event when checking whether to send an
acknowledgment for a received SMS
- More Siemens-specific patches, some extensions to the AT
command parser
- New code to print PIN status and set the PIN in gsmctl, setPIN
function in MeTa class (Andreas Roedl <flood@flood-net.de>)
- Missing virtual destructor in Port class caused destructors of
UnixSerialPort and Win32SerialPort not to be called - fixed
- Added new code to set functionality level on or off (thanks to
David Woodhouse)
- found bug in SMS store implementation that caused the now
obsolete _capacity member to be set to a too low value
- Added changes contributed by Frediano Ziglio to enable compilation
on Windows
- Added call waiting functions contributed by Ivan
gsmlib-1.8
- added workaround for Nokia Cellular Card Phone RPE-1 GSM900
that reports a CDS event that actually is an CDSI and sends a spurious
CR when waiting for a PDU
- SMS are stored without index in files now
- tested compilation with gcc-3.0.2
- added workaround for gsmlib getting confused when receiving SMS
and echo cannot be switched off - echos of the AT command are
filtered out in chat() now
- extended gsm_phonebook preload mechanism to batch-load phonebooks
where the index does not start with 1
- Added workaround for Motorola Timeport 260 to write back
deliver messages to the ME
- added workaround for compilation with libstdc++-v2
- private members of MeTa made protected
- new ext directory for phone-specific extensions
gsmlib-1.7
- fixed bug with calculation of userData length if userDataHeader
is present (octet count was subtracted, not septet count)
- fixed problem with string erase() at end of PDU for Falcom A2-1
- -t/--charset option of gsmpb did not work due to missing parameter
of getopt_long, fixed
- The SMS decoder/encoder can now handle alphanumeric addresses
in the GSM default alphabet
- set only those SMS stores that are actually needed to perform
SMS store operation
- Fixed signalling error 321 (Invalid memory index) when trying to
read from empty SMS store entry
- Fixed parsing error when reading current network operator if no
network connection
- Added capability to parse cell broadcast messages to gsmlib and
the gsmsmsd program
- Added workaround for Motorola Timeport 260 bug that doesn't correctly
report the message status when retrieving SMS messages from the
store
- Added workaround for Motorola Timeport 260 that allocates index
numbers to SMS messages linearly so that index number can be
be larger than capacity reported by AT command
gsmlib-1.6
- more fixes for the COPS=? return format
- fixed putBack() behaviour in gsm_parser (don't put back if end-of-
stream is reached)
- added toString() function to gsm_sms_codec's Address class
- SMS dates and times are now output in a locale-specific manner
- fixed bug in Parser::getEol() (_eos was accidentally set to true)
- added gsm_win32_serial module, Win32 project (VC++), and
Option FirstFone changes contributed by Frediano Ziglio
<freddy77@angelfire.com>
- fix in COM port recognition for Win32 (gsm_util)
- renamed library files libgsm.* to libgsmme.* (now starting with
version 1.0) because of conflict with another Debian package
- in gsm_phonebook and gsm_store the caching of entries can now
be disabled
- added facilities to use other character sets for phonebooks
- fixed workaround for Ericcson SH888 (missing service centre address)
- fixed bug in gsm_phonebook that prevented texts with the
character '@' to be written to to the phonebook
- fixed nasty memory allocation bug in gsmpb/gsmsmsstore
(automatic MeTa variable went out of scope even though used
later)
- fixed Y2K problem in timestamp printing
- fixed "make dist" to include win32 files
- added workarounds for Falcom A2-1 (autodetection and enabling by
"export GSMLIB_FALCOM_A2_1_FIX=1", zero after PDU)
- fixed bug that caused gsmlib to abort with an assert if a malformed
PDU was read
gsmlib-1.5
- adapted MeTa::getCurrentOPInfo() and MeTa::getAvailableOPInfo()
to handle Nokia 8290 quirks
- code to set line speed in gsm_unix_serial reinserted (it was
accidentally removed in previous version)
- minor changes to initialization sequence in gsm_unix_serial
- bugfix in gsm_unix_serial.cc: readByte() == 0 does not mean no
more bytes, but is legal value
- additionally allowed characters "*#pwPW" and '+' at any
position in telephone numbers
- added environment variable GSMLIB_SH888_FIX that (if set)
enables the gsmlib workaround for Ericsson SH888's broken SMS TPDUs
- fixed command line parameter handling bug in gsmsmsstore
- fixed %files section .spec file to correctly include manual pages
- fixed some bugs in terminal line setup (gsm_unix_serial) regarding
software/hardware handshake
- added new "--sca" option to SMS-related apps to set the SMS
service centre address on the command line (useful if default is not
set correctly in the phone)
- removed tcflush() call in UnixSerialPort::putLine that broke
the event system needed for gsmsmsd
gsmlib-1.4
- more attempts to fix UNIX serial port access
- allow custom backends for sorted phonebooks to be integrated
into gsmlib (eg. for RDBMS or LDAP storage). Introduced a new
module gsm_sorted_phonebook_base that contains the infrastructure for
this.
- Now gsmlib needs at least gcc-2.95.2 to compile correctly.
- Implemented option to open device with software handshaking (XON/XOFF).
The applications now have an -X option to turn this on.
- gsmlib now contains a facility to interrupt ongoing activity in a
controlled way. gsm_unix_serial now blocks for one second
maximum until it checks whether it was interrupted.
- various small bugfixes
- added workaround for phones that omit ':' in AT command responses
- all debugging output is now printed to stderr
- gsm_unix_serial: new attempt to initialize modem in a more
robust way (contributed)
- gsm_sms: fixed handling of user data header (contributed)
gsmlib-1.3
- fixed bug that caused gsmlib to hang if TAs don't respond
to AT inquiries for serial number etc.
- fixed bug with handling of CB mode AT command construction in
gsm_me_ta.cc, setSMSRoutingToTA()
- allow '+' as the first character of phonenumbers
- implemented reading and writing from/to stdin/stdout in
gsm_sorted_[sms_store|phonebook] and gsmpb/gsmsmsstore
- fixed (hopefully) the intermittent hangup problem in
gsm_unix_serial_port
- Some mobile phones cannot report the status of some facility
locks. The gsmctl program now prints out "unknown" in the
corresponding result line from the FLSTAT
operation if this problem occurs (instead of terminating).
- switched off non-blocking access to serial device
gsmlib-1.2
- gsmlib now also works with TAs that can not switch off echo
- fixed bug that prevented gsmlib from copying SMS_DELIVER and
SMS_STATUS_REPORT back to the ME
- introduced -I (--init) parameter to all command line apps to
allow for device-specific initialization
- made SMS decoding routines more robust against bad SMS (especially
premature end of PDU)
- New debugging feature: If compiled without NDEBUG, the
environment variable GSMLIB_DEBUG determines the verbosity of
debugging messages (0 = none, 1 = many, 2 = extreme)
gsmlib-1.1
- Parse multiple COPS (operator info) lines returned by some phones
- accept string as numeric value when interpreting COPS=? response
(Ericsson phone + GSM12 GSM module)
- accept string as numeric value when interpreting COPS? response
(Ericsson phone + GSM12 GSM module)
- retry when initializing TA (ATZ/ATE0 sequences)
- Set SMS routing:
allow mode 3 (special in-band technique) when setting routing
to TA (gsmlib should not be active when phone is switched to data mode
anyway)
- Set SMS routing:
handle buffer mode but only if it was reported by the +CNMI=? command
(the Ericsson GM12 GSM modem does not like it otherwise)
- Determine CPMS number of parameters for CPMS command (better
compability with some mobile phones / GSM modems)
- handle missing service centre address in incoming SMS for Ericsson
model 6050102
- add new RING event to gsm_event.h/.cc, gsmsmsd now handles RING
indications properly
- defined default event handler mostly to handle unexpected RING
indications that might otherwise confuse gsmlib
- gsmsmsd: can now be cleanly terminated using the SIGINT or SIGTERM
signals
- gsmsmsd: now handles multiple incoming SMS messages cleanly, before
there was a chance that some SMS messages coming in rapid succession
might have been lost
- gsmsmsd: flush option implemented that dispatches and erases
existing messages in SMS store
- gsmsmsd: added sending of SMS messages. gsmsmsd now accepts a
spool directory options where it expects to find SMS message file in a
simple format, these are dispatched every 5 seconds
gsmlib-1.0
- RPM support (spec file)
- the "+" is at least for the Siemens S10 and S25 a valid char in
telephone numbers (inserts a pause of 3 seconds), therefore it is now
allowed as part of telephone numbers
- fixed incorrect analysis of facility class parameters in gsmctl.cc
- restricted call forward time to 0..30 seconds in gsm_me_ta.cc
gsmlib-0.3
- implemented timeout for accessing the mobile phone in order
to avoid hangs
- upgraded to BETA status
- written glossary for abbreviations (gsminfo(7))
- implemented NLS support, added German translations
- implemented preserving the index position of phonebook entries in
gsmpb.cc and gsm_sorted_phonebook
- cleaned up manual pages (alphabetic ordering of options etc.)
- gsmsmstore program and gsm_sorted_sms_store./.cc completed and
tested
- gsmpb and gsmsmsstore now have --verbose (-V) options for detailed
progress reporting
- now check for getopt_long in configure (can be compiled on non-GNU
systems)
- removed asserts regarding lengths of numeric data types, put them
into configure script
- sorted options in apps/*.cc alphabetically (--help option)
- in gsm_sorted_sms_store compare telephone numbers more sensibly
- introduced -v option to gsmpb and gsmsmsstore to report execution
statistics
- tested new synchronization function in gsmpb program
- implemented operations in the gsmctl program
- rewrote test cases (compare output)
- completed gsmsmsstore program
- first changes for compilation with VC++ 6.0 on WIN32
gsmlib-0.2
- gsmsmstore program and gsm_sorted_sms_store./.cc mostly
completed but not yet much tested
- Fixed problem with some mobiles/TAs not giving prefixes after
certain AT sequences (reported for SIEMENS S25/IrDA, Nokia
8810/IrDA)
- Fixed problem with Xircom REM56G.100/Nokia 6150 that give
"CABLE: GSM" instead of "OK" after ATZ
- Mobiles that return nothing when empty phonebook entries are
requested are now handled correctly (reported for SIEMENS S25/IrDA)
- optimizations in gsm_*_phonebook modules (less AT commands necessary)
- new synchronization function in gsmpb program that is (hopefully)
more sensible (see man page for details)
gsmlib-0.1
- Initial release

View File

@ -0,0 +1,198 @@
GSMLIB Installation
===================
This distribution uses autoconf/automake/libtool. See below
for generic installation instructions. The default commands would be:
./configure
make
make install
See also the section INSTALLATION in the README file in this
directory. For questions regarding the internationalization of this
package refer to doc/README.NLS and ./ABOUT-NLS.
Developers: See also the file doc/README.developers.
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.

View File

@ -0,0 +1,24 @@
## Process this file with automake to produce Makefile.in
# *************************************************************************
# * GSM TA/ME library
# *
# * File: Makefile.am
# *
# * Purpose: Toplevel Makefile
# *
# * Author: Peter Hofmann (software@pxh.de)
# *
# * Created: 21.5.1999
# *************************************************************************
SUBDIRS_ = po gsmlib apps tests doc scripts win32 ext
EXTRA_DIST = gsmlib.spec
if COMPILE_INTL
SUBDIRS = intl $(SUBDIRS_) # po - make automake happy
else
SUBDIRS = $(SUBDIRS_) # po intl - make automake happy
endif
all:

View File

@ -0,0 +1,423 @@
# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# *************************************************************************
# * GSM TA/ME library
# *
# * File: Makefile.am
# *
# * Purpose: Toplevel Makefile
# *
# * Author: Peter Hofmann (software@pxh.de)
# *
# * Created: 21.5.1999
# *************************************************************************
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = .
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
AR = @AR@
AS = @AS@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CPP = @CPP@
CXX = @CXX@
CXXCPP = @CXXCPP@
DATADIRNAME = @DATADIRNAME@
DLLTOOL = @DLLTOOL@
ECHO = @ECHO@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
F77 = @F77@
GCJ = @GCJ@
GCJFLAGS = @GCJFLAGS@
GENCAT = @GENCAT@
GLIBC2 = @GLIBC2@
GLIBC21 = @GLIBC21@
GMSGFMT = @GMSGFMT@
GSM_VERSION = @GSM_VERSION@
HAVE_ASPRINTF = @HAVE_ASPRINTF@
HAVE_LIB = @HAVE_LIB@
HAVE_POSIX_PRINTF = @HAVE_POSIX_PRINTF@
HAVE_SNPRINTF = @HAVE_SNPRINTF@
HAVE_WPRINTF = @HAVE_WPRINTF@
INSTOBJEXT = @INSTOBJEXT@
INTLBISON = @INTLBISON@
INTLLIBS = @INTLLIBS@
INTLOBJS = @INTLOBJS@
INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
LIB = @LIB@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIB = @LTLIB@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
MAKEINFO = @MAKEINFO@
MKINSTALLDIRS = @MKINSTALLDIRS@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
POSUB = @POSUB@
RANLIB = @RANLIB@
RC = @RC@
STRIP = @STRIP@
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
SUBDIRS_ = po gsmlib apps tests doc scripts win32 ext
EXTRA_DIST = gsmlib.spec
@COMPILE_INTL_TRUE@SUBDIRS = intl $(SUBDIRS_) # po - make automake happy
@COMPILE_INTL_FALSE@SUBDIRS = $(SUBDIRS_) # po intl - make automake happy
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs
CONFIG_HEADER = gsm_config.h
CONFIG_CLEAN_FILES =
DIST_COMMON = README ./stamp-h.in ABOUT-NLS AUTHORS COPYING ChangeLog \
INSTALL Makefile.am Makefile.in NEWS TODO acconfig.h acinclude.m4 \
aclocal.m4 configure configure.in gsm_config.h.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
DIST_SUBDIRS = intl po gsmlib apps tests doc scripts win32 ext po \
gsmlib apps tests doc scripts win32 ext
all: all-redirect
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
$(ACLOCAL_M4): configure.in acinclude.m4
cd $(srcdir) && $(ACLOCAL)
config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
cd $(srcdir) && $(AUTOCONF)
gsm_config.h: stamp-h
@if test ! -f $@; then \
rm -f stamp-h; \
$(MAKE) stamp-h; \
else :; fi
stamp-h: $(srcdir)/gsm_config.h.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES= CONFIG_HEADERS=gsm_config.h \
$(SHELL) ./config.status
@echo timestamp > stamp-h 2> /dev/null
$(srcdir)/gsm_config.h.in: $(srcdir)/stamp-h.in
@if test ! -f $@; then \
rm -f $(srcdir)/stamp-h.in; \
$(MAKE) $(srcdir)/stamp-h.in; \
else :; fi
$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h
cd $(top_srcdir) && $(AUTOHEADER)
@echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null
mostlyclean-hdr:
clean-hdr:
distclean-hdr:
-rm -f gsm_config.h
maintainer-clean-hdr:
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
@SET_MAKE@
all-recursive install-data-recursive install-exec-recursive \
installdirs-recursive install-recursive uninstall-recursive \
check-recursive installcheck-recursive info-recursive dvi-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
mostlyclean-recursive clean-recursive distclean-recursive \
maintainer-clean-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
dot_seen=no; \
rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
rev="$$subdir $$rev"; \
test "$$subdir" != "." || dot_seen=yes; \
done; \
test "$$dot_seen" = "no" && rev=". $$rev"; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
TAGS: tags-recursive $(HEADERS) $(SOURCES) gsm_config.h.in $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)gsm_config.h.in$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags gsm_config.h.in $$unique $(LISP))
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
-rm -rf $(distdir)
GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
mkdir $(distdir)/=build
mkdir $(distdir)/=inst
dc_install_base=`cd $(distdir)/=inst && pwd`; \
cd $(distdir)/=build \
&& ../configure --with-included-gettext --srcdir=.. --prefix=$$dc_install_base \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) dist
-rm -rf $(distdir)
@banner="$(distdir).tar.gz is ready for distribution"; \
dashes=`echo "$$banner" | sed s/./=/g`; \
echo "$$dashes"; \
echo "$$banner"; \
echo "$$dashes"
dist: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
dist-all: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
distdir: $(DISTFILES)
-rm -rf $(distdir)
mkdir $(distdir)
-chmod 777 $(distdir)
here=`cd $(top_builddir) && pwd`; \
top_distdir=`cd $(distdir) && pwd`; \
distdir=`cd $(distdir) && pwd`; \
cd $(top_srcdir) \
&& $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Makefile
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
for subdir in $(DIST_SUBDIRS); do \
if test "$$subdir" = .; then :; else \
test -d $(distdir)/$$subdir \
|| mkdir $(distdir)/$$subdir \
|| exit 1; \
chmod 777 $(distdir)/$$subdir; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
|| exit 1; \
fi; \
done
info-am:
info: info-recursive
dvi-am:
dvi: dvi-recursive
check-am: all-am
check: check-recursive
installcheck-am:
installcheck: installcheck-recursive
all-recursive-am: gsm_config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
install-exec-am:
install-exec: install-exec-recursive
install-data-am:
install-data: install-data-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-recursive
uninstall-am:
uninstall: uninstall-recursive
all-am: Makefile gsm_config.h
all-redirect: all-recursive-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs: installdirs-recursive
installdirs-am:
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-hdr mostlyclean-tags mostlyclean-generic
mostlyclean: mostlyclean-recursive
clean-am: clean-hdr clean-tags clean-generic mostlyclean-am
clean: clean-recursive
distclean-am: distclean-hdr distclean-tags distclean-generic clean-am
-rm -f libtool
distclean: distclean-recursive
-rm -f config.status
maintainer-clean-am: maintainer-clean-hdr maintainer-clean-tags \
maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-recursive
-rm -f config.status
.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
install-data-recursive uninstall-data-recursive install-exec-recursive \
uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
all-recursive check-recursive installcheck-recursive info-recursive \
dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
dvi-am dvi check check-am installcheck-am installcheck all-recursive-am \
install-exec-am install-exec install-data-am install-data install-am \
install uninstall-am uninstall all-redirect all-am all installdirs-am \
installdirs mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
all:
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,11 @@
NEWS - 9.1.2000
Version 1.0 - first release with RPM support and binary packages
NEWS - 15.11.1999
BETA version (details see ChangeLog)
NEWS - 16.7.1999
initial release

View File

@ -0,0 +1,166 @@
INTRODUCTION
This distribution contains a library to access GSM mobile phones
through GSM modems or IrDA devices. Features include:
* modification of phonebooks stored in the mobile phone or on the
SIM card
* reading and writing of SMS messages stored in the mobile phone
* sending and reception of SMS messages
Additionally, some simple command line programs are provided to
use these functionalities.
REQUIREMENTS
You need a mobile phone that conforms to the GSM
standards ETSI GSM 07.07, ETSI GSM 07.05, and others.
Non-GSM mobile phones will not work! Additionally,
to access the mobile phone from the computer you will probably need an
GSM modem (that would be a PC-CARD, usually). There might be some
mobile phones, however, that incorporate directly terminal
adapter (TA) functionality. Access via IrDA interfaces is also
reported to work.
If you want to compile the library yourself please also read
doc/README.developers.
INSTALLATION
This distribution uses autoconf/automake/libtool. See the file
INSTALL for generic installation instructions. The default
commands for installation under /usr/local would be:
./configure
make
make install
If there are any problems you can generate a debug version. See
doc/README.developers for details.
AVAILABLE DOCUMENTATION
For the command line tools UNIX manual pages are available in the
doc subdirectory of this distribution. These are installed by
default in the directories /usr/local/man1, man7, and man8.
See also the files doc/README.developers, doc/README.NLS and doc/FAQ.
HARDWARE
The following mobile phone/GSM modem combinations are reported to
be compatible in varying degrees with the current release:
- Nokia 6150/Xircom REM56G.100
- Nokia 6150/Options "GSM-Ready(R) Cellular-Only" modem
from Option International
- Nokia 6210/- (Linux IrDA serial device)
- Nokia 8810/- (Linux IrDA serial device)
- Siemens S10D/Dr Neuhaus Gipsy Card GSM
- Siemens S25/- (Linux IrDA serial device)
- Siemens S35i/- (Linux IrDA serial device)
- Siemens S45
- Ericcson SH888/- (Linux IrDA serial device)
- Ericsson 6050102/GM 12 GSM module
- Ericsson T28s (firmware 000809 1106)
- Ericsson T20e (firmware R3A007)
- -/Siemens M20T (stand-alone GSM module)
- -/Wavecom WM02 GSM (stand-alone GSM module)
- Nokia 7110 (firware rev 4.80)/- (Linux IrDA serial device)
- Nokia 8290 (USA GSM 1900MHz)/- (Linux IrDA serial device)
- Falcom A2-1/- (stand-alone GSM module)
- Ericsson R320s/- (Linux IrDA serial device)
- Motorola Timeport 260/- (Serial cable and Linux IrDA serial device)
- Motorola Timeport 250/- (Linux IrDA serial device)
- Motorola Timeport P7389/- (Linux IrDA serial device)
- Nokia Cellular Card Phone RPE-1 GSM900 and
- Nokia Card Phone RPM-1 GSM900/1800
- Nokia Cardphone/Compaq iPAQ
- Omnipoint technologies Redhawk 2000 GSM modem
- Ericsson T28 (but one firmware revision is reported to have problems)
- Ericcson T65
- Ericcson T39m/Bluetooth
- Option International GlobeTrotter PCMCIA
Note 1: Some of the mobile phones have an integrated GSM modem
that can be accessed via the Linux IrDA drivers.
Note 2: Some of the abovementioned phones have still some glitches
with gsmlib (and I haven't tested them myself).
For the following phones I receive a lot of errors reports:
- Ericcson SH888: SMS function don't work with many firmware releases
This list is not exhaustive, there are probably many other types of
phone or GSM modem that work with gsmlib. Just try it and report back
to me!
DISCLAIMER
Even though care has been taken in the design and implementation
of this software it can not be excluded that this software could
destroy data in your mobile phone or may even render your mobile
phone useless (by erroneous PIN settings, for example). The
author will not be held responsible legally, financially, or in any
other form for any kind of damage that might occur from using
this software.
This software is provided "as is" and without any expressed or implied
warranties, including, without limitation, the implied warranties of
merchantibility and fitness for any particular purpose.
If you are not ready to accept these conditions please don't use
this software.
COPYING
This software is available on the LGPL (GNU LIBRARY GENERAL
PUBLIC LICENSE), ie. it is allowed to link
the library to commercial programs.
See the file COPYING for details on the license.
BUGS
There still seem to be some problems with IrDA devices under
Linux. There have been reports of gsmlib-based applications
(eg. gsmctl) hanging upon startup after initializing the serial port
/dev/ircomm. I would be thankful for any input on this problem.
If something does not work with your OS platform or the mobile/TA
combination please send a complete trace of the compilation or the
program execution that did fail. Make sure to compile with debugging
information enabled. Otherwise it will not be possible for me to do
much about the problem. Send bug reports to the mailing list or
to software@pxh.de. I promise not to publish telephone numbers or other
private information that might be contained in the execution traces
that you send me.
MAILING LISTS
There are now two mailings lists available for announcements and
discussion of gsmlib-related issues (hosted on lists.over.net).
Refer to these pages for information on subscription procedures
and an archive of previous postings:
http://lists.over.net/mailman/listinfo/gsmlib-announce/
for announcements regarding GSMLIB
http://lists.over.net/mailman/listinfo/gsmlib-devel/
the GSMLIB development list
AUTHOR
Peter Hofmann <software@pxh.de>.

View File

@ -0,0 +1,289 @@
This is my list of TODOs for development of this software (not
necessarily in order of importance):
("+" = DONE)
+ handle:
> --> AT+COPS=?
> <--
> <-- +COPS: (1,"AMENA",,"21403"),(3,"MOVISTAR",,"21407"),
> <-- (3,"E VODAFONE",,"21401"),,(0,1),(2)
> <--
> <-- OK
> gsmctl[ERROR]: expected comma (at position 45 of string '(1,"AMENA",,"21403"),(3,"MOVISTAR",,"21407"),')
+ extend README and web site with names of working phones (Siemens S45,...)
+ add workaround:
> <ME0> Manufacturer: Nokia Mobile Phones
> <ME1> Model: 8290
> <ME2> Revision: SW5.22
> <ME3> Serial Number: 010070303406434
> <FUN> Functionality Level: 1
> gsmctl[ERROR]: expected number, got '(2)'
- add fork to gsmsmsd
+ document "on" and "off" operations of gsmctl
- Just assume full functionality and issue AT+CGMF=0 if we haven't already
done so for this MeTa.
+ make update po
+ add find function
+ specify exact location of manual files in /usr/man/man* in spec
file, so that erase does not try to delete these directories
+ update PO
+ add option to gsmsendsms/gsmsmsd to request delivery reports
+ Fix CBM reception in gsmsmsd, see testcb.cc program
+ fix gsmsmsd:
--> AT+CNMI=?
<--
<-- +CNMI: (1),(1),(0),(0),(0)
<--
<-- OK
--> AT+CNMI=1,0,0,0,0
<--
<-- +CME ERROR: 003
./gsmsmsd[ERROR]: ME/TA error 'operation not allowed' (code 003)
+ Wenn ich den SMS-Speicher auslesen möchte, bricht gsmlib ab, weil der
Speicherplatz 1 auf der SIM-Karte nicht belegt ist. Das kann z.B.
passieren, wenn man Nachrichten im Handy löscht. Es kommt der Fehlercode
321 (Invalid memory index). Wie wäre es, in der Leseroutine alle
ungültigen Plätze zu ignorieren und solange zu lesen, bis die Anzahl der
vorhandenen Nachrichten im Speicher eingelesen ist?
+ document --charset option of gsmpb
+ Problems with PDUs with alphanumeric SCA, e.g.:
07911497941902F00414D0E474989D769F5DE4320839001040122151820000
+ > 2. Ich kann mit meinem Nokia 6210 nicht den Telefon-SMS-Speicher
auslesen. Dies liegt an der Speicherwahl, die vor dem Auslesen
an das Telefon übermittelt wird. Von der gsmlib wird anscheinend
immer die Anzahl der Speicher aus dem "CPMS=?"-Befehl genommen
(z.B. "SM","SM","SM"). Notwendig ist es aber nur, die erste
Position (zum Lesen und Löschen) bzw. die ersten beiden
Positionen (zum Schreiben) zu benutzen.
Das Nokia 6210 unterstützt aber an der ritten Stelle nur "SM",
nicht "ME". So kann ich die SMS im Telefon leider nicht
auslesen :-(
- add option to gsmpb/gsmssmstore deletion to delete ALL entries
- recheck Solaris port
+ cache character set settings in MeTa
+ add documentation for new gsmctl and gsmpb charset parameters
+ support characters sets other than GSM default alphabet for phone books
+ create non-existent files (gsmpb and gsmsmsstore)
+ rename libgsm to libgsmme, new major version 1
+ document sca/setsca operations/parameters in gsmctl
+ document option to set SCA in SMS-related apps
+ implement option to set SCA in SMS-related apps
+ convert NDEBUG test output from cout to cerr
+ test new gsm_unix_serial behaviour
+ apply checks for telephone number in gsm_sorted_phonebook
+ add interrupted() checks
+ check for gcc-2.95.2 in configure
- document custom backend options of gsmpb (and gsmsmsstore)
- /var/lock/LCK..modem
+ make gsmctl all continue even if there are some failures
+ CPIN thing
+ bring German translations up-to-date
+ document -I parameter
+ make chat routines robust against TAs that insist on echoing AT commands
+ ericsson sh 888:
<-- AT+CLCK="P2",2,,1
<--
+CME ERROR: 4
gsmctl[ERROR]: ME/TA error 'operation not supported' (code 4)
+ put README etc. into gsmlib package (not only devel)
+ make SMS decoding routines more robust against bad SMS (especially
premature end of PDU)
+ stop gsm_sorted_sms_store.cc from copying back SMS that came from
the SC (SMS_DELIVER, SMS_STATUS_REPORT, SMS_SUBMIT_REPORT). Their
message type is ambiguous and the ME may misinterpret them.
+ gsmsmsd: reinitialize modem every hour or so (signal termination implemented)
+ implement store, flush and spool options of gsmsmsd,
document them in man pages
+ test case for COPS answer numeric operator name in quotation marks
(testparser.cc)
+ retry when initializing TA (ATZ/ATE0 sequences)
+ correctly parse malformed SMS PDUs without SCA with Ericsson phone,
introduce Capability object for that. Ericsson ID:
<ME0> Manufacturer: ERICSSON
<ME1> Model: 6050102
<ME2> Revision: 990225 1852 CXC112143
<ME3> Serial Number: 520001690279310
+ Determine CPMS number of parameters for CPMS command (Ericsson
phone/GM12 GSM modem):
AT+CPMS?
+CPMS: "ME",0,10,"ME",0,10
AT+CPMS=?
+CPMS: ("ME","SM"),("ME","SM")
+ accept string as numeric value when interpreting COPS=? response
(Ericsson phone + GSM12 GSM module)
+ accept string as numeric value when interpreting COPS? response
(Ericsson phone + GSM12 GSM module)
+ It would be nice if it was possible to send sms:es
via gsmsmsd as well, via a spool directory or a socket (or stdin, in which
case one can put another program in front of this program and then
feed it with outgoing messages any way one wants). That way the program
could be the gateway between programs and the sms network. Now one has
to stop gsmsmsd to send an sms and that's not so elegant or write
ones own program.
+ gsmsmsd geht davon aus, das ein platz frei ist und benutzt nur diesen....
Wenn also eine SMS kommt, dann zieht es Sie raus, und löscht den
Speicherplatz.
Wenn aber die Karte voll ist, passiert gar nichts. Für eine automatisierte
umgebung ist das schlecht. besser wäre es, bei startup von gsmsmsd alle
Speicherplätze abzufrühstücken, und die Action aufzurufen.
+ Ein RING bringt den gsmsmsd ziemlich heftig aus dem Tritt. Hab jetzt ´ne
Rufumleitung eingebaut.
+ Links section in homepage
+ AT+CNMI=? liefert bei mir folgendes zurück:
+CNMI: (0-3),(0-3),(0-2),0,(0-1)
Parameter 4 (<ds>) liefert also keine Liste sondern nur ein Int zurück, du
versuchts aber ein ( zu parsen.
Was sagt die ETSI-spec. dazu ?? Ist das konform ??
+ give name of command at beginning of synopsis in man pages
+ list combinations of mobiles phones/GSM modems in the README
+ test ALARM in case of timeout when writing or reading to TA
+ install headers in gsmlib subdirectory
+ RPM spec file
+ test index changes for sorted phonebook -> write second test case
+ sort phone numbers the same way in gsm_sorted_sms_store and
gsm_sorted_phonebook
+ write glossary for all these nice abbreviations (TA, ME, SC, SME, TE)
+ HAVE_VSNPRINTF instead of HAVE_VPRINTF
+ internationalization of messages with GNU gettext. Files:
+gsm_at.cc +gsm_parser.cc +gsm_sorted_phonebook.cc
+gsm_error.cc +gsm_phonebook.cc +gsm_sorted_sms_store.cc
+gsm_event.cc +gsm_sms.cc +gsm_unix_serial.cc
+gsm_me_ta.cc +gsm_sms_codec.cc +gsm_util.cc
+gsm_nls.cc +gsm_sms_store.cc
+gsmctl.cc +gsmpb.cc +gsmsendsms.cc
+gsmsmsd.cc +gsmsmsstore.cc
+ implement indexed phonebook ops in gsmpb.cc
+ describe phonebook file format in gsmpb.man
+ update list of compatible hardware in README
+ all #include <gsm_config.h> must be enclosed in #ifdef's
+ check for getopt_long in configure
+ remove asserts regarding lengths of numeric data types, put them
into configure script
(string)
+ sort options in apps/*.cc alphabetically
+ in gsm_sorted_sms_store compare telephone numbers numerically
+ introduce -v option to gsmpb and gsmsmsstore to report execution
statistics (gives a nicer feeling to users)
+ test new synchronization function in gsmpb program
+ implement equality operator for SMSSToreEntry
+ test 'make install'
+ implement operations in the gsmctl program
+ test operations in the gsmctl program
+ document operations in the gsmctl program
+ rewrite test cases (compare output)
+ write gsm_sorted_sms_store module (along the lines of gsm_sorted_phonebook)
+ complete gsmsmsstore program (using abovementioned modules)
TODO low priority:
- implement SMS text mode
- The action command of gsmsmsd would be easier to make, if the program
sent the values in environment variables instead (except the user data
which could be sent on stdin).
+ Upgrade to latest autoheader, autoconf, libtool
- provide German translations for manual pages
- organize doc subdirectory for translated READMEs, manual pages
+ Win32 port
- test: optimization when accessing phonebooks: use size information
available via AT command to stop reading entries known to be empty (I
cannot test this with my hardware since CPBS? is not fully supported)
- make apps accept stdin or stdout
+ maybe strip leading and trailing whitespace from phonebook entries
when reading them from ME/TA or file? (not done, perhaps users want to
achieve special effects with white space)
- support international character sets (8-bit, 16-bit) in phonebook
operations (I'd like to have input from users who need this)

View File

@ -0,0 +1,33 @@
/* used by libtool*/
#define PACKAGE 0
/* used by libtool*/
#define VERSION 0
/* Define if getopt_long() available */
#undef HAVE_GETOPT_LONG
/* Define if alarm() available */
#undef HAVE_ALARM
/* Define if netinet/in.h header available */
#undef HAVE_NETINET_IN_H
/* Define if string.h header available */
#undef HAVE_STRING_H
/* Define for NLS */
#undef ENABLE_NLS
#undef HAVE_CATGETS
#undef HAVE_GETTEXT
#undef HAVE_LC_MESSAGES
#undef HAVE_STPCPY
/* Define LOCALEDIR */
#define LOCALEDIR "/usr/share/locale"
/* Define if libintl.h header available */
#undef HAVE_LIBINTL_H
/* Define if vsnprintf() function available */
#undef HAVE_VSNPRINTF

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
## Process this file with automake to produce Makefile.in
# *************************************************************************
# * GSM TA/ME library
# *
# * File: Makefile.am
# *
# * Purpose: apps Makefile
# *
# * Author: Peter Hofmann (software@pxh.de)
# *
# * Created: 5.6.1999
# *************************************************************************
INCLUDES = -I..
bin_PROGRAMS = gsmsmsstore gsmctl gsmsmsd gsmpb gsmsendsms
# build gsmsmsd from gsmsmsd.cc and libgsmme.la
gsmsmsd_SOURCES = gsmsmsd.cc
gsmsmsd_LDADD = ../gsmlib/libgsmme.la $(INTLLIBS)
# build gsmpb from gsmpb.cc and libgsmme.la
gsmpb_SOURCES = gsmpb.cc
gsmpb_LDADD = ../gsmlib/libgsmme.la $(INTLLIBS)
# build gsmctl from gsmctl.cc and libgsmme.la
gsmctl_SOURCES = gsmctl.cc
gsmctl_LDADD = ../gsmlib/libgsmme.la $(INTLLIBS)
# build gsmsendsms from gsmsendsms.cc and libgsmme.la
gsmsendsms_SOURCES = gsmsendsms.cc
gsmsendsms_LDADD = ../gsmlib/libgsmme.la $(INTLLIBS)
# build gsmsmsstore from gsmsmsstore.cc and libgsmme.la
gsmsmsstore_SOURCES = gsmsmsstore.cc
gsmsmsstore_LDADD = ../gsmlib/libgsmme.la $(INTLLIBS)

View File

@ -0,0 +1,442 @@
# Makefile.in generated by automake 1.6.3 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# *************************************************************************
# * GSM TA/ME library
# *
# * File: Makefile.am
# *
# * Purpose: apps Makefile
# *
# * Author: Peter Hofmann (software@pxh.de)
# *
# * Created: 5.6.1999
# *************************************************************************
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_HEADER = $(INSTALL_DATA)
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
EXEEXT = @EXEEXT@
OBJEXT = @OBJEXT@
PATH_SEPARATOR = @PATH_SEPARATOR@
AMTAR = @AMTAR@
AS = @AS@
AWK = @AWK@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CPP = @CPP@
CXX = @CXX@
DATADIRNAME = @DATADIRNAME@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
ECHO = @ECHO@
GENCAT = @GENCAT@
GLIBC21 = @GLIBC21@
GMSGFMT = @GMSGFMT@
GSM_VERSION = @GSM_VERSION@
HAVE_LIB = @HAVE_LIB@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INSTOBJEXT = @INSTOBJEXT@
INTLBISON = @INTLBISON@
INTLLIBS = @INTLLIBS@
INTLOBJS = @INTLOBJS@
INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
LIB = @LIB@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIB = @LTLIB@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
MKINSTALLDIRS = @MKINSTALLDIRS@
OBJDUMP = @OBJDUMP@
PACKAGE = @PACKAGE@
POSUB = @POSUB@
RANLIB = @RANLIB@
STRIP = @STRIP@
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
am__include = @am__include@
am__quote = @am__quote@
install_sh = @install_sh@
INCLUDES = -I..
bin_PROGRAMS = gsmsmsstore gsmctl gsmsmsd gsmpb gsmsendsms
# build gsmsmsd from gsmsmsd.cc and libgsmme.la
gsmsmsd_SOURCES = gsmsmsd.cc
gsmsmsd_LDADD = ../gsmlib/libgsmme.la $(INTLLIBS)
# build gsmpb from gsmpb.cc and libgsmme.la
gsmpb_SOURCES = gsmpb.cc
gsmpb_LDADD = ../gsmlib/libgsmme.la $(INTLLIBS)
# build gsmctl from gsmctl.cc and libgsmme.la
gsmctl_SOURCES = gsmctl.cc
gsmctl_LDADD = ../gsmlib/libgsmme.la $(INTLLIBS)
# build gsmsendsms from gsmsendsms.cc and libgsmme.la
gsmsendsms_SOURCES = gsmsendsms.cc
gsmsendsms_LDADD = ../gsmlib/libgsmme.la $(INTLLIBS)
# build gsmsmsstore from gsmsmsstore.cc and libgsmme.la
gsmsmsstore_SOURCES = gsmsmsstore.cc
gsmsmsstore_LDADD = ../gsmlib/libgsmme.la $(INTLLIBS)
subdir = apps
mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/gsm_config.h
CONFIG_CLEAN_FILES =
bin_PROGRAMS = gsmsmsstore$(EXEEXT) gsmctl$(EXEEXT) gsmsmsd$(EXEEXT) \
gsmpb$(EXEEXT) gsmsendsms$(EXEEXT)
PROGRAMS = $(bin_PROGRAMS)
am_gsmctl_OBJECTS = gsmctl.$(OBJEXT)
gsmctl_OBJECTS = $(am_gsmctl_OBJECTS)
gsmctl_DEPENDENCIES = ../gsmlib/libgsmme.la
gsmctl_LDFLAGS =
am_gsmpb_OBJECTS = gsmpb.$(OBJEXT)
gsmpb_OBJECTS = $(am_gsmpb_OBJECTS)
gsmpb_DEPENDENCIES = ../gsmlib/libgsmme.la
gsmpb_LDFLAGS =
am_gsmsendsms_OBJECTS = gsmsendsms.$(OBJEXT)
gsmsendsms_OBJECTS = $(am_gsmsendsms_OBJECTS)
gsmsendsms_DEPENDENCIES = ../gsmlib/libgsmme.la
gsmsendsms_LDFLAGS =
am_gsmsmsd_OBJECTS = gsmsmsd.$(OBJEXT)
gsmsmsd_OBJECTS = $(am_gsmsmsd_OBJECTS)
gsmsmsd_DEPENDENCIES = ../gsmlib/libgsmme.la
gsmsmsd_LDFLAGS =
am_gsmsmsstore_OBJECTS = gsmsmsstore.$(OBJEXT)
gsmsmsstore_OBJECTS = $(am_gsmsmsstore_OBJECTS)
gsmsmsstore_DEPENDENCIES = ../gsmlib/libgsmme.la
gsmsmsstore_LDFLAGS =
DEFS = @DEFS@
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
depcomp = $(SHELL) $(top_srcdir)/scripts/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/gsmctl.Po ./$(DEPDIR)/gsmpb.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/gsmsendsms.Po ./$(DEPDIR)/gsmsmsd.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/gsmsmsstore.Po
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
CXXFLAGS = @CXXFLAGS@
DIST_SOURCES = $(gsmctl_SOURCES) $(gsmpb_SOURCES) $(gsmsendsms_SOURCES) \
$(gsmsmsd_SOURCES) $(gsmsmsstore_SOURCES)
DIST_COMMON = Makefile.am Makefile.in
SOURCES = $(gsmctl_SOURCES) $(gsmpb_SOURCES) $(gsmsendsms_SOURCES) $(gsmsmsd_SOURCES) $(gsmsmsstore_SOURCES)
all: all-am
.SUFFIXES:
.SUFFIXES: .cc .lo .o .obj
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu apps/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(bindir)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
if test -f $$p \
|| test -f $$p1 \
; then \
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
rm -f $(DESTDIR)$(bindir)/$$f; \
done
clean-binPROGRAMS:
@list='$(bin_PROGRAMS)'; for p in $$list; do \
f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
echo " rm -f $$p $$f"; \
rm -f $$p $$f ; \
done
gsmctl$(EXEEXT): $(gsmctl_OBJECTS) $(gsmctl_DEPENDENCIES)
@rm -f gsmctl$(EXEEXT)
$(CXXLINK) $(gsmctl_LDFLAGS) $(gsmctl_OBJECTS) $(gsmctl_LDADD) $(LIBS)
gsmpb$(EXEEXT): $(gsmpb_OBJECTS) $(gsmpb_DEPENDENCIES)
@rm -f gsmpb$(EXEEXT)
$(CXXLINK) $(gsmpb_LDFLAGS) $(gsmpb_OBJECTS) $(gsmpb_LDADD) $(LIBS)
gsmsendsms$(EXEEXT): $(gsmsendsms_OBJECTS) $(gsmsendsms_DEPENDENCIES)
@rm -f gsmsendsms$(EXEEXT)
$(CXXLINK) $(gsmsendsms_LDFLAGS) $(gsmsendsms_OBJECTS) $(gsmsendsms_LDADD) $(LIBS)
gsmsmsd$(EXEEXT): $(gsmsmsd_OBJECTS) $(gsmsmsd_DEPENDENCIES)
@rm -f gsmsmsd$(EXEEXT)
$(CXXLINK) $(gsmsmsd_LDFLAGS) $(gsmsmsd_OBJECTS) $(gsmsmsd_LDADD) $(LIBS)
gsmsmsstore$(EXEEXT): $(gsmsmsstore_OBJECTS) $(gsmsmsstore_DEPENDENCIES)
@rm -f gsmsmsstore$(EXEEXT)
$(CXXLINK) $(gsmsmsstore_LDFLAGS) $(gsmsmsstore_OBJECTS) $(gsmsmsstore_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT) core *.core
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsmctl.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsmpb.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsmsendsms.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsmsmsd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsmsmsstore.Po@am__quote@
distclean-depend:
-rm -rf ./$(DEPDIR)
.cc.o:
@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
.cc.obj:
@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CXXCOMPILE) -c -o $@ `cygpath -w $<`
.cc.lo:
@AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(LTCXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
CXXDEPMODE = @CXXDEPMODE@
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
ETAGS = etags
ETAGSFLAGS =
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@list='$(DISTFILES)'; for file in $$list; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(PROGRAMS)
installdirs:
$(mkinstalldirs) $(DESTDIR)$(bindir)
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
distclean: distclean-am
distclean-am: clean-am distclean-compile distclean-depend \
distclean-generic distclean-libtool distclean-tags
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am:
install-exec-am: install-binPROGRAMS
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
uninstall-am: uninstall-binPROGRAMS uninstall-info-am
.PHONY: GTAGS all all-am check check-am clean clean-binPROGRAMS \
clean-generic clean-libtool distclean distclean-compile \
distclean-depend distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am info info-am install \
install-am install-binPROGRAMS install-data install-data-am \
install-exec install-exec-am install-info install-info-am \
install-man install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool tags uninstall uninstall-am \
uninstall-binPROGRAMS uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,635 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsmctl.cc
// *
// * Purpose: GSM mobile phone control program
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 11.7.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_nls.h>
#include <string>
#if defined(HAVE_GETOPT_LONG) || defined(WIN32)
#include <getopt.h>
#endif
#include <strstream>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <gsmlib/gsm_me_ta.h>
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_sysdep.h>
#ifdef WIN32
#include <gsmlib/gsm_win32_serial.h>
#else
#include <gsmlib/gsm_unix_serial.h>
#include <unistd.h>
#endif
#include <iostream>
using namespace std;
using namespace gsmlib;
// my ME
static MeTa *m;
// information parameters
enum InfoParameter {AllInfo, // print all info
MeInfo, // MeInfo must be first!
FunctionalityInfo,
OperatorInfo,
CurrentOperatorInfo,
FacilityLockStateInfo,
FacilityLockCapabilityInfo,
PasswordInfo,
PINInfo,
CLIPInfo,
CallForwardingInfo,
BatteryInfo,
BitErrorInfo,
SCAInfo,
CharSetInfo,
SignalInfo}; // SignalInfo must be last!
// operation parameters
// FIXME operations not implemented yet
// options
#ifdef HAVE_GETOPT_LONG
static struct option longOpts[] =
{
{"xonxoff", no_argument, (int*)NULL, 'X'},
{"operation", required_argument, (int*)NULL, 'o'},
{"device", required_argument, (int*)NULL, 'd'},
{"baudrate", required_argument, (int*)NULL, 'b'},
{"init", required_argument, (int*)NULL, 'I'},
{"help", no_argument, (int*)NULL, 'h'},
{"version", no_argument, (int*)NULL, 'v'},
{(char*)NULL, 0, (int*)NULL, 0}
};
#else
#define getopt_long(argc, argv, options, longopts, indexptr) \
getopt(argc, argv, options)
#endif
// helper function, prints forwarding info
void printForwardReason(string s, ForwardInfo &info)
{
cout << s << " "
<< (info._active ? _("active ") : _("inactive "))
<< _("number: ") << info._number
<< _(" subaddr: ") << info._subAddr
<< _(" time: ") << info._time << endl;
}
// print information
static void printInfo(InfoParameter ip)
{
switch (ip)
{
case MeInfo:
{
MEInfo mei = m->getMEInfo();
cout << _("<ME0> Manufacturer: ") << mei._manufacturer << endl
<< _("<ME1> Model: ") << mei._model << endl
<< _("<ME2> Revision: ") << mei._revision << endl
<< _("<ME3> Serial Number: ") << mei._serialNumber << endl;
break;
}
case FunctionalityInfo:
{
try {
int fun;
fun = m->getFunctionalityLevel();
cout << _("<FUN> Functionality Level: ") << fun << endl;
} catch (GsmException &x) {
cout << _("<FUN> Functionality Level: ") << _("unsupported") << endl;
}
break;
}
case OperatorInfo:
{
int count = 0;
vector<OPInfo> opis = m->getAvailableOPInfo();
for (vector<OPInfo>::iterator i = opis.begin(); i != opis.end(); ++i)
{
cout << "<OP" << count << _("> Status: ");
switch (i->_status)
{
case UnknownOPStatus: cout << _("unknown"); break;
case CurrentOPStatus: cout << _("current"); break;
case AvailableOPStatus: cout << _("available"); break;
case ForbiddenOPStatus: cout << _("forbidden"); break;
}
cout << _(" Long name: '") << i->_longName << "' "
<< _(" Short name: '") << i->_shortName << "' "
<< _(" Numeric name: ") << i->_numericName << endl;
++count;
}
break;
}
case CurrentOperatorInfo:
{
OPInfo opi = m->getCurrentOPInfo();
cout << "<CURROP0>"
<< _(" Long name: '") << opi._longName << "' "
<< _(" Short name: '") << opi._shortName << "' "
<< _(" Numeric name: ") << opi._numericName
<< _(" Mode: ");
switch (opi._mode)
{
case AutomaticOPMode: cout << _("automatic"); break;
case ManualOPMode: cout << _("manual"); break;
case DeregisterOPMode: cout << _("deregister"); break;
case ManualAutomaticOPMode: cout << _("manual/automatic"); break;
}
cout << endl;
break;
}
case FacilityLockStateInfo:
{
int count = 0;
vector<string> fclc = m->getFacilityLockCapabilities();
for (vector<string>::iterator i = fclc.begin(); i != fclc.end(); ++i)
if (*i != "AB" && *i != "AG" && *i != "AC")
{
cout << "<FLSTAT" << count << "> '" << *i << "'";
try
{
if (m->getFacilityLockStatus(*i, VoiceFacility))
cout << _(" Voice");
}
catch (GsmException &e)
{
cout << _(" unknown");
}
try
{
if (m->getFacilityLockStatus(*i, DataFacility))
cout << _(" Data");
}
catch (GsmException &e)
{
cout << _(" unknown");
}
try
{
if (m->getFacilityLockStatus(*i, FaxFacility))
cout << _(" Fax");
}
catch (GsmException &e)
{
cout << _(" unknown");
}
cout << endl;
++count;
}
break;
}
case FacilityLockCapabilityInfo:
{
cout << "<FLCAP0> ";
vector<string> fclc = m->getFacilityLockCapabilities();
for (vector<string>::iterator i = fclc.begin(); i != fclc.end(); ++i)
cout << "'" << *i << "' ";
cout << endl;
break;
}
case PasswordInfo:
{
vector<PWInfo> pwi = m->getPasswords();
int count = 0;
for (vector<PWInfo>::iterator i = pwi.begin(); i != pwi.end(); ++i)
{
cout << "<PW" << count << "> '"
<< i->_facility << "' " << i->_maxPasswdLen << endl;
++count;
}
break;
}
case PINInfo:
{
cout << "<PIN0> " << m->getPINStatus() << endl;
break;
}
case CLIPInfo:
{
cout << "<CLIP0> " << (m->getNetworkCLIP() ? _("on") : _("off")) << endl;
break;
}
case CallForwardingInfo:
{
for (int r = 0; r < 4; ++r)
{
string text;
switch (r)
{
case 0: text = _("UnconditionalReason"); break;
case 1: text = _("MobileBusyReason"); break;
case 2: text = _("NoReplyReason"); break;
case 3: text = _("NotReachableReason"); break;
}
ForwardInfo voice, fax, data;
m->getCallForwardInfo((ForwardReason)r, voice, fax, data);
cout << "<FORW" << r << ".";
printForwardReason("0> " + text + _(" Voice"), voice);
cout << "<FORW" << r << ".";
printForwardReason("1> " + text + _(" Data"), data);
cout << "<FORW" << r << ".";
printForwardReason("2> " + text + _(" Fax"), fax);
}
break;
}
case BatteryInfo:
{
cout << "<BATT0> ";
int bcs = m->getBatteryChargeStatus();
switch (bcs)
{
case 0: cout << _("0 ME is powered by the battery") << endl; break;
case 1: cout << _("1 ME has a battery connected, but is not powered by it")
<< endl; break;
case 2: cout << _("2 ME does not have a battery connected") << endl; break;
case 3:
cout << _("3 Recognized power fault, calls inhibited") << endl;
break;
}
cout << "<BATT1> " << m->getBatteryCharge() << endl;
break;
}
case BitErrorInfo:
{
cout << "<BITERR0> " << m->getBitErrorRate() << endl;
break;
}
case SCAInfo:
{
cout << "<SCA0> " << m->getServiceCentreAddress() << endl;
break;
}
case CharSetInfo:
{
cout << "<CSET0> ";
vector<string> cs = m->getSupportedCharSets();
for (vector<string>::iterator i = cs.begin(); i != cs.end(); ++i)
cout << "'" << *i << "' ";
cout << endl;
cout << "<CSET1> '" << m->getCurrentCharSet() << "'" << endl;
break;
}
case SignalInfo:
{
cout << "<SIG0> " << m->getSignalStrength() << endl;
break;
}
default:
assert(0);
break;
}
}
// convert facility class string of the form "", "all", or any combination
// of "v" (voice), "d" (data), or "f" (fax) to numeric form
FacilityClass strToFacilityClass(string facilityClassS)
{
facilityClassS = lowercase(facilityClassS);
FacilityClass facilityClass = (FacilityClass)0;
if (facilityClassS == "all" || facilityClassS == "")
return (FacilityClass)ALL_FACILITIES;
// OR in facility class bits
for (unsigned int i = 0; i < facilityClassS.length(); ++i)
if (facilityClassS[i] == 'v')
facilityClass = (FacilityClass)(facilityClass | VoiceFacility);
else if (facilityClassS[i] == 'd')
facilityClass = (FacilityClass)(facilityClass | DataFacility);
else if (facilityClassS[i] == 'f')
facilityClass = (FacilityClass)(facilityClass | FaxFacility);
else
throw GsmException(
stringPrintf(_("unknown facility class parameter '%c'"),
facilityClassS[i]), ParameterError);
return facilityClass;
}
// check if argc - optind is in range min..max
// throw exception otherwise
void checkParamCount(int optind, int argc, int min, int max)
{
int paramCount = argc - optind;
if (paramCount < min)
throw GsmException(stringPrintf(_("not enough parameters, minimum number "
"of parameters is %d"), min),
ParameterError);
else if (paramCount > max)
throw GsmException(stringPrintf(_("too many parameters, maximum number "
"of parameters is %d"), max),
ParameterError);
}
// *** main program
int main(int argc, char *argv[])
{
try
{
// handle command line options
string device = "/dev/mobilephone";
string operation;
string baudrate;
string initString = DEFAULT_INIT_STRING;
bool swHandshake = false;
int opt;
int dummy;
while((opt = getopt_long(argc, argv, "I:o:d:b:hvX", longOpts, &dummy))
!= -1)
switch (opt)
{
case 'X':
swHandshake = true;
break;
case 'I':
initString = optarg;
break;
case 'd':
device = optarg;
break;
case 'o':
operation = optarg;
break;
case 'b':
baudrate = optarg;
break;
case 'v':
cerr << argv[0] << stringPrintf(_(": version %s [compiled %s]"),
VERSION, __DATE__) << endl;
exit(0);
break;
case 'h':
cerr << argv[0] << _(": [-b baudrate][-d device][-h]"
"[-I init string][-o operation]\n"
" [-v][-X]{parameters}") << endl
<< endl
<< _(" -b, --baudrate baudrate to use for device "
"(default: 38400)")
<< endl
<< _(" -d, --device sets the destination device to "
"connect to") << endl
<< _(" -h, --help prints this message") << endl
<< _(" -I, --init device AT init sequence") << endl
<< _(" -o, --operation operation to perform on the mobile \n"
" phone with the specified parameters")
<< endl
<< _(" -v, --version prints version and exits") << endl
<< _(" -X, --xonxoff switch on software handshake") << endl
<< endl
<< _(" parameters parameters to use for the operation\n"
" (if an operation is given) or\n"
" a specification which kind of\n"
" information to read from the mobile "
"phone")
<< endl << endl
<< _("Refer to gsmctl(1) for details on the available parameters"
" and operations.")
<< endl << endl;
exit(0);
break;
case '?':
throw GsmException(_("unknown option"), ParameterError);
break;
}
// open the port and ME/TA
m = new MeTa(new
#ifdef WIN32
Win32SerialPort
#else
UnixSerialPort
#endif
(device,
baudrate == "" ?
DEFAULT_BAUD_RATE :
baudRateStrToSpeed(baudrate),
initString, swHandshake));
if (operation == "")
{ // process info parameters
for (int i = optind; i < argc; ++i)
{
string param = lowercase(argv[i]);
if (param == "all")
for (int ip = MeInfo; ip <= SignalInfo; ++ip)
printInfo((InfoParameter)ip);
else if (param == "me")
printInfo(MeInfo);
else if (param == "fun")
printInfo(FunctionalityInfo);
else if (param == "op")
printInfo(OperatorInfo);
else if (param == "currop")
printInfo(CurrentOperatorInfo);
else if (param == "flstat")
printInfo(FacilityLockStateInfo);
else if (param == "flcap")
printInfo(FacilityLockCapabilityInfo);
else if (param == "pw")
printInfo(PasswordInfo);
else if (param == "pin")
printInfo(PINInfo);
else if (param == "clip")
printInfo(CLIPInfo);
else if (param == "forw")
printInfo(CallForwardingInfo);
else if (param == "batt")
printInfo(BatteryInfo);
else if (param == "biterr")
printInfo(BitErrorInfo);
else if (param == "sig")
printInfo(SignalInfo);
else if (param == "sca")
printInfo(SCAInfo);
else if (param == "cset")
printInfo(CharSetInfo);
else
throw GsmException(
stringPrintf(_("unknown information parameter '%s'"),
param.c_str()),
ParameterError);
}
}
else
{ // process operation
operation = lowercase(operation);
if (operation == "dial")
{
// dial: number
checkParamCount(optind, argc, 1, 1);
m->dial(argv[optind]);
// wait for keypress from stdin
char c;
read(1, &c, 1);
}
else if (operation == "on")
{
m->setFunctionalityLevel(1);
}
else if (operation == "off")
{
m->setFunctionalityLevel(0);
}
else if (operation == "pin")
{
// pin: PIN
checkParamCount(optind, argc, 1, 1);
m->setPIN(argv[optind]);
}
else if (operation == "setop")
{
// setop: opmode numeric FIXME allow long and numeric too
checkParamCount(optind, argc, 2, 2);
string opmodeS = lowercase(argv[optind]);
OPModes opmode;
if (opmodeS == "automatic")
opmode = AutomaticOPMode;
else if (opmodeS == "manual")
opmode = ManualOPMode;
else if (opmodeS == "deregister")
opmode = DeregisterOPMode;
else if (opmodeS == "manualautomatic")
opmode = ManualAutomaticOPMode;
else
throw GsmException(stringPrintf(_("unknown opmode parameter '%s'"),
opmodeS.c_str()), ParameterError);
m->setCurrentOPInfo(opmode, "" , "", checkNumber(argv[optind + 1]));
}
else if (operation == "lock")
{
// lock: facility [facilityclass] [passwd]
checkParamCount(optind, argc, 1, 3);
string passwd = (argc - optind == 3) ?
(string)argv[optind + 2] : (string)"";
m->lockFacility(argv[optind],
(argc - optind >= 2) ?
strToFacilityClass(argv[optind + 1]) :
(FacilityClass)ALL_FACILITIES,
passwd);
}
else if (operation == "unlock")
{
// unlock: facility [facilityclass] [passwd]
checkParamCount(optind, argc, 1, 3);
string passwd = argc - optind == 3 ? argv[optind + 2] : "";
m->unlockFacility(argv[optind],
(argc - optind >= 2) ?
strToFacilityClass(argv[optind + 1]) :
(FacilityClass)ALL_FACILITIES,
passwd);
}
else if (operation == "setpw")
{
// set password: facility oldpasswd newpasswd
checkParamCount(optind, argc, 1, 3);
string oldPasswd = argc - optind >= 2 ? argv[optind + 1] : "";
string newPasswd = argc - optind == 3 ? argv[optind + 2] : "";
m->setPassword(argv[optind], oldPasswd, newPasswd);
}
else if (operation == "forw")
{
// call forwarding: mode reason number [facilityclass] [forwardtime]
checkParamCount(optind, argc, 2, 5);
// get optional parameters facility class and forwardtime
int forwardTime = argc - optind == 5 ? checkNumber(argv[optind + 4]) :
NOT_SET;
FacilityClass facilityClass =
argc - optind >= 4 ? strToFacilityClass(argv[optind + 3]) :
(FacilityClass)ALL_FACILITIES;
// get forward reason
string reasonS = lowercase(argv[optind + 1]);
ForwardReason reason;
if (reasonS == "unconditional")
reason = UnconditionalReason;
else if (reasonS == "mobilebusy")
reason = MobileBusyReason;
else if (reasonS == "noreply")
reason = NoReplyReason;
else if (reasonS == "notreachable")
reason = NotReachableReason;
else if (reasonS == "all")
reason = AllReasons;
else if (reasonS == "allconditional")
reason = AllConditionalReasons;
else
throw GsmException(
stringPrintf(_("unknown forward reason parameter '%s'"),
reasonS.c_str()), ParameterError);
// get mode
string modeS = lowercase(argv[optind]);
ForwardMode mode;
if (modeS == "disable")
mode = DisableMode;
else if (modeS == "enable")
mode = EnableMode;
else if (modeS == "register")
mode = RegistrationMode;
else if (modeS == "erase")
mode = ErasureMode;
else
throw GsmException(
stringPrintf(_("unknown forward mode parameter '%s'"),
modeS.c_str()), ParameterError);
m->setCallForwarding(reason, mode,
(argc - optind >= 3) ? argv[optind + 2] : "",
"", // subaddr
facilityClass, forwardTime);
}
else if (operation == "setsca")
{
// set sca: number
checkParamCount(optind, argc, 1, 1);
m->setServiceCentreAddress(argv[optind]);
}
else if (operation == "cset")
{
// set charset: string
checkParamCount(optind, argc, 1, 1);
m->setCharSet(argv[optind]);
}
else
throw GsmException(stringPrintf(_("unknown operation '%s'"),
operation.c_str()), ParameterError);
}
}
catch (GsmException &ge)
{
cerr << argv[0] << _("[ERROR]: ") << ge.what() << endl;
return 1;
}
return 0;
}

View File

@ -0,0 +1,507 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsmpb.cc
// *
// * Purpose: phonebook management program
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 24.6.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_nls.h>
#include <string>
#ifdef WIN32
#include <gsmlib/gsm_win32_serial.h>
#else
#include <gsmlib/gsm_unix_serial.h>
#include <unistd.h>
#endif
#if defined(HAVE_GETOPT_LONG) || defined(WIN32)
#include <getopt.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <gsmlib/gsm_me_ta.h>
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_sorted_phonebook.h>
#include <iostream>
using namespace std;
using namespace gsmlib;
#ifdef HAVE_GETOPT_LONG
static struct option longOpts[] =
{
{"xonxoff", no_argument, (int*)NULL, 'X'},
{"phonebook", required_argument, (int*)NULL, 'p'},
{"init", required_argument, (int*)NULL, 'I'},
{"destination", required_argument, (int*)NULL, 'd'},
{"source", required_argument, (int*)NULL, 's'},
{"destination-backend", required_argument, (int*)NULL, 'D'},
{"source-backend", required_argument, (int*)NULL, 'S'},
{"baudrate", required_argument, (int*)NULL, 'b'},
{"charset", required_argument, (int*)NULL, 't'},
{"copy", no_argument, (int*)NULL, 'c'},
{"synchronize", no_argument, (int*)NULL, 'y'},
{"help", no_argument, (int*)NULL, 'h'},
{"version", no_argument, (int*)NULL, 'v'},
{"verbose", no_argument, (int*)NULL, 'V'},
{"indexed", no_argument, (int*)NULL, 'i'},
{(char*)NULL, 0, (int*)NULL, 0}
};
#else
#define getopt_long(argc, argv, options, longopts, indexptr) \
getopt(argc, argv, options)
#endif
// insert those entries from sourcePhonebook into destPhonebook
// that are not already present in destPhonebook
void insertNotPresent(SortedPhonebookRef sourcePhonebook,
SortedPhonebookRef destPhonebook,
bool indexed, bool verbose)
{
for (SortedPhonebookBase::iterator i = sourcePhonebook->begin();
i != sourcePhonebook->end(); ++i)
{
pair<SortedPhonebookBase::iterator, SortedPhonebookBase::iterator> range;
if (indexed)
{
int index = i->index();
range = destPhonebook->equal_range(index);
}
else
{
string text = i->text();
range = destPhonebook->equal_range(text);
}
// do nothing if the entry is already present in the destination
bool alreadyPresent = false;
for (SortedPhonebookBase::iterator j = range.first;
j != range.second; ++j)
{
i->setUseIndex(indexed);
if (i->telephone() == j->telephone())
{
alreadyPresent = true;
break;
}
}
// ... else insert it
if (! alreadyPresent)
{
if (verbose)
{
cout << stringPrintf(_("inserting '%s' tel# %s"),
i->text().c_str(), i->telephone().c_str());
if (indexed)
cout << stringPrintf(_(" (index #%d)"), i->index());
cout << endl;
}
i->setUseIndex(indexed);
destPhonebook->insert(*i); // insert
}
}
}
// update those entries in destPhonebook, that
// - have the same name as one entry in destPhonebook
// - but have a different telephone number
// this is only done if the name in question is unique in the destPhonebook
// the case of several entries having the same in the sourcePhonebook
// is handled - only the first is considered for updating
void updateEntries(SortedPhonebookRef sourcePhonebook,
SortedPhonebookRef destPhonebook,
bool verbose)
{
bool firstLoop = true;
string lastText;
for (SortedPhonebookBase::iterator i = sourcePhonebook->begin();
i != sourcePhonebook->end(); ++i)
{
string text = i->text();
if (! firstLoop && text != lastText)
{
pair<SortedPhonebookBase::iterator,
SortedPhonebookBase::iterator> range =
destPhonebook->equal_range(text);
SortedPhonebookBase::iterator first = range.first;
if (first != destPhonebook->end() && range.second == ++first)
{ // just one text in the destPhonebook
if (! (*range.first == *i)) // overwrite if different in destination
{
if (verbose)
cout << stringPrintf(_("updating '%s' tel# %s to new tel# %s"),
range.first->text().c_str(),
range.first->telephone().c_str(),
i->telephone().c_str())
<< endl;
*range.first = *i;
}
}
lastText = text;
}
firstLoop = false;
}
}
// the same but for indexed phonebooks
void updateEntriesIndexed(SortedPhonebookRef sourcePhonebook,
SortedPhonebookRef destPhonebook,
bool verbose)
{
for (SortedPhonebookBase::iterator i = sourcePhonebook->begin();
i != sourcePhonebook->end(); ++i)
{
int index = i->index();
SortedPhonebookBase::iterator j = destPhonebook->find(index);
if (j != destPhonebook->end())
{ // index present in the destPhonebook
if (! (*j == *i)) // overwrite if different in destination
{
if (verbose)
cout << stringPrintf(_("updating '%s' tel# %s to new tel# %s"
"(index %d)"),
j->text().c_str(),
j->telephone().c_str(),
i->telephone().c_str(), i->index())
<< endl;
*j = *i;
}
}
}
}
// delete those entries from destPhonebook, that are not present
// in sourcePhonebook
void deleteNotPresent(SortedPhonebookRef sourcePhonebook,
SortedPhonebookRef destPhonebook,
bool indexed, bool verbose)
{
for (SortedPhonebookBase::iterator i = destPhonebook->begin();
i != destPhonebook->end(); ++i)
{
pair<SortedPhonebookBase::iterator, SortedPhonebookBase::iterator> range;
if (indexed)
{
int index = i->index();
range = sourcePhonebook->equal_range(index);
}
else
{
string text = i->text();
range = sourcePhonebook->equal_range(text);
}
bool found = false;
for (SortedPhonebookBase::iterator j = range.first;
j != range.second; ++j)
{
i->setUseIndex(indexed);
if (j->telephone() == i->telephone())
{
found = true;
break;
}
}
if (! found)
{
if (verbose)
{
cout << stringPrintf(_("deleting '%s' tel# %s"),
i->text().c_str(), i->telephone().c_str());
if (indexed)
cout << stringPrintf(_(" (index #%d)"), i->index());
cout << endl;
}
destPhonebook->erase(i);
#ifdef BUGGY_MAP_ERASE
deleteNotPresent(sourcePhonebook, destPhonebook, indexed, verbose);
return;
#endif
}
}
}
// *** main program
int main(int argc, char *argv[])
{
try
{
// handle command line options
string destination;
string source;
string destinationBackend;
string sourceBackend;
string baudrate;
bool doSynchronize = true;
string phonebook;
SortedPhonebookRef sourcePhonebook, destPhonebook;
bool verbose = false;
bool indexed = false;
string initString = DEFAULT_INIT_STRING;
bool swHandshake = false;
string charSet;
Ref<MeTa> sourceMeTa, destMeTa;
int opt;
int dummy;
while((opt = getopt_long(argc, argv, "I:p:s:d:b:cyhvViD:S:Xt:", longOpts,
&dummy))
!= -1)
switch (opt)
{
case 'X':
swHandshake = true;
break;
case 'I':
initString = optarg;
break;
case 'V':
verbose = true;
break;
case 'p':
phonebook = optarg;
break;
case 'd':
destination = optarg;
break;
case 's':
source = optarg;
break;
case 'D':
destinationBackend = optarg;
break;
case 'S':
sourceBackend = optarg;
break;
case 'b':
baudrate = optarg;
break;
case 't':
charSet = optarg;
break;
case 'c':
doSynchronize = false;
break;
case 'i':
indexed = true;
break;
case 'y':
doSynchronize = true;
break;
case 'v':
cerr << argv[0] << stringPrintf(_(": version %s [compiled %s]"),
VERSION, __DATE__) << endl;
exit(0);
break;
case 'h':
cerr << argv[0] << _(": [-b baudrate][-c][-d device or file][-h]"
"[-I init string]\n"
" [-p phonebook name][-s device or file]"
"[-t charset][-v]"
"[-V][-y][-X]") << endl
<< endl
<< _(" -b, --baudrate baudrate to use for device "
"(default: 38400)")
<< endl
<< _(" -c, --copy copy source entries to destination")
<< endl
<< _(" -d, --destination sets the destination device to "
"connect \n"
" to, or the file to write") << endl
<< _(" -D, --destination-backend sets the destination backend")
<< endl
<< _(" -h, --help prints this message") << endl
<< _(" -i, --index takes index positions into account")
<< endl
<< _(" -I, --init device AT init sequence") << endl
<< _(" -p, --phonebook name of phonebook to use") << endl
<< _(" -s, --source sets the source device to connect to,\n"
" or the file to read") << endl
<< _(" -t, --charset sets the character set to use for\n"
" phonebook entries") << endl
<< _(" -S, --source-backend sets the source backend")
<< endl
<< _(" -v, --version prints version and exits") << endl
<< _(" -V, --verbose print detailed progress messages")
<< endl
<< _(" -X, --xonxoff switch on software handshake") << endl
<< _(" -y, --synchronize synchronize destination with source\n"
" entries (destination is overwritten)\n"
" (see gsmpb(1) for details)")
<< endl << endl;
exit(0);
break;
case '?':
throw GsmException(_("unknown option"), ParameterError);
break;
}
// check if all parameters all present
if (destination == "" || source == "")
throw GsmException(_("both source and destination must be given"),
ParameterError);
// start accessing source mobile phone or file
if (sourceBackend != "")
sourcePhonebook =
CustomPhonebookRegistry::createPhonebook(sourceBackend, source);
else if (source == "-")
sourcePhonebook = new SortedPhonebook(true, indexed);
else if (isFile(source))
sourcePhonebook = new SortedPhonebook(source, indexed);
else
{
if (phonebook == "")
throw GsmException(_("phonebook name must be given"), ParameterError);
sourceMeTa = new MeTa(new
#ifdef WIN32
Win32SerialPort
#else
UnixSerialPort
#endif
(source,
baudrate == "" ? DEFAULT_BAUD_RATE :
baudRateStrToSpeed(baudrate), initString,
swHandshake));
if (charSet != "")
sourceMeTa->setCharSet(charSet);
sourcePhonebook =
new SortedPhonebook(sourceMeTa->getPhonebook(phonebook));
}
// make sure destination.c_str file exists
if (destination != "")
{
try
{
ofstream f(destination.c_str(), ios::out | ios::app);
}
catch (exception)
{
}
}
// start accessing destination mobile phone or file
if (destinationBackend != "")
destPhonebook =
CustomPhonebookRegistry::createPhonebook(destinationBackend,
destination);
else if (destination == "-")
destPhonebook = new SortedPhonebook(false, indexed);
else if (isFile(destination))
destPhonebook = new SortedPhonebook(destination, indexed);
else
{
if (phonebook == "")
throw GsmException(_("phonebook name must be given"), ParameterError);
destMeTa = new MeTa(new
#ifdef WIN32
Win32SerialPort
#else
UnixSerialPort
#endif
(destination,
baudrate == "" ? DEFAULT_BAUD_RATE :
baudRateStrToSpeed(baudrate), initString,
swHandshake));
if (charSet != "")
destMeTa->setCharSet(charSet);
PhonebookRef destPb = destMeTa->getPhonebook(phonebook);
// check maximum lengths of source text and phonenumber when writing to
// mobile phone
unsigned int maxTextLen = destPb->getMaxTextLen();
unsigned int maxTelLen = destPb->getMaxTelephoneLen();
for (SortedPhonebookBase::iterator i = sourcePhonebook->begin();
i != sourcePhonebook->end(); ++i)
if (i->text().length() > maxTextLen)
throw GsmException(
stringPrintf(_("text '%s' is too large to fit into destination "
"(maximum size %d characters)"),
i->text().c_str(), maxTextLen),
ParameterError);
else if (i->telephone().length() > maxTelLen)
throw GsmException(
stringPrintf(_("phone number '%s' is too large to fit into "
"destination (maximum size %d characters)"),
i->telephone().c_str(), maxTelLen),
ParameterError);
// read phonebook
destPhonebook = new SortedPhonebook(destPb);
}
// now do the actual work
if (doSynchronize)
{ // synchronizing
if (indexed)
{
sourcePhonebook->setSortOrder(ByIndex);
destPhonebook->setSortOrder(ByIndex);
// for an explanation see below
updateEntriesIndexed(sourcePhonebook, destPhonebook, verbose);
deleteNotPresent(sourcePhonebook, destPhonebook, true, verbose);
insertNotPresent(sourcePhonebook, destPhonebook, true, verbose);
}
else
{
sourcePhonebook->setSortOrder(ByText);
destPhonebook->setSortOrder(ByText);
// the following is done to avoid superfluous writes to the TA
// (that takes time) and keep updated (ie. telephone number changed)
// entries at the same place
// 1. update entries in place where just the number changed
updateEntries(sourcePhonebook, destPhonebook, verbose);
// 2. delete those that are not present anymore
deleteNotPresent(sourcePhonebook, destPhonebook, false, verbose);
// 3. insert the new ones
insertNotPresent(sourcePhonebook, destPhonebook, false, verbose);
}
}
else
{ // copying
destPhonebook->clear();
for (SortedPhonebookBase::iterator i = sourcePhonebook->begin();
i != sourcePhonebook->end(); ++i)
{
if (verbose)
{
cout << stringPrintf(_("inserting '%s' tel# %s"),
i->text().c_str(), i->telephone().c_str());
if (indexed)
cout << stringPrintf(_(" (index #%d)"), i->index());
cout << endl;
}
destPhonebook->insert(*i);
}
}
}
catch (GsmException &ge)
{
cerr << argv[0] << _("[ERROR]: ") << ge.what() << endl;
return 1;
}
return 0;
}

View File

@ -0,0 +1,257 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsmsendsms.cc
// *
// * Purpose: GSM sms send program
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 16.7.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_nls.h>
#include <string>
#ifdef WIN32
#include <gsmlib/gsm_win32_serial.h>
#else
#include <gsmlib/gsm_unix_serial.h>
#include <unistd.h>
#endif
#if defined(HAVE_GETOPT_LONG) || defined(WIN32)
#include <getopt.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <gsmlib/gsm_me_ta.h>
#include <gsmlib/gsm_util.h>
#include <iostream>
using namespace std;
using namespace gsmlib;
// options
#ifdef HAVE_GETOPT_LONG
static struct option longOpts[] =
{
{"requeststat", no_argument, (int*)NULL, 'r'},
{"xonxoff", no_argument, (int*)NULL, 'X'},
{"sca", required_argument, (int*)NULL, 'C'},
{"device", required_argument, (int*)NULL, 'd'},
{"init", required_argument, (int*)NULL, 'I'},
{"concatenate", required_argument, (int*)NULL, 'c'},
{"baudrate", required_argument, (int*)NULL, 'b'},
{"test", no_argument, (int*)NULL, 't'},
{"help", no_argument, (int*)NULL, 'h'},
{"version", no_argument, (int*)NULL, 'v'},
{(char*)NULL, 0, (int*)NULL, 0}
};
#else
#define getopt_long(argc, argv, options, longopts, indexptr) \
getopt(argc, argv, options)
#endif
// convert /r and /n to CR and LF
static string unescapeString(char *line)
{
string result;
bool escaped = false;
int index = 0;
while (line[index] != 0 &&
line[index] != CR && line[index] != LF)
{
if (escaped)
{
escaped = false;
if (line[index] == 'r')
result += CR;
else if (line[index] == 'n')
result += LF;
else if (line[index] == '\\')
result += '\\';
else
result += line[index];
}
else
if (line[index] == '\\')
escaped = true;
else
result += line[index];
++index;
}
return result;
}
// *** main program
int main(int argc, char *argv[])
{
try
{
// handle command line options
string device = "/dev/mobilephone";
bool test = false;
string baudrate;
Ref<GsmAt> at;
string initString = DEFAULT_INIT_STRING;
bool swHandshake = false;
bool requestStatusReport = false;
// service centre address (set on command line)
string serviceCentreAddress;
MeTa *m = NULL;
string concatenatedMessageIdStr;
int concatenatedMessageId = -1;
int opt;
int dummy;
while((opt = getopt_long(argc, argv, "c:C:I:d:b:thvXr", longOpts, &dummy))
!= -1)
switch (opt)
{
case 'c':
concatenatedMessageIdStr = optarg;
break;
case 'C':
serviceCentreAddress = optarg;
break;
case 'X':
swHandshake = true;
break;
case 'I':
initString = optarg;
break;
case 'd':
device = optarg;
break;
case 'b':
baudrate = optarg;
break;
case 't':
test = true;
break;
case 'r':
requestStatusReport = true;
break;
case 'v':
cerr << argv[0] << stringPrintf(_(": version %s [compiled %s]"),
VERSION, __DATE__) << endl;
exit(0);
break;
case 'h':
cerr << argv[0] << _(": [-b baudrate][-c concatenatedID]"
"[-C sca][-d device][-h][-I init string]\n"
" [-t][-v][-X] phonenumber [text]") << endl
<< endl
<< _(" -b, --baudrate baudrate to use for device "
"(default: 38400)")
<< endl
<< _(" -c, --concatenate ID for concatenated SMS messages")
<< endl
<< _(" -C, --sca SMS service centre address") << endl
<< _(" -d, --device sets the destination device to connect "
"to") << endl
<< _(" -h, --help prints this message") << endl
<< _(" -I, --init device AT init sequence") << endl
<< _(" -r, --requeststat request SMS status report") << endl
<< _(" -t, --test convert text to GSM alphabet and "
"vice\n"
" versa, no SMS message is sent") << endl
<< _(" -v, --version prints version and exits")
<< endl
<< _(" -X, --xonxoff switch on software handshake") << endl
<< endl
<< _(" phonenumber recipient's phone number") << endl
<< _(" text optional text of the SMS message\n"
" if omitted: read from stdin")
<< endl << endl;
exit(0);
break;
case '?':
throw GsmException(_("unknown option"), ParameterError);
break;
}
if (! test)
{
// open the port and ME/TA
Ref<Port> port = new
#ifdef WIN32
Win32SerialPort
#else
UnixSerialPort
#endif
(device,
baudrate == "" ? DEFAULT_BAUD_RATE :
baudRateStrToSpeed(baudrate),
initString, swHandshake);
// switch message service level to 1
// this enables acknowledgement PDUs
m = new MeTa(port);
m->setMessageService(1);
at = new GsmAt(*m);
}
// check parameters
if (optind == argc)
throw GsmException(_("phone number and text missing"), ParameterError);
if (optind + 2 < argc)
throw GsmException(_("more than two parameters given"), ParameterError);
if (concatenatedMessageIdStr != "")
concatenatedMessageId = checkNumber(concatenatedMessageIdStr);
// get phone number
string phoneNumber = argv[optind];
// get text
string text;
if (optind + 1 == argc)
{ // read from stdin
char s[1000];
cin.get(s, 1000);
text = unescapeString(s);
if (text.length() > 160)
throw GsmException(_("text is larger than 160 characters"),
ParameterError);
}
else
text = argv[optind + 1];
if (test)
cout << gsmToLatin1(latin1ToGsm(text)) << endl;
else
{
// send SMS
Ref<SMSSubmitMessage> submitSMS = new SMSSubmitMessage();
// set service centre address in new submit PDU if requested by user
if (serviceCentreAddress != "")
{
Address sca(serviceCentreAddress);
submitSMS->setServiceCentreAddress(sca);
}
submitSMS->setStatusReportRequest(requestStatusReport);
Address destAddr(phoneNumber);
submitSMS->setDestinationAddress(destAddr);
if (concatenatedMessageId == -1)
m->sendSMSs(submitSMS, text, true);
else
m->sendSMSs(submitSMS, text, false, concatenatedMessageId);
}
}
catch (GsmException &ge)
{
cerr << argv[0] << _("[ERROR]: ") << ge.what() << endl;
return 1;
}
return 0;
}

View File

@ -0,0 +1,723 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsmsmsd.cc
// *
// * Purpose: SMS receiver daemon
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 5.6.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_nls.h>
#include <string>
#ifdef WIN32
#include <io.h>
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_win32_serial.h>
#define popen _popen
#define pclose _pclose
#else
#include <gsmlib/gsm_unix_serial.h>
#include <unistd.h>
#include <dirent.h>
#include <syslog.h>
#endif
#if defined(HAVE_GETOPT_LONG) || defined(WIN32)
#include <getopt.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <fstream>
#include <iostream>
#include <gsmlib/gsm_me_ta.h>
#include <gsmlib/gsm_event.h>
#include <cstring>
using namespace std;
using namespace gsmlib;
#ifdef HAVE_GETOPT_LONG
static struct option longOpts[] =
{
{"requeststat", no_argument, (int*)NULL, 'r'},
{"direct", no_argument, (int*)NULL, 'D'},
{"xonxoff", no_argument, (int*)NULL, 'X'},
{"init", required_argument, (int*)NULL, 'I'},
{"store", required_argument, (int*)NULL, 't'},
{"device", required_argument, (int*)NULL, 'd'},
{"spool", required_argument, (int*)NULL, 's'},
{"sent", required_argument, (int*)NULL, 'S'},
{"failed", required_argument, (int*)NULL, 'F'},
{"priorities", required_argument, (int*)NULL, 'P'},
#ifndef WIN32
{"syslog", no_argument, (int*)NULL, 'L'},
#endif
{"sca", required_argument, (int*)NULL, 'C'},
{"flush", no_argument, (int*)NULL, 'f'},
{"concatenate", required_argument, (int*)NULL, 'c'},
{"action", required_argument, (int*)NULL, 'a'},
{"baudrate", required_argument, (int*)NULL, 'b'},
{"help", no_argument, (int*)NULL, 'h'},
{"version", no_argument, (int*)NULL, 'v'},
{(char*)NULL, 0, (int*)NULL, 0}
};
#else
#define getopt_long(argc, argv, options, longopts, indexptr) \
getopt(argc, argv, options)
#endif
// my ME
static MeTa *me = NULL;
string receiveStoreName; // store name for received SMSs
// service centre address (set on command line)
static string serviceCentreAddress;
// ID if concatenated messages should be sent
static int concatenatedMessageId = -1;
// signal handler for terminate signal
bool terminateSent = false;
void terminateHandler(int signum)
{
terminateSent = true;
}
// local class to handle SMS events
struct IncomingMessage
{
// used if new message is put into store
int _index; // -1 means message want send directly
string _storeName;
// used if SMS message was sent directly to TA
SMSMessageRef _newSMSMessage;
// used if CB message was sent directly to TA
CBMessageRef _newCBMessage;
// used in both cases
GsmEvent::SMSMessageType _messageType;
IncomingMessage() : _index(-1) {}
};
vector<IncomingMessage> newMessages;
class EventHandler : public GsmEvent
{
public:
// inherited from GsmEvent
void SMSReception(SMSMessageRef newMessage,
SMSMessageType messageType);
void CBReception(CBMessageRef newMessage);
void SMSReceptionIndication(string storeName, unsigned int index,
SMSMessageType messageType);
virtual ~EventHandler() {}
};
void EventHandler::SMSReception(SMSMessageRef newMessage,
SMSMessageType messageType)
{
IncomingMessage m;
m._messageType = messageType;
m._newSMSMessage = newMessage;
newMessages.push_back(m);
}
void EventHandler::CBReception(CBMessageRef newMessage)
{
IncomingMessage m;
m._messageType = GsmEvent::CellBroadcastSMS;
m._newCBMessage = newMessage;
newMessages.push_back(m);
}
void EventHandler::SMSReceptionIndication(string storeName, unsigned int index,
SMSMessageType messageType)
{
IncomingMessage m;
m._index = index;
if (receiveStoreName != "" && ( storeName == "MT" || storeName == "mt"))
m._storeName = receiveStoreName;
else
m._storeName = storeName;
m._messageType = messageType;
newMessages.push_back(m);
}
// execute action on string
void doAction(string action, string result)
{
if (action != "")
{
FILE *fd = popen(action.c_str(), "w");
if (fd == NULL)
throw GsmException(stringPrintf(_("could not execute '%s'"),
action.c_str()), OSError);
fputs(result.c_str(), fd);
if (ferror(fd))
throw GsmException(stringPrintf(_("error writing to '%s'"),
action.c_str()), OSError);
pclose(fd);
}
else
// default if no action: output on stdout
cout << result << endl;
}
// send all SMS messages in spool dir
bool requestStatusReport = false;
void sendSMS(string spoolDirBase, string sentDirBase, string failedDirBase,
unsigned int priority, bool enableSyslog, Ref<GsmAt> at)
{
string spoolDir = spoolDirBase;
string sentDir = sentDirBase;
string failedDir = failedDirBase;
if ( priority >= 1 )
{
spoolDir = spoolDirBase + stringPrintf(_("%d"),priority);
sentDir = sentDirBase + stringPrintf(_("%d"),priority);
failedDir = failedDirBase + stringPrintf(_("%d"),priority);
}
if ( priority > 1 )
sendSMS(spoolDirBase, sentDirBase, failedDirBase, priority-1, enableSyslog, at);
if (spoolDirBase != "")
{
// look into spoolDir for any outgoing SMS that should be sent
#ifdef WIN32
struct _finddata_t fileInfo;
long fileHandle;
string pattern = spoolDir + "\\*";
fileHandle = _findfirst(pattern.c_str(), &fileInfo);
bool moreFiles = fileHandle != -1L;
#else
DIR *dir = opendir(spoolDir.c_str());
if (dir == (DIR*)NULL)
throw GsmException(
stringPrintf(_("error when calling opendir('%s')"
"(errno: %d/%s)"),
spoolDir.c_str(), errno, strerror(errno)),
OSError);
#endif
#ifdef WIN32
while (moreFiles)
{
if (strcmp(fileInfo.name, ".") != 0 &&
strcmp(fileInfo.name, "..") != 0)
#else
struct dirent *entry;
while ((entry = readdir(dir)) != (struct dirent*)NULL)
if (strcmp(entry->d_name, ".") != 0 &&
strcmp(entry->d_name, "..") != 0)
#endif
{
if ( priority > 1 )
sendSMS(spoolDirBase, sentDirBase, failedDirBase, priority-1, enableSyslog, at);
// read in file
// the first line is interpreted as the phone number
// the rest is the message
#ifdef WIN32
string filename = spoolDir + "\\" + fileInfo.name;
#else
string filename = spoolDir + "/" + entry->d_name;
#endif
ifstream ifs(filename.c_str());
if (! ifs)
#ifndef WIN32
if (enableSyslog)
{
syslog(LOG_WARNING, "Could not open SMS spool file %s",
filename.c_str());
if (failedDirBase != "") {
string failedfilename = failedDir + "/" + entry->d_name;
rename(filename.c_str(),failedfilename.c_str());
}
continue;
}
else
#endif
throw GsmException(
stringPrintf(_("count not open SMS spool file %s"),
filename.c_str()), ParameterError);
char phoneBuf[1001];
ifs.getline(phoneBuf, 1000);
for(int i=0;i<1000;i++)
if(phoneBuf[i]=='\t' || phoneBuf[i]==0)
{ // ignore everything after a <TAB> in the phone number
phoneBuf[i]=0;
break;
}
string text;
while (! ifs.eof())
{
char c;
ifs.get(c);
text += c;
}
ifs.close();
// remove trailing newline/linefeed
while (text[text.length() - 1] == '\n' ||
text[text.length() - 1] == '\r')
text = text.substr(0, text.length() - 1);
// send the message
string phoneNumber(phoneBuf);
Ref<SMSSubmitMessage> submitSMS = new SMSSubmitMessage();
// set service centre address in new submit PDU if requested by user
if (serviceCentreAddress != "")
{
Address sca(serviceCentreAddress);
submitSMS->setServiceCentreAddress(sca);
}
submitSMS->setStatusReportRequest(requestStatusReport);
Address destAddr(phoneNumber);
submitSMS->setDestinationAddress(destAddr);
try
{
if (concatenatedMessageId == -1)
me->sendSMSs(submitSMS, text, true);
else
{
// maximum for concatenatedMessageId is 255
if (concatenatedMessageId > 256)
concatenatedMessageId = 0;
me->sendSMSs(submitSMS, text, false, concatenatedMessageId++);
}
#ifndef WIN32
if (enableSyslog)
syslog(LOG_NOTICE, "Sent SMS to %s from file %s", phoneBuf, filename.c_str());
#endif
if (sentDirBase != "") {
#ifdef WIN32
string sentfilename = sentDir + "\\" + fileInfo.name;
#else
string sentfilename = sentDir + "/" + entry->d_name;
#endif
rename(filename.c_str(),sentfilename.c_str());
} else {
unlink(filename.c_str());
}
}
catch (GsmException &me)
{
#ifndef WIN32
if (enableSyslog)
syslog(LOG_WARNING, "Failed sending SMS to %s from file %s: %s", phoneBuf,
filename.c_str(), me.what());
else
#endif
cerr << "Failed sending SMS to " << phoneBuf << " from "
<< filename << ": " << me.what() << endl;
if (failedDirBase != "") {
#ifdef WIN32
string failedfilename = failedDir + "\\" + fileInfo.name;
#else
string failedfilename = failedDir + "/" + entry->d_name;
#endif
rename(filename.c_str(),failedfilename.c_str());
}
}
#ifdef WIN32
}
moreFiles = _findnext(fileHandle, &fileInfo) == 0;
#endif
}
#ifdef WIN32
_findclose(fileHandle);
#else
closedir(dir);
#endif
}
}
#ifndef WIN32
void syslogExit(int exitcode, int *dummy)
{
syslog(LOG_NOTICE, "exited (exit %d)",exitcode);
}
#endif
// *** main program
int main(int argc, char *argv[])
{
bool enableSyslog = false;
try
{
string device = "/dev/mobilephone";
string action;
string baudrate;
bool enableSMS = true;
bool enableCB = true;
bool enableStat = true;
bool flushSMS = false;
bool onlyReceptionIndication = true;
string spoolDir;
string sentDir = "";
string failedDir = "";
unsigned int priorities = 0;
string initString = DEFAULT_INIT_STRING;
bool swHandshake = false;
string concatenatedMessageIdStr;
int opt;
int dummy;
while((opt = getopt_long(argc, argv, "c:C:I:t:fd:a:b:hvs:S:F:P:LXDr",
longOpts, &dummy)) != -1)
switch (opt)
{
case 'c':
concatenatedMessageIdStr = optarg;
break;
case 'r':
requestStatusReport = true;
break;
case 'D':
onlyReceptionIndication = false;
break;
case 'X':
swHandshake = true;
break;
case 'I':
initString = optarg;
break;
case 't':
receiveStoreName = optarg;
break;
case 'd':
device = optarg;
break;
case 'C':
serviceCentreAddress = optarg;
break;
case 's':
spoolDir = optarg;
break;
case 'L':
enableSyslog = true;
break;
case 'S':
sentDir = optarg;
break;
case 'F':
failedDir = optarg;
break;
case 'P':
priorities = abs(atoi(optarg));
break;
case 'f':
flushSMS = true;
break;
case 'a':
action = optarg;
break;
case 'b':
baudrate = optarg;
break;
case 'v':
cerr << argv[0] << stringPrintf(_(": version %s [compiled %s]"),
VERSION, __DATE__) << endl;
exit(0);
break;
case 'h':
cerr << argv[0] << _(": [-a action][-b baudrate][-C sca][-d device]"
"[-f][-h][-I init string]\n"
" [-s spool dir][-t][-v]{sms_type}")
<< endl << endl
<< _(" -a, --action the action to execute when an SMS "
"arrives\n"
" (SMS is send to stdin of action)")
<< endl
<< _(" -b, --baudrate baudrate to use for device "
"(default: 38400)")
<< endl
<< _(" -c, --concatenate start ID for concatenated SMS messages")
<< endl
<< _(" -C, --sca SMS service centre address") << endl
<< _(" -d, --device sets the device to connect to") << endl
<< _(" -D, --direct enable direct routing of SMSs") << endl
<< _(" -f, --flush flush SMS from store") << endl
<< _(" -F, --failed directory to move failed SMS to,") << endl
<< _(" if unset, the SMS will be deleted") << endl
<< _(" -h, --help prints this message") << endl
<< _(" -I, --init device AT init sequence") << endl
#ifndef WIN32
<< _(" -L, --syslog log errors and information to syslog")
<< endl
#endif
<< _(" -P, --priorities number of priority levels to use,") << endl
<< _(" (default: none)") << endl
<< _(" -r, --requeststat request SMS status report") << endl
<< _(" -s, --spool spool directory for outgoing SMS")
<< endl
<< _(" -S, --sent directory to move sent SMS to,") << endl
<< _(" if unset, the SMS will be deleted") << endl
<< _(" -t, --store name of SMS store to use for flush\n"
" and/or temporary SMS storage") << endl
<< endl
<< _(" -v, --version prints version and exits") << endl
<< _(" -X, --xonxoff switch on software handshake") << endl
<< endl
<< _(" sms_type may be any combination of") << endl << endl
<< _(" sms, no_sms controls reception of normal SMS")
<< endl
<< _(" cb, no_cb controls reception of cell broadcast"
" messages") << endl
<< _(" stat, no_stat controls reception of status reports")
<< endl << endl
<< _(" default is \"sms cb stat\"") << endl << endl
<< _("If no action is given, the SMS is printed to stdout")
<< endl << endl
<< _("If -P is given, it activates the priority system and sets the") << endl
<< _("number or levels to use. For every level, there must be directories") << endl
<< _("named <spool directory>+<priority level>.") << endl
<< _("For example \"-P 2 -s queue -S send -F failed\" needs the following") <<endl
<< _("directories: queue1/ queue2/ send1/ send2/ failed1/ failed2/") <<endl
<< _("Before sending one SMS from queue2, all pending SMS from queue1") <<endl
<< _("will be sent.") <<endl
<< endl << endl;
exit(0);
break;
case '?':
throw GsmException(_("unknown option"), ParameterError);
break;
}
// find out which kind of message to route
for (int i = optind; i < argc; ++i)
{
string s = lowercase(argv[i]);
if (s == "sms")
enableSMS = true;
else if (s == "no_sms")
enableSMS = false;
else if (s == "cb")
enableCB = true;
else if (s == "no_cb")
enableCB = false;
else if (s == "stat")
enableStat = true;
else if (s == "no_stat")
enableStat = false;
}
// check parameters
if (concatenatedMessageIdStr != "")
concatenatedMessageId = checkNumber(concatenatedMessageIdStr);
// register signal handler for terminate signal
#ifndef WIN32
struct sigaction terminateAction;
terminateAction.sa_handler = terminateHandler;
sigemptyset(&terminateAction.sa_mask);
terminateAction.sa_flags = SA_RESTART;
if (sigaction(SIGINT, &terminateAction, NULL) != 0 ||
sigaction(SIGTERM, &terminateAction, NULL) != 0)
#else
if(signal(SIGINT, terminateHandler) == SIG_ERR ||
signal(SIGTERM, terminateHandler) == SIG_ERR)
#endif
throw GsmException(
stringPrintf(_("error when calling sigaction() (errno: %d/%s)"),
errno, strerror(errno)),
OSError);
// open GSM device
me = new MeTa(new
#ifdef WIN32
Win32SerialPort
#else
UnixSerialPort
#endif
(device,
baudrate == "" ? DEFAULT_BAUD_RATE :
baudRateStrToSpeed(baudrate), initString,
swHandshake));
// if flush option is given get all SMS from store and dispatch them
if (flushSMS)
{
if (receiveStoreName == "")
throw GsmException(_("store name must be given for flush option"),
ParameterError);
SMSStoreRef store = me->getSMSStore(receiveStoreName);
for (SMSStore::iterator s = store->begin(); s != store->end(); ++s)
if (! s->empty())
{
string result = _("Type of message: ");
switch (s->message()->messageType())
{
case SMSMessage::SMS_DELIVER:
result += _("SMS message\n");
break;
case SMSMessage::SMS_SUBMIT_REPORT:
result += _("submit report message\n");
break;
case SMSMessage::SMS_STATUS_REPORT:
result += _("status report message\n");
break;
}
result += s->message()->toString();
doAction(action, result);
store->erase(s);
}
}
// set default SMS store if -t option was given or
// read from ME otherwise
if (receiveStoreName == "")
{
string dummy1, dummy2;
me->getSMSStore(dummy1, dummy2, receiveStoreName );
}
else
me->setSMSStore(receiveStoreName, 3);
// switch message service level to 1
// this enables SMS routing to TA
me->setMessageService(1);
// switch on SMS routing
me->setSMSRoutingToTA(enableSMS, enableCB, enableStat,
onlyReceptionIndication);
// register event handler to handle routed SMSs, CBMs, and status reports
me->setEventHandler(new EventHandler());
// wait for new messages
bool exitScheduled = false;
while (1)
{
#ifdef WIN32
::timeval timeoutVal;
timeoutVal.tv_sec = 5;
timeoutVal.tv_usec = 0;
me->waitEvent((gsmlib::timeval *)&timeoutVal);
#else
struct timeval timeoutVal;
timeoutVal.tv_sec = 5;
timeoutVal.tv_usec = 0;
me->waitEvent(&timeoutVal);
#endif
// if it returns, there was an event or a timeout
while (newMessages.size() > 0)
{
// get first new message and remove it from the vector
SMSMessageRef newSMSMessage = newMessages.begin()->_newSMSMessage;
CBMessageRef newCBMessage = newMessages.begin()->_newCBMessage;
GsmEvent::SMSMessageType messageType =
newMessages.begin()->_messageType;
int index = newMessages.begin()->_index;
string storeName = newMessages.begin()->_storeName;
newMessages.erase(newMessages.begin());
// process the new message
string result = _("Type of message: ");
switch (messageType)
{
case GsmEvent::NormalSMS:
result += _("SMS message\n");
break;
case GsmEvent::CellBroadcastSMS:
result += _("cell broadcast message\n");
break;
case GsmEvent::StatusReportSMS:
result += _("status report message\n");
break;
}
if (! newSMSMessage.isnull())
result += newSMSMessage->toString();
else if (! newCBMessage.isnull())
result += newCBMessage->toString();
else
{
SMSStoreRef store = me->getSMSStore(storeName);
store->setCaching(false);
if (messageType == GsmEvent::CellBroadcastSMS)
result += (*store.getptr())[index].cbMessage()->toString();
else
result += (*store.getptr())[index].message()->toString();
store->erase(store->begin() + index);
}
// call the action
doAction(action, result);
}
// if no new SMS came in and program exit was scheduled, then exit
if (exitScheduled)
exit(0);
// handle terminate signal
if (terminateSent)
{
exitScheduled = true;
// switch off SMS routing
try
{
me->setSMSRoutingToTA(false, false, false);
}
catch (GsmException &ge)
{
// some phones (e.g. Motorola Timeport 260) don't allow to switch
// off SMS routing which results in an error. Just ignore this.
}
// the AT sequences involved in switching of SMS routing
// may yield more SMS events, so go round the loop one more time
}
// send spooled SMS
if (! terminateSent)
sendSMS(spoolDir, sentDir, failedDir, priorities, enableSyslog, me->getAt());
}
}
catch (GsmException &ge)
{
cerr << argv[0] << _("[ERROR]: ") << ge.what() << endl;
if (ge.getErrorClass() == MeTaCapabilityError)
cerr << argv[0] << _("[ERROR]: ")
<< _("(try setting sms_type, please refer to gsmsmsd manpage)")
<< endl;
// switch off message routing, so that following invocations of gsmsmd
// are not swamped with message deliveries while they start up
if (me != NULL)
{
try
{
me->setSMSRoutingToTA(false, false, false);
}
catch (GsmException &ge)
{
// some phones (e.g. Motorola Timeport 260) don't allow to switch
// off SMS routing which results in an error. Just ignore this.
}
}
return 1;
}
return 0;
}

View File

@ -0,0 +1,434 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsmsmsstore.cc
// *
// * Purpose: SMS store management program
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 4.8.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_nls.h>
#include <string>
#include <ctype.h>
#ifdef WIN32
#include <gsmlib/gsm_win32_serial.h>
#else
#include <gsmlib/gsm_unix_serial.h>
#include <unistd.h>
#endif
#if defined(HAVE_GETOPT_LONG) || defined(WIN32)
#include <getopt.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <gsmlib/gsm_me_ta.h>
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_sorted_sms_store.h>
#include <iostream>
using namespace std;
using namespace gsmlib;
#ifdef HAVE_GETOPT_LONG
static struct option longOpts[] =
{
{"xonxoff", no_argument, (int*)NULL, 'X'},
{"init", required_argument, (int*)NULL, 'I'},
{"store", required_argument, (int*)NULL, 't'},
{"erase", no_argument, (int*)NULL, 'e'},
{"add", no_argument, (int*)NULL, 'a'},
{"list", no_argument, (int*)NULL, 'l'},
{"destination", required_argument, (int*)NULL, 'd'},
{"source", required_argument, (int*)NULL, 's'},
{"baudrate", required_argument, (int*)NULL, 'b'},
{"sca", required_argument, (int*)NULL, 'C'},
{"copy", no_argument, (int*)NULL, 'c'},
{"delete", no_argument, (int*)NULL, 'x'},
{"backup", no_argument, (int*)NULL, 'k'},
{"help", no_argument, (int*)NULL, 'h'},
{"version", no_argument, (int*)NULL, 'v'},
{"verbose", no_argument, (int*)NULL, 'V'},
{(char*)NULL, 0, (int*)NULL, 0}
};
#else
#define getopt_long(argc, argv, options, longopts, indexptr) \
getopt(argc, argv, options)
#endif
bool verbose = false; // true if --verbose option given
// type of operation to perform
enum Operation {CopyOp = 'c', BackupOp = 'k', DeleteOp = 'x',
AddOp = 'a', ListOp = 'l', NoOp = 0};
// aux function, insert entry only if not already present in dest
void backup(SortedSMSStoreRef destStore, SMSStoreEntry &entry)
{
// the following only works because we know that the default sort order
// is by date
assert(destStore->sortOrder() == ByDate);
Timestamp date = entry.message()->serviceCentreTimestamp();
pair<SortedSMSStore::iterator, SortedSMSStore::iterator> range =
destStore->equal_range(date);
for (SortedSMSStore::iterator j = range.first;
j != range.second; ++j)
if (entry == *j)
// do nothing if the entry is already present in the destination
return;
if (verbose)
cout << stringPrintf(_("inserting entry #%d from source into destination"),
entry.index()) << endl
<< entry.message()->toString();
destStore->insert(entry); // insert
}
// aux function, throw exception if operation != NoOp
void checkNoOp(Operation operation, int opt)
{
if (operation != NoOp)
throw GsmException(stringPrintf(_("incompatible options '%c' and '%c'"),
(char)operation, (char)opt),
ParameterError);
}
// *** main program
int main(int argc, char *argv[])
{
try
{
// handle command line options
string destination;
string source;
string baudrate;
string storeName;
char operation = NoOp;
SortedSMSStoreRef sourceStore, destStore;
bool useIndices = false; // use indices in delete, copy, backup op
string initString = DEFAULT_INIT_STRING;
bool swHandshake = false;
// service centre address (set on command line)
string serviceCentreAddress;
Ref<MeTa> sourceMeTa, destMeTa;
int opt;
int dummy;
while((opt = getopt_long(argc, argv, "I:t:s:d:b:cxlakhvVXC:",
longOpts, &dummy))
!= -1)
switch (opt)
{
case 'C':
serviceCentreAddress = optarg;
break;
case 'X':
swHandshake = true;
break;
case 'I':
initString = optarg;
break;
case 'V':
verbose = true;
break;
case 't':
storeName = optarg;
break;
case 'd':
destination = optarg;
break;
case 's':
source = optarg;
break;
case 'b':
baudrate = optarg;
break;
case 'c':
checkNoOp((Operation)operation, opt);
operation = CopyOp;
break;
case 'x':
checkNoOp((Operation)operation, opt);
operation = DeleteOp;
break;
case 'l':
checkNoOp((Operation)operation, opt);
operation = ListOp;
break;
case 'a':
checkNoOp((Operation)operation, opt);
operation = AddOp;
break;
case 'k':
checkNoOp((Operation)operation, opt);
operation = BackupOp;
break;
case 'v':
cerr << argv[0] << stringPrintf(_(": version %s [compiled %s]"),
VERSION, __DATE__) << endl;
exit(0);
break;
case 'h':
cerr << argv[0] << _(": [-a][-b baudrate][-c][-C sca]"
"[-d device or file]\n"
" [-h][-I init string][-k][-l]"
"[-s device or file]"
"[-t SMS store name]\n [-v][-V][-x][-X]"
"{indices}|[phonenumber text]") << endl
<< endl
<< _(" -a, --add add new SMS submit message\n"
" (phonenumber and text) to destination")
<< endl
<< _(" -b, --baudrate baudrate to use for device "
"(default: 38400)")
<< endl
<< _(" -c, --copy copy source entries to destination\n"
" (if indices are given, "
"copy only these entries)") << endl
<< _(" -C, --sca SMS service centre address") << endl
<< _(" -d, --destination sets the destination device to\n"
" connect to, or the file to write to")
<< endl
<< _(" -h, --help prints this message") << endl
<< _(" -I, --init device AT init sequence") << endl
<< _(" -k, --backup backup new entries to destination\n"
" (if indices are given, "
"copy only these entries)") << endl
<< _(" -l, --list list source to stdout") << endl
<< _(" -s, --source sets the source device to connect to,\n"
" or the file to read") << endl
<< _(" -t, --store name of SMS store to use") << endl
<< _(" -v, --version prints version and exits") << endl
<< _(" -V, --verbose print detailed progress messages")
<< endl
<< _(" -x, --delete delete entries denoted by indices")
<< endl
<< _(" -X, --xonxoff switch on software handshake") << endl
<< endl;
exit(0);
break;
case '?':
throw GsmException(_("unknown option"), ParameterError);
break;
}
// check if parameters are complete
if (operation == NoOp)
throw GsmException(_("no operation option given"), ParameterError);
if (operation == BackupOp || operation == CopyOp)
if (destination.length() == 0 || source.length() == 0)
throw GsmException(_("both source and destination required"),
ParameterError);
if (operation == ListOp)
{
if (destination.length() != 0)
throw GsmException(_("destination must not be given"), ParameterError);
if (source.length() == 0)
throw GsmException(_("source required"), ParameterError);
}
if (operation == AddOp || operation == DeleteOp)
{
if (source.length() != 0)
throw GsmException(_("source must not be given"), ParameterError);
if (destination.length() == 0)
throw GsmException(_("destination required"), ParameterError);
}
if (operation == CopyOp || operation == DeleteOp || operation == BackupOp)
{
// check if all indices are numbers
for (int i = optind; i < argc; ++i)
for (char *pp = argv[i]; *pp != 0; ++pp)
if (! isdigit(*pp))
throw GsmException(stringPrintf(_("expected number, got '%s'"),
argv[i]), ParameterError);
useIndices = optind != argc;
}
else if (operation == AddOp)
{
if (optind + 2 < argc)
throw GsmException(_("more than two parameters given"),
ParameterError);
if (optind + 2 > argc)
throw GsmException(_("not enough parameters given"),
ParameterError);
}
else
if (optind != argc)
throw GsmException(_("unexpected parameters"), ParameterError);
// start accessing source store or file if required by operation
if (operation == CopyOp || operation == BackupOp || operation == ListOp)
if (source == "-")
sourceStore = new SortedSMSStore(true);
else if (isFile(source))
sourceStore = new SortedSMSStore(source);
else
{
if (storeName == "")
throw GsmException(_("store name must be given"), ParameterError);
sourceMeTa = new MeTa(new
#ifdef WIN32
Win32SerialPort
#else
UnixSerialPort
#endif
(source,
baudrate == "" ? DEFAULT_BAUD_RATE :
baudRateStrToSpeed(baudrate), initString,
swHandshake));
sourceStore = new SortedSMSStore(sourceMeTa->getSMSStore(storeName));
}
// make sure destination file exists if specified
// Use isFile() for its exception-throwing properties, and discard
// return value cos we don't care (yet) whether it's a device or a
// regular file.
if (destination != "")
isFile(destination);
// start accessing destination store or file
if (operation == CopyOp || operation == BackupOp || operation == AddOp ||
operation == DeleteOp)
if (destination == "-")
destStore = new SortedSMSStore(false);
else if (isFile(destination))
destStore = new SortedSMSStore(destination);
else
{
if (storeName == "")
throw GsmException(_("store name must be given"), ParameterError);
destMeTa = new MeTa(new
#ifdef WIN32
Win32SerialPort
#else
UnixSerialPort
#endif
(destination,
baudrate == "" ? DEFAULT_BAUD_RATE :
baudRateStrToSpeed(baudrate), initString,
swHandshake));
destStore = new SortedSMSStore(destMeTa->getSMSStore(storeName));
}
// now do the actual work
switch (operation)
{
case BackupOp:
{
sourceStore->setSortOrder(ByIndex); // needed in loop
if (useIndices)
for (int i = optind; i < argc; ++i)
{
SortedSMSStore::iterator j = sourceStore->find(atoi(argv[i]));
if (j == sourceStore->end())
throw GsmException(stringPrintf(_("no index '%s' in source"),
argv[i]), ParameterError);
backup(destStore, *j);
}
else
for (SortedSMSStore::iterator i = sourceStore->begin();
i != sourceStore->end(); ++i)
backup(destStore, *i);
break;
}
case CopyOp:
{
destStore->clear();
if (! useIndices) // copy all entries
{
for (SortedSMSStore::iterator i = sourceStore->begin();
i != sourceStore->end(); ++i)
{
if (verbose)
cout << stringPrintf(_("inserting entry #%d from source "
"into destination"), i->index()) << endl
<< i->message()->toString();
destStore->insert(*i);
}
}
else // copy indexed entries
{
sourceStore->setSortOrder(ByIndex); // needed in loop
for (int i = optind; i < argc; ++i)
{
SortedSMSStore::iterator j = sourceStore->find(atoi(argv[i]));
if (j == sourceStore->end())
throw GsmException(stringPrintf(_("no index '%s' in source"),
argv[i]), ParameterError);
if (verbose)
cout << stringPrintf(_("inserting entry #%d from source into "
"destination"), j->index()) << endl
<< j->message()->toString();
destStore->insert(*j);
}
}
break;
}
case ListOp:
{
for (SortedSMSStore::iterator i = sourceStore->begin();
i != sourceStore->end(); ++i)
cout << stringPrintf(_("index #%d"), i->index()) << endl
<< i->message()->toString();
break;
}
case AddOp:
{
SMSMessageRef sms = new SMSSubmitMessage(argv[optind + 1], argv[optind]);
// set service centre address in new submit PDU if requested by user
if (serviceCentreAddress != "")
{
Address sca(serviceCentreAddress);
sms->setServiceCentreAddress(sca);
}
if (verbose)
cout << _("inserting new entry into destination") << endl
<< sms->toString();
destStore->insert(sms);
break;
}
case DeleteOp:
{
destStore->setSortOrder(ByIndex);
for (int i = optind; i < argc; ++i)
{
int index = atoi(argv[i]);
if (verbose)
{
SortedSMSStore::iterator e = destStore->find(index);
if (e != destStore->end())
cout << stringPrintf(_("deleting entry #%d from destination"),
index) << endl
<< e->message()->toString();
}
if (destStore->erase(index) != 1)
throw GsmException(stringPrintf(_("no index '%s' in destination"),
argv[i]), ParameterError);
}
break;
}
}
}
catch (GsmException &ge)
{
cerr << argv[0] << _("[ERROR]: ") << ge.what() << endl;
return 1;
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,131 @@
dnl *************************************************************************
dnl * GSM TA/ME library
dnl *
dnl * File: configure.in
dnl *
dnl * Purpose: autoconf configure script template
dnl *
dnl * Author: Peter Hofmann (software@pxh.de)
dnl *
dnl * Created: 11.11.1999
dnl *************************************************************************
dnl Process this file with autoconf to produce a configure script.
AC_INIT(gsmlib/gsm_error.h)
dnl Other
AC_CONFIG_AUX_DIR(scripts)
AC_PROG_INSTALL
dnl check for libintl
AC_CHECK_LIB(intl, textdomain)
dnl use config header
AM_CONFIG_HEADER(gsm_config.h)
dnl use automake
AM_INIT_AUTOMAKE(gsmlib, 1.10)
dnl change to no if you want no shared libraries for debugging purposes
AM_ENABLE_SHARED(yes)
dnl use -O2 optimization by default
if test "$CXXFLAGS" = ""; then
CXXFLAGS="-O2"
fi
dnl comment out this line to get extensive debugging output and asserts
dnl CXXFLAGS="-DNDEBUG $CXXFLAGS"
dnl uncomment to get translations without installing gsmlib
dnl CXXFLAGS="-DLOCAL_TRANSLATIONS $CXXFLAGS"
dnl check _REENTRANT in header files
if test x"`egrep _REENTRANT /usr/include/features.h`" != x; then
CXXFLAGS="-D_REENTRANT $CXXFLAGS"
CFLAGS="-D_REENTRANT $CFLAGS"
fi
dnl output all warnings
CXXFLAGS="-Wall $CXXFLAGS"
dnl use libtool
AM_PROG_LIBTOOL
dnl Checks for programs.
AC_PROG_CPP
AC_PROG_CXX
dnl check for gcc 2.95.x
AC_TRY_RUN([
#include <unistd.h>
main()
{
#if defined(__GNUC__) && \
! (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95))
return 1;
#endif
return 0;
}
],,
[echo "need at least gcc 2.95 to compile correctly"
exit 1])
dnl check for alloca
AC_FUNC_ALLOCA
dnl check for getopt_long in the C library
AC_CHECK_LIB(c, getopt_long, AC_DEFINE(HAVE_GETOPT_LONG))
dnl check for alarm in the C library
AC_CHECK_LIB(c, alarm, AC_DEFINE(HAVE_ALARM))
dnl check for netinet/in.h header
AC_CHECK_HEADERS(netinet/in.h)
dnl check for string.h header
AC_CHECK_HEADERS(string.h)
dnl check for libintl.h header
AC_CHECK_HEADERS(libintl.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
dnl check for vsnprintf()
dnl AC_FUNC_VPRINTF
AC_EGREP_HEADER(vsnprintf, stdio.h, AC_DEFINE(HAVE_VSNPRINTF))
dnl checks for builtin data type sizes
AC_CHECK_SIZEOF(unsigned short int, 2)
AC_CHECK_SIZEOF(unsigned long int, 4)
AC_CHECK_SIZEOF(unsigned int, 4)
dnl Project-specific settings
GSM_VERSION="1:4:0"
AC_SUBST(GSM_VERSION)
dnl national language support (NLS)
LINGUAS="de"
ALL_LINGUAS=$LINGUAS
AM_GNU_GETTEXT
dnl set locale dir (FIXME there must be a better way)
_localedir=`eval "echo $datadir/locale"`
if test "$_localedir" = "NONE/share/locale"; then
AC_DEFINE_UNQUOTED(LOCALEDIR, "/usr/local/share/locale")
else
_localedir=`echo \"$_localedir\"`
AC_DEFINE_UNQUOTED(LOCALEDIR, $_localedir)
fi
dnl whether to compile the intl directory
AM_CONDITIONAL(COMPILE_INTL, test x$USE_INCLUDED_LIBINTL = xyes)
AC_OUTPUT(Makefile gsmlib/Makefile tests/Makefile apps/Makefile win32/Makefile
doc/Makefile scripts/Makefile intl/Makefile po/Makefile.in
ext/Makefile,
echo timestamp > stamp-h)
dnl repair Makefile in po subdir
dnl sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile

View File

@ -0,0 +1,3 @@
# /etc/cron.d/gsm-utils: crontab fragment for gsm-utils
*/5 * * * * root if [ -x /usr/bin/gsmsmsrequeue ]; then /usr/bin/gsmsmsrequeue; fi

View File

@ -0,0 +1,13 @@
PHONEDEV=/dev/mobilephone # or /dev/ttyS0 or /dev/ircomm0
BAUDRATE=9600
PIN="" # or 1234
SPOOLDIR=/var/spool/sms
PRIORITIES=3
SMSADMIN=root
SUBJECT="SMS delivery report:"
SMSPROCESSOR="" # or /usr/bin/gsmsmsprocessor
do_accounting () { true; } # it's your turn

View File

@ -0,0 +1,81 @@
#! /bin/sh
### BEGIN INIT INFO
# Provides: gsm-utils
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start daemon at boot time
# Description: Enable service provided by daemon.
### END INIT INFO
#
# /etc/init.d/gsm-utils: Controls the GSM SMS send daemon
#
# written by Matthias Goebl <matthias@goebl.net>
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/bin/gsmsmsd
NAME=gsmsmsd
DESC="GSM SMS send daemon"
test -x $DAEMON || exit 0
PHONEDEV=/dev/mobilephone # or /dev/ttyS0 or /dev/ircomm0
BAUDRATE=9600
PIN="" # or 1234
SMSPROCESSOR="" # or /usr/bin/gsmsmsprocessor
SPOOLDIR=/var/spool/sms
PRIORITIES=3
STARTOPTS=""
SMSUSER="gsmsms:gsmsms"
test -r /etc/default/gsm-utils && . /etc/default/gsm-utils # for overwriting some parameters
OPTIONS="-d $PHONEDEV -b $BAUDRATE -L -P $PRIORITIES"
OPTIONS="$OPTIONS -s $SPOOLDIR/queue -S $SPOOLDIR/sent -F $SPOOLDIR/failed"
test -n "$SMSPROCESSOR" && OPTIONS="$OPTIONS -a $SMSPROCESSOR"
test -n "$SMSUSER" && STARTOPTS="$STARTOPTS --chuid $SMSUSER"
test -r /etc/default/gsm-utils && . /etc/default/gsm-utils # for overwriting OPTIONS
case "$1" in
start)
echo -n "Starting $DESC: "
if [ -n "$PIN" ];then
echo -n "entering PIN.. "
(
# This is ugly.. But if the PIN is already entered, the ME returns
# "ERROR" and makes gsmctl retrying..
/usr/bin/gsmctl -d $PHONEDEV -b $BAUDRATE -I "+cpin=$PIN" &
PID=$!
sleep 3
kill $PID 2>/dev/null
) >/dev/null 2>&1
fi
echo -n "$NAME"
start-stop-daemon --start --quiet --pidfile /var/run/gsm-utils/$NAME.pid \
--make-pidfile --background $STARTOPTS --exec $DAEMON -- $OPTIONS
echo "."
;;
stop)
echo -n "Stopping $DESC: $NAME "
start-stop-daemon --stop --quiet --pidfile /var/run/gsm-utils/$NAME.pid \
--exec $DAEMON
sleep 5
echo "."
;;
restart|force-reload)
echo -n "Restarting $DESC: $NAME"
start-stop-daemon --stop --quiet --pidfile /var/run/gsm-utils/$NAME.pid \
--make-pidfile --background $STARTOPTS --exec $DAEMON -- $OPTIONS
sleep 5
start-stop-daemon --start --quiet --pidfile /var/run/gsm-utils/$NAME.pid \
--make-pidfile --background --exec $DAEMON -- $OPTIONS
echo "."
;;
*)
N=/etc/init.d/gsm-utils
echo "Usage: $N {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0

View File

@ -0,0 +1,48 @@
#! /bin/bash
#
# /usr/bin/gsmsmsrequeue: Re-queues failed SMS
#
# written by Matthias Goebl <matthias@goebl.net>
SPOOLDIR=/var/spool/sms
PRIORITIES=3
SMSADMIN=root
SUBJECT="SMS delivery report:"
send_notify()
{
tmpfile="$SPOOLDIR/tmp/"`basename "$1"`
status="$2"
if mv "$1" "$tmpfile" 2>/dev/null; then
# extract the first tab-separated field after the phone number as
# email-address to send the notification to
mailto=` cat "$tmpfile" | sed -ne '1s/^[^ ]* \([^ ]*\).*/\1/p' `
test -z "$mailto" && mailto="$SMSADMIN"
cat "$tmpfile" | mail -s "$SUBJECT $status" "$mailto"
rm "$tmpfile"
fi
}
do_accounting()
{
true;
}
test -r /etc/default/gsm-utils && . /etc/default/gsm-utils
for p in `seq 1 $PRIORITIES`; do
ls "$SPOOLDIR/failed$p" | while read file; do
if expr "$file" : ".*rrrrrrrrrrrr" >/dev/null; then
send_notify "$SPOOLDIR/failed$p/$file" "failed"
else
# re-queue SMS
mv "$SPOOLDIR/failed$p/$file" "$SPOOLDIR/queue$p/${file}r" 2>/dev/null
fi
done
done
for p in `seq 1 $PRIORITIES`; do
ls "$SPOOLDIR/sent$p" | while read file; do
do_accounting "$SPOOLDIR/sent$p/$file" "sent"
send_notify "$SPOOLDIR/sent$p/$file" "sent"
done
done

View File

@ -0,0 +1,34 @@
#! /bin/bash
#
# /usr/bin/gsmsmsspool: Queues SMS for sending
#
# written by Matthias Goebl <matthias@goebl.net>
SPOOLDIR=/var/spool/sms
PRIORITIES=3
test -r /etc/default/gsm-utils && . /etc/default/gsm-utils
if [ -z "$1" ]; then
echo "Usage: gsmsmsspool NUMBER [MESSAGE]"
exit 1
fi
priority=$PRIORITIES # default priority
test -n "$GSMSMS_PRIORITY" && priority="$GSMSMS_PRIORITY"
mailto=`id -un`
test -n "$GSMSMS_NOTIFY" && mailto="$GSMSMS_NOTIFY"
tmpfile="$SPOOLDIR/tmp/`date +%s`.$$"
umask 022
echo "$1 $mailto" > "$tmpfile"
if [ -n "$2" ]; then
echo "$2" | head -c 160 >> "$tmpfile"
else
head -c 160 >> "$tmpfile"
fi
if [ "`id -un`" = "root" ]; then
chown gsmsms:gsmsms "$tmpfile"
fi
mv "$tmpfile" "$SPOOLDIR/queue$priority/"

View File

@ -0,0 +1,284 @@
gsmlib (1.10-13) unstable; urgency=low
* Ack NMU, Thanks Michael, Christoph & Petter
* debian/control add Homepage:
* Update debian/copyright; gsm-lib/COPYING actually specifies LGPL:
- fixes lintian:copyright-without-copyright-notice
* Update manpages fixes lintian:hyphen-used-as-minus-sign
* Update debian/gsm-utils.init
- fixes lintian:init.d-script-missing-lsb-short-description
* Bug fixes from ubuntu
- Don't install contrib/gsm-utils.init dh_installinit debian/gsm-utils.init
- Create /var/run/gsm-utils
* Add case 'L' to apps/gsmsmsd.cc - thks to Andrew Suffield
- syslog support does not work (Closes: #346240)
* gsm-utils.init really call restart with --stop first
- init script calls --start twice (Closes: #377448)
* Explictly set /bin/bash: gsmsmsspool & gsmsmsrequeue
- bashism in /bin/sh script (Closes: #464981)
- gsmsmsrequeue contains bashism or function error (Closes: #459396)
* Patch apps/gsmsmsstore.cc - thks Isaac Wilcox
- gsmsmsstore device existence check causes problems with RFCOMM
devices (Closes: #340179)
* Only start gsmsmsd if set in /etc/default/gsm-utils. crontab -> examples
- gsmsmsd should be optional / start only if told so in
/etc/default/gsm-utils (Closes: #474093)
* Apply patch from Stefan Katerkamp & Jacob Nevins
- Gsmsendsms fails with SonyEricsson W880 (fix included) (Closes:
#413341)
-- Mark Purcell <msp@debian.org> Mon, 06 Oct 2008 15:01:49 +1100
gsmlib (1.10-12.5) unstable; urgency=low
* Non-maintainer upload.
* Yet another bashism that was later on reported on the old bug report, thus
again closes: #464981
* Also found a shell related problem in debian/rules and fixed it.
* Bumped standard to 3.7.3.
-- Michael Meskes <meskes@debian.org> Mon, 14 Apr 2008 10:48:19 +0200
gsmlib (1.10-12.4) unstable; urgency=low
* Non-maintainer upload.
* Argh, somehow I mananged to upload without fixing the bug completely,
sorry. Added those missing braces, closes: #464981.
-- Michael Meskes <meskes@debian.org> Wed, 09 Apr 2008 14:46:08 +0200
gsmlib (1.10-12.3) unstable; urgency=high
* Non-maintainer upload.
* Removed bashism in contrib/gsmsmsrequeue (Closes: #464981).
-- Michael Meskes <meskes@debian.org> Sun, 06 Apr 2008 15:37:35 +0200
gsmlib (1.10-12.2) unstable; urgency=low
* Non-maintainer upload.
* Fix FTBFS with GCC 4.3: 'strerror' was not declared in this scope, thanks
to Cyril Brulebois for the patch (Closes: #455402).
-- Christoph Berg <myon@debian.org> Fri, 04 Apr 2008 18:01:05 +0200
gsmlib (1.10-12.1) unstable; urgency=low
* Non-maintainer upload to solve release goal.
* Add LSB dependency header to init.d scripts (Closes: #464061).
-- Petter Reinholdtsen <pere@debian.org> Fri, 28 Mar 2008 11:39:20 +0100
gsmlib (1.10-12) unstable; urgency=low
* addgroup --system gsmsms works better. Thanks Jon
* only delete gsmsms on purge
- gsm-utils: deletes and recreates the gsmsms user on each upgrade
(Closes: #346238)
- gsm-utils fails installation / addgroup: The user gsmsms; does
not exist (Closes: #445404)
* lintian cleanup: debian-rules-ignores-make-clean-error substvar-
source-version-is-deprecated
* Scripts are installed +x
- gsm-utils: uselessly installs non-executable scripts into /usr/bin
(Closes: #346230)
* Remove bogus symlink
- gsm-utils: wrong symlink for manpage gsmsiectl.1 (Closes: #322382)
- gsm-utils: gsmsiectl.1 dangling symlink (Closes: #399582)
* debian/gsm-utils.init reload/restart was not calling --stop. Thanks
Barry
- init script calls --start twice (Closes: #377448)
-- Mark Purcell <msp@debian.org> Mon, 08 Oct 2007 21:44:00 +0100
gsmlib (1.10-11) unstable; urgency=low
* Create system group gsmsms - Thanks Emmanuel
- gsm-utils: creates group in non-system gid range (Closes: #353967)
- gsm-utils: postinst should create system grp gsmsms (Closes:
#390266)
* Upgrade to compat 4
* Apply gcc-4.3 patch from Martin
- FTBFS with GCC 4.3: missing #includes (Closes: #417222)
-- Mark Purcell <msp@debian.org> Sat, 29 Sep 2007 18:22:56 +0100
gsmlib (1.10-10) unstable; urgency=low
* FTBFS with G++ 4.1: extra qualifications (Closes: #356109)
-- Mark Purcell <msp@debian.org> Sat, 20 May 2006 21:54:42 +0100
gsmlib (1.10-9) unstable; urgency=low
* library package needs to be renamed (libstdc++ allocator change)
(Closes: #339179)
-- Mark Purcell <msp@debian.org> Mon, 21 Nov 2005 21:19:51 +0000
gsmlib (1.10-8) unstable; urgency=low
* removal of automake1.6 (Closes: #335123)
* fails with dash [bashisms in scripts] (Closes: #309834)
* Update libtool Fixes: gsmlib(GNU/k*BSD): FTBFS: out of date libtool scripts (Closes:
#319688)
* [INTL:de] German PO file corrections (Closes: #314060)
* Fix: old-fsf-address-in-copyright-file
-- Mark Purcell <msp@debian.org> Thu, 3 Nov 2005 22:40:19 +0000
gsmlib (1.10-7) unstable; urgency=low
* C++ 4.0 transition
* Closes: #315864: Missing manpages
* gsm-utils: maintainer-script-needs-depends-on-adduser postinst
-- Mark Purcell <msp@debian.org> Sat, 23 Jul 2005 00:46:31 +1000
gsmlib (1.10-6) unstable; urgency=low
* Rebuild for invalid dependancies
* Closes: #258056: libgsmme 99% cpu usage
- Patch from Emard
* Closes: #274382: FTBFS with gcc-3.4: template-id `operator&lt;
&lt;&gt;' for `bool gsmlib::operator&lt;(const
gsmlib::MapKey&lt;gsmlib::SortedPhonebookBase&gt;&amp;, const
gsmlib::MapKey&lt;gsmlib::SortedPhonebookBase&gt;&amp;)' does not
match any template declaration
- Patch from Andreas Jochens
* Closes: #294251: FTBFS (amd64/gcc-4.0): explicit qualification in
declaration of `bool gsmlib::operator&lt;(const
gsmlib::MapKey&lt;SortedStore&gt;&amp;, const
gsmlib::MapKey&lt;SortedStore&gt;&amp;)'
- Patch from Andreas Jochens
* Closes: #200189: Patch and contribution
+ Added multi-queue-priority-system and syslog patch (Matthias Goebl)
+ Included init, spool and requeue scripts for gsmsmsd (Matthias Goebl)
+ gsmsmsd runs with own user and group (gsmsms:gsmsms) (Matthias Goebl)
-- Mark Purcell <msp@debian.org> Tue, 17 May 2005 11:34:45 +0100
gsmlib (1.10-5) unstable; urgency=low
* Change Section: libdevel
* gsm_unix_serial.cc patch from Daniel Schepler to fix g++-3.3
compliation. Thanks. (Closes: Bug#195151)
-- Mark Purcell <msp@debian.org> Sat, 19 Jul 2003 15:57:28 +1000
gsmlib (1.10-4) unstable; urgency=low
* Include file descriptor leak patch from Edd Dumbill (Closes:
Bug#168475)
* lintian cleanup: description-synopsis-might-not-be-phrased-properly
* lintian cleanup: configure-generated-file-in-source
-- Mark Purcell <msp@debian.org> Sun, 9 Feb 2003 14:04:54 +1100
gsmlib (1.10-3) unstable; urgency=low
* New Maintainer (Closes: Bug#180061). Thanks Mikael for your work.
-- Mark Purcell <msp@debian.org> Sat, 8 Feb 2003 16:55:26 +1100
gsmlib (1.10-2) unstable; urgency=low
* Rebuild to use the new c++ ABI (GCC 3.2)
-- Mikael Hedin <micce@debian.org> Thu, 23 Jan 2003 20:57:50 +0100
gsmlib (1.10-1) unstable; urgency=low
* New upstrem release.
-- Mikael Hedin <micce@debian.org> Wed, 6 Nov 2002 17:44:17 +0100
gsmlib (1.9-2) unstable; urgency=low
* Made new rules for the config.guess/sub update thing (closes: #146865,
#146867).
-- Mikael Hedin <micce@debian.org> Tue, 14 May 2002 09:28:03 +0200
gsmlib (1.9-1) unstable; urgency=low
* New upstream version.
* Use chrpath to get rid of rpaths.
* Add mini-manpage for gsmsiexfer.
* Remove b-d on auto-stuff, we don't use them.
-- Mikael Hedin <micce@debian.org> Mon, 13 May 2002 22:10:28 +0200
gsmlib (1.8-2) unstable; urgency=low
* Removed b-d on gcc 3.0, as they are no longer nessecary.
-- Mikael Hedin <micce@debian.org> Thu, 24 Jan 2002 12:59:07 +0100
gsmlib (1.8-1) unstable; urgency=low
* New upstream version.
* Revert the arch hack, now it should compile with either g++.
* Include the new lib in libgsmme1. Run dh_makeshlibs -V because of this.
* Added info for gsmsiectl in gsmctl(1).
-- Mikael Hedin <micce@debian.org> Wed, 9 Jan 2002 22:38:45 +0100
gsmlib (1.7-2) unstable; urgency=low
* gsm-utils: Added shlibs:Depends (closes: #126127).
* Spelling correction (closes: #124705, #124972)
* Rm libgsmme1.postins, and let dh_makeshlibs take care of ldconfig.
* Made explicit arch list without sparc and arm, they cannot use g++-3.0
right now.
-- Mikael Hedin <micce@debian.org> Sat, 22 Dec 2001 20:27:54 +0100
gsmlib (1.7-1) unstable; urgency=low
* New upstream
* Use gcc-3.0 and g++-3.0, 2.95 doesn't compile.
-- Mikael Hedin <micce@debian.org> Thu, 1 Nov 2001 10:24:33 +0100
gsmlib (1.6-5) unstable; urgency=low
* Updated manpage (closes: #110973)
* Corrected problem with OP status (closes: #110970)
-- Mikael Hedin <micce@debian.org> Sat, 8 Sep 2001 18:12:17 +0200
gsmlib (1.6-4) unstable; urgency=low
* Support DEB_BUILD_OPTIONS
* Changed libgsmme-dev to section devel.
* Reran libtoolize.
* Lots of small patches to compile with g++-3.0. (Closes: #104411)
* Removed dh_testversion.
-- Mikael Hedin <micce@debian.org> Thu, 12 Jul 2001 16:06:23 +0200
gsmlib (1.6-3) unstable; urgency=low
* Various minor corrections.
-- Mikael Hedin <mikael.hedin@irf.se> Thu, 8 Mar 2001 16:24:07 +0100
gsmlib (1.6-2) unstable; urgency=low
* Dont install INSTALL. Correct indentation for libgsmme1 description.
-- Mikael Hedin <mikael.hedin@irf.se> Tue, 6 Mar 2001 14:55:05 +0100
gsmlib (1.6-1) unstable; urgency=low
* New upstream version.
-- Mikael Hedin <mikael.hedin@irf.se> Mon, 29 Jan 2001 17:57:21 +0100
gsmlib (1.5-1) unstable; urgency=low
* Initial Release.
-- Mikael Hedin <mikael.hedin@irf.se> Thu, 14 Dec 2000 01:06:40 +0100

View File

@ -0,0 +1,45 @@
Source: gsmlib
Section: comm
Priority: extra
Maintainer: Mark Purcell <msp@debian.org>
Build-Depends: debhelper (>= 3.0.0), chrpath
Standards-Version: 3.7.3
Homepage: http://www.pxh.de/fs/gsmlib/
Package: libgsmme-dev
Section: libdevel
Architecture: any
Depends: libgsmme1c2a (= ${binary:Version}), libc6-dev
Description: Header files and static libraries for gsmlib
Headers and static libraries for use when compiling programs with
gsmlib.
.
gsmlib is a library for access to a GSM mobile phone using the
standards ETSI GSM 07.07, ETSI GSM 07.05, and others.
Package: libgsmme1c2a
Conflicts: libgsmme1, libgsmme1c102, libgsmme1c2
Replaces: libgsmme1c102, libgsmme1c2
Section: libs
Architecture: any
Depends: ${shlibs:Depends}
Description: GSM mobile phone access library
Library to access GSM mobile phones through GSM modems or IrDA devices.
Features include:
.
* modification of phone books stored in the mobile phone or on the
SIM card
* reading and writing of SMS messages stored in the mobile phone
* sending and reception of SMS messages
.
gsmlib uses standard ETSI GSM 07.07, ETSI GSM 07.05, and others.
Package: gsm-utils
Section: comm
Architecture: any
Depends: ${shlibs:Depends}, adduser
Description: GSM mobile phone access applications
Some simple command line programs to access a GSM mobile phone via
GSM modem or IrDA. Functions include: modification of phone books and
reading, writing, sending and receiving SMS messages. Uses the GSM
standards ETSI GSM 07.07, ETSI GSM 07.05, and others.

View File

@ -0,0 +1,34 @@
This package was debianized by Mikael Hedin <mikael.hedin@irf.se> on
Thu, 14 Dec 2000 01:06:40 +0100.
It was downloaded from http://www.pxh.de/fs/gsmlib/index.html
Upstream Author: Peter Hofmann <software@pxh.de>
ext/gsmsiexfer.cc:// * Author: Christian W. Zuckschwerdt <zany@triq.net>
Copyright:
Copyright (C) 1999-2002 Peter Hofmann <software@pxh.de>
License:
This package is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this package; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
On Debian systems, the complete text of the GNU Lesser General
Public License can be found in `/usr/share/common-licenses/LGPL'.
The Debian packaging is (C) 2000, Mikael Hedin <mikael.hedin@irf.se> and
is licensed under the GPL, see `/usr/share/common-licenses/GPL'.

View File

@ -0,0 +1 @@
/var/run/gsm-utils

View File

@ -0,0 +1,3 @@
# /etc/cron.d/gsm-utils: crontab fragment for gsm-utils
*/5 * * * * root if [ -x /usr/bin/gsmsmsrequeue ]; then /usr/bin/gsmsmsrequeue; fi

View File

@ -0,0 +1,18 @@
PHONEDEV=/dev/mobilephone # or /dev/ttyS0 or /dev/ircomm0
BAUDRATE=9600
PIN="" # or 1234
# RUNGSMSMS: If set to anything other that 'yes', the asterisk init.d script
# will not run. The default is 'yes'.
# You should probaly also install the crontab from /usr/share/doc/gsm-utils/examples
RUNGSMSMS=no
SPOOLDIR=/var/spool/sms
PRIORITIES=3
SMSADMIN=root
SUBJECT="SMS delivery report:"
SMSPROCESSOR="" # or /usr/bin/gsmsmsprocessor
do_accounting () { true; } # it's your turn

View File

@ -0,0 +1,11 @@
var/spool/sms/queue1
var/spool/sms/queue2
var/spool/sms/queue3
var/spool/sms/sent1
var/spool/sms/sent2
var/spool/sms/sent3
var/spool/sms/failed1
var/spool/sms/failed2
var/spool/sms/failed3
var/spool/sms/tmp
var/run/gsm-utils

View File

@ -0,0 +1,4 @@
NEWS
README
TODO
doc/FAQ

View File

@ -0,0 +1,2 @@
contrib/gsm-utils.cron.d
contrib/gsm-utils.init

View File

@ -0,0 +1,87 @@
#! /bin/sh
### BEGIN INIT INFO
# Provides: gsm-utils
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start daemon at boot time
# Description: Enable service provided by daemon.
### END INIT INFO
#
# /etc/init.d/gsm-utils: Controls the GSM SMS send daemon
#
# written by Matthias Goebl <matthias@goebl.net>
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/bin/gsmsmsd
NAME=gsmsmsd
DESC="GSM SMS send daemon"
test -x $DAEMON || exit 0
if [ "$RUNGSMSMS" != "yes" ];then
echo "GSM SMS deamon not yet configured. Edit /etc/default/gsm-utils first."
exit 0
fi
PHONEDEV=/dev/mobilephone # or /dev/ttyS0 or /dev/ircomm0
BAUDRATE=9600
PIN="" # or 1234
SMSPROCESSOR="" # or /usr/bin/gsmsmsprocessor
SPOOLDIR=/var/spool/sms
PRIORITIES=3
STARTOPTS=""
SMSUSER="gsmsms:gsmsms"
test -r /etc/default/gsm-utils && . /etc/default/gsm-utils # for overwriting some parameters
OPTIONS="-d $PHONEDEV -b $BAUDRATE -L -P $PRIORITIES"
OPTIONS="$OPTIONS -s $SPOOLDIR/queue -S $SPOOLDIR/sent -F $SPOOLDIR/failed"
test -n "$SMSPROCESSOR" && OPTIONS="$OPTIONS -a $SMSPROCESSOR"
test -n "$SMSUSER" && STARTOPTS="$STARTOPTS --chuid $SMSUSER"
test -r /etc/default/gsm-utils && . /etc/default/gsm-utils # for overwriting OPTIONS
case "$1" in
start)
echo -n "Starting $DESC: "
if [ -n "$PIN" ];then
echo -n "entering PIN.. "
(
# This is ugly.. But if the PIN is already entered, the ME returns
# "ERROR" and makes gsmctl retrying..
/usr/bin/gsmctl -d $PHONEDEV -b $BAUDRATE -I "+cpin=$PIN" &
PID=$!
sleep 3
kill $PID 2>/dev/null
) >/dev/null 2>&1
fi
echo -n "$NAME"
start-stop-daemon --start --quiet --pidfile /var/run/gsm-utils/$NAME.pid \
--make-pidfile --background $STARTOPTS --exec $DAEMON -- $OPTIONS
echo "."
;;
stop)
echo -n "Stopping $DESC: $NAME "
start-stop-daemon --stop --quiet --pidfile /var/run/gsm-utils/$NAME.pid \
--exec $DAEMON
sleep 5
echo "."
;;
restart|force-reload)
echo -n "Restarting $DESC: $NAME"
start-stop-daemon --stop --quiet --pidfile /var/run/gsm-utils/$NAME.pid \
--make-pidfile --background --exec $DAEMON -- $OPTIONS
sleep 5
start-stop-daemon --start --quiet --pidfile /var/run/gsm-utils/$NAME.pid \
--make-pidfile --background $STARTOPTS --exec $DAEMON -- $OPTIONS
echo "."
;;
*)
N=/etc/init.d/gsm-utils
echo "Usage: $N {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0

View File

@ -0,0 +1,28 @@
#!/bin/sh -e
# create gsmsms group if necessary.
if ! grep -q ^gsmsms: /etc/group; then
# echo Adding system group: gsmsms.
addgroup --system gsmsms
fi
# create gsmsms user if necessary.
if ! grep -q ^gsmsms: /etc/passwd; then
# echo Adding system user: gsmsms.
adduser --system --ingroup gsmsms \
--no-create-home --home /var/spool/sms gsmsms
fi
# allow gsmsms to use serial lines
if ! groups gsmsms | grep -q dialout ; then
adduser gsmsms dialout
fi
# echo Updating spool directory structure: /var/spool/sms
chown -R gsmsms:gsmsms /var/spool/sms /var/run/gsm-utils
chmod 700 /var/spool/sms/*
chmod 750 /var/spool/sms
chmod 730 /var/spool/sms/queue* /var/spool/sms/tmp
# Add the rest automatically..
#DEBHELPER#

View File

@ -0,0 +1,43 @@
#!/bin/sh
# postrm script for #PACKAGE#
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postrm> `remove'
# * <postrm> `purge'
# * <old-postrm> `upgrade' <new-version>
# * <new-postrm> `failed-upgrade' <old-version>
# * <new-postrm> `abort-install'
# * <new-postrm> `abort-install' <old-version>
# * <new-postrm> `abort-upgrade' <old-version>
# * <disappearer's-postrm> `disappear' <overwriter>
# <overwriter-version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
;;
purge)
deluser gsmsms
;;
*)
echo "postrm called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

View File

@ -0,0 +1,29 @@
.\" -*- eval: (nroff-mode) -*-
.de TQ
.br
.ns
.TP \\$1
..
.\" Like TP, but if specified indent is more than half
.\" the current line-length - indent, use the default indent.
.de Tp
.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
.el .TP "\\$1"
..
.TH GSMSIEXFER 1 "" "gsmsiexfer"
.SH NAME
gsmsiexfer \- Siemens ME file transfer program for Siemens phones S25, S35, S45, ME45, SL45
.SH SYNOPSIS
.B gsmsiexfer \-\-help
.PP
.SH DESCRIPTION
\fIgsmsiexer\fP comes with no man page. Try gsmsiexfer \-\-help, or
read the source.
.PP
.SH "SEE ALSO"
.BR gsminfo(7),
.BR gsmctl(1),
.BR gsmsendsms(1),
.BR gsmsmsd(8),
.BR gsmsmsstore(1).

View File

@ -0,0 +1,2 @@
doc/README.developers
doc/README.NLS

View File

@ -0,0 +1,129 @@
#!/usr/bin/make -f
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# shared library versions, option 1
#version=2.0.5
#major=2
# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so
me_version=`ls gsmlib/.libs/libgsmme*.so.* | \
awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'`
me_major=`ls gsmlib/.libs/libgsmme*.so.* | \
awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'`
ex_version=`ls ext/.libs/libgsmext*.so.* | \
awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'`
ex_major=`ls ext/.libs/libgsmext*.so.* | \
awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'`
export DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
export DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
# FOR AUTOCONF 2.13 ONLY
ifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE))
confflags += $(DEB_HOST_GNU_TYPE)
else
confflags += --host $(DEB_BUILD_GNU_TYPE) --build $(DEB_HOST_GNU_TYPE)
endif
ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
CFLAGS += -g
CXXFLAGS += -g
endif
configure: configure-stamp
configure-stamp:
dh_testdir
# Add here commands to configure the package.
CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" INSTALL_PROGRAM=$(INSTALL_PROGRAM) \
./configure $(confflags) --prefix=/usr --mandir=\$${prefix}/share/man \
--infodir=\$${prefix}/share/info
touch configure-stamp
build: configure-stamp build-stamp
build-stamp:
dh_testdir
# Add here commands to compile the package.
$(MAKE)
touch build-stamp
clean:
dh_testdir
dh_testroot
# Add here commands to clean up after the build process.
[ ! -f Makefile ] || $(MAKE) distclean
rm -f build-stamp configure-stamp config.log config.status po/de.gmo
-test -r /usr/share/misc/config.sub && \
cp -f /usr/share/misc/config.sub scripts/config.sub
-test -r /usr/share/misc/config.guess && \
cp -f /usr/share/misc/config.guess scripts/config.guess
dh_clean
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
dh_installdirs -pgsm-utils
# Add here commands to install the package into debian/gsmlib.
$(MAKE) install DESTDIR=$(CURDIR)/debian/tmp
chrpath -d debian/tmp/usr/bin/*
cp contrib/gsmsmsspool contrib/gsmsmsrequeue debian/tmp/usr/bin
# Build architecture-independent files here.
binary-indep: build install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
#
# build libgsmlib${major} package by moving files from gsmlib-dev
#
dh_movefiles -plibgsmme$(me_major)c2a \
usr/lib/libgsmme.so.$(me_major) \
usr/lib/libgsmme.so.$(me_version) \
usr/lib/libgsmext.so.$(ex_major) \
usr/lib/libgsmext.so.$(ex_version) \
usr/share/locale
dh_movefiles -plibgsmme-dev \
usr/include \
usr/lib
dh_movefiles -pgsm-utils \
usr/bin
dh_installdocs
dh_installexamples
dh_installmenu
dh_installinit
dh_installcron
dh_installman -pgsm-utils debian/*.1 debian/tmp/usr/share/man/man*/*
dh_installinfo
dh_installchangelogs ChangeLog
dh_link
dh_strip
dh_compress
dh_fixperms
dh_makeshlibs -V
dh_installdeb
dh_shlibdeps -ldebian/libgsmme1c2a/usr/lib
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure

View File

@ -0,0 +1,2 @@
version=2
http://www.pxh.de/fs/gsmlib/download/content.html gsmlib-(.*)\.tar\.gz

View File

@ -0,0 +1,101 @@
*** 1. I get the error
/usr/local/bin/gsmsmsd [ERROR]: cannot route status report message to TE
Some phones/modems cannot route all kinds of SMS to the TE
(computer). Please try
gsmsmsd no_stat
This is documented in the gsmsmsd manual page.
*** 2. Siemens M20T expects an initial PIN.
For the Siemens M20T an initial PIN must be send once (probably when
it is switched on or the computer is powered on). This PIN is used for
all subsequent invocations of gsmlib-based programs. The trick is to
issue the following program (eg. in the rc-scripts of the operating system):
gsmctl -I "+cpin=<MY PIN>"
*** 3. Sending SMS with or retrieving SMS from my Ericsson SH888 does
not work.
Set the environment variable GSMLIB_SH888_FIX:
export GSMLIB_SH888_FIX=1 (bash)
setenv GSMLIB_SH888_FIX 1 (tcsh)
If it works now, I need your model number. You could just enter
"AT+CGMM" in a terminal program and send me the results. Alternatively
set the environment variable GSMLIB_DEBUG=2 and me the dump.
*** 4. I get the error "ME/TA error 'Unidentified subscriber' (code
28)" when trying to send SMS using gsmsendsms or gsmsmsd.
The SMS service centre address (SCA, the phone number of the centre that is
accepting SMS for delivery) is not set correctly in your phone. There
are three ways to correct this:
1. set the default SCA (example is for Germany T-D1):
gsmctl -o setsca "+491710760000"
2. Use the menus of your phone to set the SMS SCA.
3. Use the option "--sca 1234567" for the gsmsmsd, gsmsmsstore, and
gsmsendsms programs. This tries to set the SCA in the SMS itself (does
not change default SCA) and might not work with all phones.
*** 5. gsmlib works unreliably with my phone.
Try another baudrate, even higher baudrates sometimes work better then
lower ones.
*** 6. On Win32 accessing the COM device fails.
Use COMx: (x is the number of the COM device) instead of the UNIX
device name. If this doesn't work use "\\.\COMx:".
*** 7. Windows 2000 Does Not Support Mapping Virtual COM Ports to
Infrared Ports.
Windows 2000 users should follow the instructions in
support.microsoft.com article Q252795 in order to connect with their
mobile.
*** 8. gcc-compiled shared C++ libraries do not work properly on some
commercial UNIX systems and with older version of gcc.
The symptoms may be that the program dumps core on exceptions (AIX) or that
global constructors are not called (Solaris).
Try to compile gsmlib with
./configure --disable-shared --enable-static
if you encounter strange problems.
*** 9. How to support unicode?
You need 6 steps:
1. set datacodingschema to DCS_SIXTEEN_BIT_ALPHABET
2. set your locale correctly, for example, my locale, china.
setlocale(LC_ALL, "chs");
3. translate MBCS(multiple byte character set) string to unicode string.
wchar_t wstr[ 1000 ];
memset(wstr, 0, 2000);
mbstowcs(wstr, data.c_str(), data.length());
4. get unicode string length.
int wcs_len = wcslen(wstr);
5. change unicode string to net order.
for (int i = 0; i < wcs_len; i++)
wstr[ i ] = htons(wstr[ i ]);
6. put unicode string into pdu.

View File

@ -0,0 +1,33 @@
## Process this file with automake to produce Makefile.in
# *************************************************************************
# * GSM TA/ME library
# *
# * File: Makefile.am
# *
# * Purpose: doc Makefile
# *
# * Author: Peter Hofmann (software@pxh.de)
# *
# * Created: 11.6.1999
# *************************************************************************
man_MANS = gsmsmsd.8 gsmctl.1 gsmpb.1 gsmsendsms.1 gsmsmsstore.1 gsminfo.7
EXTRA_DIST = gsmsmsd.man gsmctl.man gsmpb.man gsmsendsms.man \
gsmsmsstore.man gsmlib.lsm gsminfo.man \
README.NLS README.developers FAQ
%.1: %.man
sed -e "s/##VERSION##/$(VERSION)/g;s/##DATE##/`date`/g" \
$< > $@
%.7: %.man
sed -e "s/##VERSION##/$(VERSION)/g;s/##DATE##/`date`/g" \
$< > $@
%.8: %.man
sed -e "s/##VERSION##/$(VERSION)/g;s/##DATE##/`date`/g" \
$< > $@
clean-local:
rm -f *.1 *.7 *.8

View File

@ -0,0 +1,412 @@
# Makefile.in generated by automake 1.6.3 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# *************************************************************************
# * GSM TA/ME library
# *
# * File: Makefile.am
# *
# * Purpose: doc Makefile
# *
# * Author: Peter Hofmann (software@pxh.de)
# *
# * Created: 11.6.1999
# *************************************************************************
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_HEADER = $(INSTALL_DATA)
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
EXEEXT = @EXEEXT@
OBJEXT = @OBJEXT@
PATH_SEPARATOR = @PATH_SEPARATOR@
AMTAR = @AMTAR@
AS = @AS@
AWK = @AWK@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CPP = @CPP@
CXX = @CXX@
DATADIRNAME = @DATADIRNAME@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
ECHO = @ECHO@
GENCAT = @GENCAT@
GLIBC21 = @GLIBC21@
GMSGFMT = @GMSGFMT@
GSM_VERSION = @GSM_VERSION@
HAVE_LIB = @HAVE_LIB@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INSTOBJEXT = @INSTOBJEXT@
INTLBISON = @INTLBISON@
INTLLIBS = @INTLLIBS@
INTLOBJS = @INTLOBJS@
INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
LIB = @LIB@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIB = @LTLIB@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
MKINSTALLDIRS = @MKINSTALLDIRS@
OBJDUMP = @OBJDUMP@
PACKAGE = @PACKAGE@
POSUB = @POSUB@
RANLIB = @RANLIB@
STRIP = @STRIP@
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
am__include = @am__include@
am__quote = @am__quote@
install_sh = @install_sh@
man_MANS = gsmsmsd.8 gsmctl.1 gsmpb.1 gsmsendsms.1 gsmsmsstore.1 gsminfo.7
EXTRA_DIST = gsmsmsd.man gsmctl.man gsmpb.man gsmsendsms.man \
gsmsmsstore.man gsmlib.lsm gsminfo.man \
README.NLS README.developers FAQ
subdir = doc
mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/gsm_config.h
CONFIG_CLEAN_FILES =
DIST_SOURCES =
NROFF = nroff
MANS = $(man_MANS)
DIST_COMMON = Makefile.am Makefile.in
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu doc/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
man1dir = $(mandir)/man1
install-man1: $(man1_MANS) $(man_MANS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(man1dir)
@list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
for i in $$l2; do \
case "$$i" in \
*.1*) list="$$list $$i" ;; \
esac; \
done; \
for i in $$list; do \
if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
else file=$$i; fi; \
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
case "$$ext" in \
1*) ;; \
*) ext='1' ;; \
esac; \
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
inst=`echo $$inst | sed -e 's/^.*\///'`; \
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \
$(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \
done
uninstall-man1:
@$(NORMAL_UNINSTALL)
@list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
for i in $$l2; do \
case "$$i" in \
*.1*) list="$$list $$i" ;; \
esac; \
done; \
for i in $$list; do \
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
inst=`echo $$inst | sed -e 's/^.*\///'`; \
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \
rm -f $(DESTDIR)$(man1dir)/$$inst; \
done
man7dir = $(mandir)/man7
install-man7: $(man7_MANS) $(man_MANS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(man7dir)
@list='$(man7_MANS) $(dist_man7_MANS) $(nodist_man7_MANS)'; \
l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
for i in $$l2; do \
case "$$i" in \
*.7*) list="$$list $$i" ;; \
esac; \
done; \
for i in $$list; do \
if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
else file=$$i; fi; \
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
case "$$ext" in \
7*) ;; \
*) ext='7' ;; \
esac; \
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
inst=`echo $$inst | sed -e 's/^.*\///'`; \
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man7dir)/$$inst"; \
$(INSTALL_DATA) $$file $(DESTDIR)$(man7dir)/$$inst; \
done
uninstall-man7:
@$(NORMAL_UNINSTALL)
@list='$(man7_MANS) $(dist_man7_MANS) $(nodist_man7_MANS)'; \
l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
for i in $$l2; do \
case "$$i" in \
*.7*) list="$$list $$i" ;; \
esac; \
done; \
for i in $$list; do \
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
inst=`echo $$inst | sed -e 's/^.*\///'`; \
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
echo " rm -f $(DESTDIR)$(man7dir)/$$inst"; \
rm -f $(DESTDIR)$(man7dir)/$$inst; \
done
man8dir = $(mandir)/man8
install-man8: $(man8_MANS) $(man_MANS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(man8dir)
@list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
for i in $$l2; do \
case "$$i" in \
*.8*) list="$$list $$i" ;; \
esac; \
done; \
for i in $$list; do \
if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
else file=$$i; fi; \
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
case "$$ext" in \
8*) ;; \
*) ext='8' ;; \
esac; \
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
inst=`echo $$inst | sed -e 's/^.*\///'`; \
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \
$(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \
done
uninstall-man8:
@$(NORMAL_UNINSTALL)
@list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
for i in $$l2; do \
case "$$i" in \
*.8*) list="$$list $$i" ;; \
esac; \
done; \
for i in $$list; do \
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
inst=`echo $$inst | sed -e 's/^.*\///'`; \
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \
rm -f $(DESTDIR)$(man8dir)/$$inst; \
done
tags: TAGS
TAGS:
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@list='$(DISTFILES)'; for file in $$list; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(MANS)
installdirs:
$(mkinstalldirs) $(DESTDIR)$(man1dir) $(DESTDIR)$(man7dir) $(DESTDIR)$(man8dir)
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool clean-local mostlyclean-am
distclean: distclean-am
distclean-am: clean-am distclean-generic distclean-libtool
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am: install-man
install-exec-am:
install-info: install-info-am
install-man: install-man1 install-man7 install-man8
installcheck-am:
maintainer-clean: maintainer-clean-am
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
uninstall-am: uninstall-info-am uninstall-man
uninstall-man: uninstall-man1 uninstall-man7 uninstall-man8
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
clean-local distclean distclean-generic distclean-libtool \
distdir dvi dvi-am info info-am install install-am install-data \
install-data-am install-exec install-exec-am install-info \
install-info-am install-man install-man1 install-man7 \
install-man8 install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-generic mostlyclean-libtool uninstall \
uninstall-am uninstall-info-am uninstall-man uninstall-man1 \
uninstall-man7 uninstall-man8
%.1: %.man
sed -e "s/##VERSION##/$(VERSION)/g;s/##DATE##/`date`/g" \
$< > $@
%.7: %.man
sed -e "s/##VERSION##/$(VERSION)/g;s/##DATE##/`date`/g" \
$< > $@
%.8: %.man
sed -e "s/##VERSION##/$(VERSION)/g;s/##DATE##/`date`/g" \
$< > $@
clean-local:
rm -f *.1 *.7 *.8
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,72 @@
0 Introduction
--------------
This version of gsmlib contains national language support (NLS) using
the GNU (or OS-supplied) gettext library. gettext eases the handling
of translations of (usually english) output messages to other
languages by introducing the concept of message catalogs.
Message catalogs can exist in various formats. The human-readable and
-editable format is the PO file format. I have written a PO-file for
the german language (de.po). These human-readable files are then
translated to MO files which can be used by the gettext library.
Please refer to the GNU gettext documentation (at the time of this
writing gettext-0.10) for further details.
1 Compiling gsmlib with localized messages
------------------------------------------
Gsmlib is compiled by default with NLS enabled. If you don't want
NLS invoke configure with the option
./configure --disable-nls
2 Adding new message dialogs
----------------------------
1. Edit the ALL_LINGUAS line in "source/configure.in" and add your
language, eg. French:
ALL_LINGUAS="de fr"
2. Execute "autoconf" to create a new "configure" script (possible
problem: incompatible "autoconf")
3. Now issue "./configure" in the "sources" directory.
4. go to the "po" subdirectory
5. do a "touch fr.po" to create an initially empty PO-file.
6. do a "make update-po". This extracts all the strings from the files
listed in "POTFILES" and puts them with empty translations into "fr.po"
(it also updates existing po-Files such as "de.po").
7. Now use the editor of your choice to provide translations in
"fr.po". There is an emacs major mode (po-mode) that eases this
process.
8. now issue "make". This causes an "fr.mo" to be created.
3 Adding new strings to gsmlib source code
------------------------------------------
1. If you add new strings to the gsmlib source code that need
translation enclose them with "_(" and ")" (see gettext documentation
for special cases).
2. go to the "po" directory.
3. do a "make update-po". This updates all existing PO-files (removing
obsolete translations, providing new, emptry entries).
4. Provide translations for the new, empty entries (ideally using
emacs po-mode)
5. now issue "make". This causes up-to-date MO-files to be created.

View File

@ -0,0 +1,138 @@
OVERVIEW
The GSM library is written in C++ and uses the latest C++
features: namespaces, exceptions, the standard template library.
The actual library source code is in the gsmlib subdirectory of
this distribution. The following modules are available:
gsm_alloca.h OS-specific alloca defines
gsm_at.h Utility classes for AT command sequence handling
gsm_error.h Error codes and error handling functions
gsm_event.h Event handler interface
gsm_me_ta.h Mobile Equipment/Terminal Adapter and SMS functions
(ETSI GSM 07.07 and 07.05)
gsm_parser.h Parser to parse MA/TA result strings
gsm_phonebook.h Phonebook management functions
gsm_port.h Abstract port definition
gsm_sms.h SMS functions (ETSI GSM 07.05)
gsm_sms_codec.h Coder and Encoder for SMS TPDUs
gsm_sms_store.h SMS functions, SMS store (ETSI GSM 07.05)
gsm_sorted_phonebook.h Alphabetically sorted phonebook
(residing in files or in the ME)
gsm_sorted_sms_store.h Sorted SMS store
(sorted by address, time or type)
(residing in files or in the ME)
gsm_unix_serial.h UNIX serial port implementation
gsm_util.h Various utilities
REQUIREMENTS
I have used egcs-1.1.2 and libstdc++.so.2.8.0 for compiling the
library and all programs. Older probably don't work because of
missing features.
AVAILABLE DOCUMENTATION
If you want to do your own programming using the GSM library please
refer to the extensively documented header files or to the example
programs in the test or apps subdirectory.
I have used the following documentation to develop this software:
gts_gsm_02.30_v5.2.0.pdf
gts_gsm_03.40_v5.3.0.pdf
gts_gsm_04.11_v5.1.0.pdf
gts_gsm_02.82_v5.0.0.pdf
gts_gsm_03.41_v5.2.0.pdf
gts_gsm_07.05_v5.3.0.pdf
gts_gsm_03.38_v5.3.0.pdf
gts_gsm_04.08_v5.1.0.pdf
gts_gsm_07.07_v5.0.0.pdf
Due to copyright reasons I cannot include this documentation in
this distribution. You can download it from the ETSI website
(www.etsi.org) for free, though.
COMPILATION
The code is automatically compiled without debugging code enabled
(mostly assert()'s).
If there are any problems you can generate a debug version
by issuing
CXXFLAGS="-g" ./configure --disable-shared
To switch on asserts and additional debugging output change the line
CXXFLAGS="-DNEBUG $CXXFLAGS"
in configure.in do
dnl CXXFLAGS="-DNEBUG $CXXFLAGS"
Then regenerate configure by executing autoconf.
You must use at least gcc-2.95.2 to compile gsmlib successfully.
TESTS
The tests directory contains a number of software tests. Two kinds
of test programs are provided: Those, that run without a mobile
phone and those that require a mobile phone to be connected to a
serial port.
No access to mobile phone needed:
runparser.sh Test the parser for AT responses
runsms.sh Test SMS message encoding and decoding routines
runspb.sh Test sorted phonebook module
runssms.sh Test sorted SMS store module
Give mobile phone device as argument:
testsms2 Manipulate SMS store in the mobile phone (read/write)
testgsmlib Test the gsm_me_ta module (readonly)
testpb Dump all phonebooks in the mobile phone to the stdout
(readonly)
testpb2 Manipulate phonebook in the mobile phone (read/write)
The tests that do not require a mobile phone can be executed by
issuing "make check" in the tests subdirectory. The others must be
invoked manually. WARNING: These tests alter the contents of the
mobile phone's phonebook or SMS message memory!!! Make sure, that
you understand what the test does and be prepared for loss of data in
the mobile phone.
HINTS
- By default gsmlib is compiled with NDEBUG set. There are lots
of assert()s all over the library that may help to find problems
in programs that use the library. Disable NDEBUG to get best
debugging support.
CUSTOM BACKENDS
gsmlib now allows custom backends to be defined for sorted phonebooks
and sorted SMS stores. This can be used to store phonebook entries in
relational databases or LDAP servers. The interfaces are defined in
gsm_sorted_phonebook_base.h and gsm_sorted_sms_store_base.h,
respectively.
To register a custom backend (eg. for sorted phonebooks) follow
these steps:
1. Define a subclass of CustomPhonebookFactory.
2. Define a static initializer class in your module that uses the
interface CustomPhonebookRegistry::registerCustomPhonebookFactory()
to make your custom backend available.
3. Link your module to any application that should use your custom
backend. The gsmpb and gsmsmsstore programs are prepared to use the
CustomPhonebookRegistry class to obtain your custom backend
objects.

View File

@ -0,0 +1,683 @@
.TH GSMCTL 8 "##DATE##" "gsmctl v##VERSION##"
.SH NAME
gsmctl, gsmsiectl \- GSM mobile phone control program
.SH SYNOPSIS
.B gsmctl
.RB [\| \-b
.IR baudrate \|]
.RB [\| \-\-baudrate
.IR baudrate\| ]
.RB [ \|\-d
.IR device\| ]
.RB [ \|\-\-device
.IR device\fP ]
.RB [ \|\-h\| ]
.RB [ \|\-\-help\| ]
.RB [ \|\-I
.IR "init string" \|]
.RB [ \|\-\-init
.IR "init string" \|]
.RB [ \|\-v\| ]
.RB [ \|\-\-version\| ]
.RB [ \|\-X\| ]
.RB [ \|\-\-xonxoff\| ]
.BI \-o \ operation
.RB | \ \-\-operation
.IR operation \ |
.I parameters
.PP
.B gsmsiectl
.RB [\| \-b
.IR baudrate \|]
.RB [\| \-\-baudrate
.IR baudrate\| ]
.RB [ \|\-d
.IR device\| ]
.RB [ \|\-\-device
.IR device\fP ]
.RB [ \|\-h\| ]
.RB [ \|\-\-help\| ]
.RB [ \|\-I
.IR "init string" \|]
.RB [ \|\-\-init
.IR "init string" \|]
.RB [ \|\-v\| ]
.RB [ \|\-\-version\| ]
.RB [ \|\-X\| ]
.RB [ \|\-\-xonxoff\| ]
.BI \-o \ operation
.RB | \ \-\-operation
.IR operation \ |
.I parameters
.SH DESCRIPTION
.B gsmctl
can request information from or perform operations on an GSM mobile
phone.
.PP
.B gsmctl
attaches itself to the
.I device
given on the command line (usually an GSM modem) using the specified
.IR baudrate .
If no
.I device
is given, the device
.I /dev/mobilephone
is used. If no
.I baudrate
is given, a default baud rate of 38400 is used.
.PP
.B gsmctl
can be used in to modes: If no
.B \-\-operation
option is given the
.I parameters
specify the status information to be retrieved from
the mobile phone. See the section
.B STATUS INFORMATION
for more details. If an
.B \-\-operation
option is given the requested
.I operation
is performed on the mobile using the
.IR parameters .
See the section
.B OPERATIONS
for more details.
.PP
.B gsmsiectl
is the same program with some extension for Siemens mobile phones.
Some extra
.B OPERATIONS
are available in this case.
.PP
Error messages are printed to the standard error output. If the
program terminates on error the error code 1 is returned.
.SH OPTIONS
.TP
.BI \-b\ baudrate ,\ \-\-baudrate\ baudrate
The baud rate to use. Defaults to 38400.
.TP
.BI \-d\ device ,\ \-\-device\ device
The device to which the GSM modem is connected. The default is
.IR /dev/mobilephone .
.TP
.B \-h,\ \-\-help
Prints an option summary.
.TP
.BI \-I\ "init string" ,\ \-\-init\ "init string"
Initialization string to send to the TA (default: "E0"). Note that the
sequence "ATZ" is sent first.
.TP
.BI \-o\ operation ,\ \-\-operation\ operation
This option is used to perform an operation on the mobile phone. Refer
to the section
.B OPERATIONS
for more information on the available
operations and the
.I parameters
required for each operation.
.TP
.B \-v,\ \-\-version
Prints the program version.
.TP
.B \-X,\ \-\-xonxoff
Uses software handshaking (XON/XOFF) for accessing the device.
.SH STATUS INFORMATION
If called without the
.B \-\-operation
option
.B gsmctl
prints out default mobile phone status information as specified by the
.I parameters
described below:
.TP 7
.B ALL
Prints all available information.
.TP 7
.B BATT
Prints out information about the current battery status. Two lines of
the form "<BATT0> text" and "<BATT1> charge" are printed. Text may be
of "0 ME is powered by the battery", "1 ME has a battery connected,
but is not powered by it", "2 ME does not have a battery connected",
or "3 Recognized power fault, calls inhibited". Charge is a number in
the range 0..100 where 0 means that the battery is empty or not
connected and 100 means full charge.
.TP 7
.B BITERR
Prints information about the current bit error rate. The output is of
form "<BITERR0> value" where value can be of 0..7, 99 (99 means not
available or not detectable).
.TP 7
.B CLIP
This option prints a line of the form "<CLIP0> on" if caller line
identification is turned on in the network, "<CLIP0> off" otherwise.
.TP 7
.B CSET
Display info about charsets. The output is in the form "<CSET0>
available" and "<CSET1> current", which describes the charsets
available and which is current.
.TP 7
.B CURROP
Prints information about the current operator. The output line has the
form "<CURROP0> Long name: \'xxxx\' Short name: \'yyyy\' Numeric Name: zzzz".
.TP 7
.B FLCAP
Prints out the two-letter names of available facility locks. The
meaning of standardized facility lock names is as follows:
.RS
.TP 3
.I CS
Lock control surface (eg. phone keyboard)
.TP 3
.I PS
Lock phone to SIM card (mobile phone asks password when other than
current SIM card inserted)
.TP 3
.I SC
Lock SIM card (SIM asks password in mobile phone power-up and when
this lock command issued)
.TP 3
.I AO
Barr all outgoing calls
.TP 3
.I OI
Barr outgoing international calls
.TP 3
.I OX
Barr outgoing international calls except to home country
.TP 3
.I AI
Barr all incoming calls
.TP 3
.I IR
Barr incoming calls when roaming outside the home country
.TP 3
.I NT
Barr incoming calls from numbers not stored to TA memory
.TP 3
.I NM
Barr incoming calls from numbers not stored to mobile phone memory
.TP 3
.I NS
Barr incoming calls from numbers not stored to SIM memory
.TP 3
.I NA
Barr incoming calls from numbers not stored in Any memory
.TP 3
.I AB
All Barring services (FIXME)
.TP 3
.I AG
All outGoing barring services (FIXME)
.TP 3
.I AC
All inComing barring services (FIXME)
.TP 3
.I FD
SIM fixed dialling memory feature (if PIN2 authentication has not been
done during the current session, PIN2 is required as <passwd>)
.PP
Note that mobile phones may implement facility locks not documented
here.
.RE
.TP 7
.B FLSTAT
Prints information about the status of facility locking in the mobile
phone. For each facility a line of the form "<FLSTATn> \'facilityname\'
classes" is printed. The classes may be "Voice", "Data", and/or "Fax"
depending on the class for which the facility is enabled. If "unknown"
is printed out this means that the TA is not able to report the
status. If the facility is not enabled for any class, no class
identifier is printed. See
.B FLCAP
for information about the available two-letter names of facility
locks.
.TP 7
.B FORW
Prints information about call forwarding enabled in the mobile
phone. For each combination of reason (UnconditionalReason,
MobileBusyReason, NoReplyReason, and NotReachableReason) and class
(Voice, Data, and Fax) a line of the form "<FORWn.m> reason class
number: xxx subaddr: yyy time: zzz" is printed. The time is the number
of seconds to wait before forwarding in case of NoReplyReason.
.TP 7
.B ME
Prints manufacturer, model, revision, and serial number of
the mobile phone (ME = mobile equipment). Output lines are numbered from
"<ME0>" to "<ME3>".
.TP 7
.B OP
Prints information about the currently available mobile network
operators. For each operator an output line of the form "<OPn> status
Long name: \'xxxx\' Short name: \'yyyy\' Numeric name: zzz" is returned
where status may be of:
.RS
.TP 10
.I unknown
The status of the operator is unknown.
.TP
.I current
This is the currently selected operator.
.TP
.I available
This operator is available for selection.
.TP
.I forbidden
This operator is not available for selection, ie. not
accessible with this SIM card.
.RE
.TP 7
.B PIN
Prints information about the current PIN status. The output is of
form "<PIN0> status". Where status can be one of the following lines:
.RS
.TP 10
.I READY
ME is not pending for any password.
.TP
.I SIM PIN
ME is waiting SIM PIN to be given.
.TP
.I SIM PUK
ME is waiting SIM PUK to be given.
.TP
.I PH\-SIM PIN
ME is waiting phone/-to/-SIM card password to be given.
.TP
.I PH/-FSIM PIN
ME is waiting phone/-to/-very first SIM card password to be given.
.TP
.I PH/-FSIM PUK
ME is waiting phone/-to/-very first SIM card unblocking password to be
given.
.TP
.I SIM PIN2
ME is waiting SIM PIN2 to be given.
.TP
.I SIM PUK2
ME is waiting SIM PUK2 to be given.
.TP
.I PH/-NET PIN
ME is waiting network personalisation password to be given.
.TP
.I PH/-NET PUK
ME is waiting network personalisation unblocking password to be given.
.TP
.I PH/-NETSUB PIN
ME is waiting network subset personalisation password to be given.
.RE
.TP 7
.B PW
Facilities in the mobile phone may be protected by passwords (ie. PINs
or PUKs). This option prints out lines of the form "<PWn>
\'facilityname\' len" for each facility for which a facility lock
password exists. See
.B FLCAP
for information about the available two-letter names of facility
locks.
.TP 7
.B SCA
Reports the default SMS service centre address currently set in the
mobile phone.
.TP 7
.B SIG
Prints information about the current network signal
strength. The output is of the form "<SIG0> value". Following values
are possible:
.TP
.po +7
.I 0
-113 dBm or less
.TP
.I 1
-111 dBm
.TP
.I 2...30
-109... -53 dBm (in steps of 2 dBm)
.TP
.I 31
-51 dBm or greater
.TP
.I 99
not known or not detectable
.PP
.po
.SH OPERATIONS
.TP
.BI dial\ number
Dials
.IR number .
After dialling
.B gsmctl
waits for a <CR> keypress to terminate.
.PP
.B forw
.IR mode\ reason\ number\ [\| facilityclass\| ]\ [ forwardtime ]
.RS
Changes the call forwarding behaviour in the network.
.I mode
can be any of:
.RS 3
.I disable
Call forwarding is disabled.
.PP
.I enable
Call forwarding is enabled. The call forwarding reason, number, and
(optionally) forwardtime must be registered beforehand.
.PP
.I register
This registers the call forwarding reason, number, and forwardtime in
the network.
.PP
.I erase
This is the counterpart to register. It erase the call forwarding info
in the network.
.RE
.PP
.I reason
can be any of:
.RS 3
.I unconditional
This applies to every call.
.PP
.I mobilebusy
The mobile phone is busy.
.PP
.I noreply
The call is not answered in \fIforwardtime\fP seconds.
.PP
.I notreachable
Mobile phone cannot be reached (ie. switched off).
.PP
.I all
This refers to all forwarding reasons.
.PP
.I allconditional
This refers to all conditional forward reasons
.RI ( mobilebusy ,\ noreply ,\ notreachable ).
.RE
.PP
.I number
is the number the incoming call is forwarded to. See the explanation
for
.I lock
operation for the meaning of
.IR facilityclass .
The default for
.I forwardtime
is 20 seconds if omitted.
.I forwardtime
can be in the range 1..30.
.RE
.PP
.TP
.BI off
Sets functionality level of the phone to 0 (low functionality). The
effects of this command depend on the phone (eg. sets low power
consumption).
.PP
.TP
.BI on
Sets functionality level of the phone to 1 (high functionality). The
effects of this command depend on the phone.
.PP
.TP
.BI pin\ pin
Sets PIN code. Use
.BI gsmctl\ pin
to get the current pin status.
.PP
.B lock
.IR facility\ [\| facilityclass \|]\ [\| passwd \|]
.RS
Locks the named facility. Use
.BI gsmctl\ flcap
to get a list of supported facilities. The
.I facilityclass
can be any of:
.RS 3
.I all
Voice, data, and fax.
.PP
.I v\ vf\ vd\ f\ fd\ d
Any combination of voice, data and fax.
.RE
.PP
The default is \fIall\fP if \fIfacilityclass\fP is omitted. The
\fIpasswd\fP is password for the facility. If no password is given
this parameter can be omitted.
.RE
.PP
.BI setop\ opmode\ numericname
.RS
Sets the current operator to
.IR numericname .
Use
.BI gsmctl\ op
to get a list of operators with their numeric codes.
.I opmode
can be any of:
.RS 3
.I automatic
.PP
.I manual
.PP
.I deregister
Deregister from network.
.PP
.I manualautomatic
If manual selection fails, automatic mode is entered.
.RE
.RE
.PP
.B setpw
.IR facility\ [\| oldpasswd\| ]\ [\| newpasswd\| ]
.RS
Sets the password for the facility. If one of the passwords is omitted
this means that the facility has no password protection. Passwords are
PIN1, PIN2, PUK etc.
.RE
.TP
.BI setsca\ service\ centre\ address
Sets the default SMS service centre address.
.PP
.B unlock
.IR facility\ [\| facilityclass\| ]\ [ \|passwd\| ]
.RS
This is the reverse operation to \fBlock\fP. See above for a
description of the parameters.
.RE
.PP
.B Extra operators for gsmsiectl:
.PP
.B cset
.RS
Charset info.
.RE
.PP
.B pbook
.RS
Phone book info.
.RE
.PP
.B signal
.RS
Signal tone info.
.RE
.PP
.B ring
.RS
Ringing tone info.
.RE
.PP
.B binary
.RS
Binary info.
.RE
.SH EXAMPLES
The following invocation of
.I gsmctl
prints out all available status information for the mobile phone
connected to
.B /dev/mobilephone
.PP
.nf
.IP "" 3
gsmctl all
.fi
.PP
The output could look like (lines edited to fit):
.RS 3
.PP
.PD 0
<ME0> Manufacturer: SIEMENS
.HP
<ME1> Model: S10
.HP
<ME2> Revision: 06
.HP
<ME3> Serial Number: 448058511817585
.HP
<OP0> Status: available Long name: 'D1/-TELEKOM' Short name: '' Numeric name: 26201
.HP
<OP1> Status: forbidden Long name: 'D2 PRIVAT' Short name: '' Numeric name: 26202
.HP
<CURROP0> Long name: 'D1/-TELEKOM' Short name: '' Numeric name: 26201 Mode: automatic
.HP
<FLSTAT0> 'CS'
.HP
<FLSTAT1> 'PS'
.HP
<FLSTAT2> 'SC' Voice Data Fax
.HP
<FLSTAT3> 'AO'
.HP
<FLSTAT4> 'OI'
.HP
<FLSTAT5> 'OX'
.HP
<FLSTAT6> 'AI'
.HP
<FLSTAT7> 'IR'
.HP
<FLCAP0> 'CS' 'PS' 'SC' 'AO' 'OI' 'OX' 'AI' 'IR' 'AB' 'AG' 'AC'
.HP
<PW0> 'PS' 8
.HP
<PW1> 'SC' 8
.HP
<PW2> 'AO' 4
.HP
<PW3> 'OI' 4
.HP
<PW4> 'OX' 4
.HP
<PW5> 'AI' 4
.HP
<PW6> 'IR' 4
.HP
<PW7> 'AB' 4
.HP
<PW8> 'AG' 4
.HP
<PW9> 'AC' 4
.HP
<CLIP0> on
.HP
<FORW0.0> UnconditionalReason Voice inactive number: subaddr: time: -1
.HP
<FORW0.1> UnconditionalReason Data inactive number: subaddr: time: -1
.HP
<FORW0.2> UnconditionalReason Fax inactive number: subaddr: time: -1
.HP
<FORW1.0> MobileBusyReason Voice active number: +494012345678 subaddr: time: -1
.HP
<FORW1.1> MobileBusyReason Data inactive number: subaddr: time: -1
.HP
<FORW1.2> MobileBusyReason Fax inactive number: subaddr: time: -1
.HP
<FORW2.0> NoReplyReason Voice active number: +494012345678 subaddr: time: 20
.HP
<FORW2.1> NoReplyReason Data inactive number: subaddr: time: -1
.HP
<FORW2.2> NoReplyReason Fax inactive number: subaddr: time: -1
.HP
<FORW3.0> NotReachableReason Voice active number: +494012345678 subaddr: time: -1
.HP
<FORW3.1> NotReachableReason Data inactive number: subaddr: time: -1
.HP
<FORW3.2> NotReachableReason Fax inactive number: subaddr: time: -1
.HP
<BATT0> 0 ME is powered by the battery
.HP
<BATT1> 100
.HP
<BITERR0> 0
.HP
<SIG0> 19
.RE
.PD
.PP
The following locks the keys on the mobile phone:
.nf
.IP "" 3
gsmctl -o lock cs
.fi
.PP
This changes the SIM card PIN from 1234 to 2345:
.nf
.IP "" 3
gsmctl -o setpw sc 1234 2345
.fi
.PP
Switch off all call forwarding (actually erase the numbers):
.nf
.IP "" 3
gsmctl -o forw erase all
.fi
.PP
Switch on call forwarding to German D1 voice box:
.nf
.IP "" 3
gsmctl -o forw register notreachable 3313
gsmctl -o forw enable notreachable
.fi
.PP
.SH FILES
.TP
.B /dev/mobilephone
Default mobile phone device.
.SH AUTHOR
Peter Hofmann <software@pxh.de>
.SH BUGS
Report bugs to software@pxh.de. Include a complete, self-ncontained
example that will allow the bug to be reproduced, and say which
version of \fIgsmctl\fP you are using.
.SH COPYRIGHT
Copyright \(co 1999 Peter Hofmann
.PP
.B gsmctl
is free software; you can redistribute it and/or modify it under the
terms of the GNU Library General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
.PP
.B gsmctl
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 Library General Public
License for more details.
.PP
You should have received a copy of the GNU Library General Public
License along with
.BR gsmctl ;
see the file COPYING. If not, write to the Free Software Foundation,
675 Mass Ave, Cambridge, MA 02139, USA.
.SH "SEE ALSO"
.BR gsminfo (7),
.BR gsmpb (1),
.BR gsmsendsms (1),
.BR gsmsmsd (8),
.BR gsmsmsstore (1).

View File

@ -0,0 +1,56 @@
.\" -*- eval: (nroff-mode) -*-
.de TQ
.br
.ns
.TP \\$1
..
.\" Like TP, but if specified indent is more than half
.\" the current line-length - indent, use the default indent.
.de Tp
.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
.el .TP "\\$1"
..
.TH GSMINFO 7 "##DATE##" "gsmctl v##VERSION##"
.PP
.SH NAME
gsminfo \- GSM general information
.PP
.SH DESCRIPTION
\fIgsmlib\fP is a library to access GSM mobile phones through GSM
modems or via IrDA devices. In the \fIgsmlib\fP documentation and error
messages the following abbreviations are used:
.TP .7i
\fBME\fP
Mobile Equipment. The mobile phone, usually.
.TP .7i
\fBSC\fP
Service Centre. In the context of this documentation, the center
responsible for sending and relaying SMs.
.TP .7i
\fBSM\fP
Short Message.
.TP .7i
\fBSME\fP
Short Message Equipment. Usually the mobile phone.
.TP .7i
\fBTA\fP
Terminal Adapter. This can be a GSM modem PC card or it can be
integrated into the ME.
.TP .7i
\fBTE\fP
Terminal Equipment. This is the device to which the TA is connected,
usually the computer.
.PP
.SH AUTHOR
Peter Hofmann <software@pxh.de>
.PP
.SH COPYRIGHT
Copyright \(co 1999 Peter Hofmann
.PP
.SH "SEE ALSO"
.BR gsmctl(1),
.BR gsmpb(1),
.BR gsmsendsms(1),
.BR gsmsmsd(8),
.BR gsmsmsstore(1).

View File

@ -0,0 +1,20 @@
Begin3
Title: gsmlib
Version: 1.0
Entered-date: 29JUL99
Description: This distribution contains a library to access
GSM mobile phones through GSM modems. Features include:
* modification of phonebooks stored in the
mobile phone or on the SIM card
* reading and writing of SMS messages stored in
the mobile phone
* sending and reception of SMS messages
Additionally, some simple command line programs are
provided to use these functionalities.
Keywords: gsm mobile phone modem sms
Author: Peter Hofmann <software@pxh.de>
Maintained-by: Peter Hofmann <software@pxh.de>
Primary-site: http://www.pxh.de/fs/gsmlib/
Platforms: Linux
Copying-policy: LGPL
End

View File

@ -0,0 +1,245 @@
.\" -*- eval: (nroff-mode) -*-
.de TQ
.br
.ns
.TP \\$1
..
.\" Like TP, but if specified indent is more than half
.\" the current line-length - indent, use the default indent.
.de Tp
.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
.el .TP "\\$1"
..
.TH GSMPB 8 "##DATE##" "gsmpb v##VERSION##"
.SH NAME
gsmpb \- GSM mobile phone phonebook manipulation program
.SH SYNOPSIS
.B gsmpb
[ \fB\-b\fP \fIbaudrate\fP ]
[ \fB\-\-baudrate\fP \fIbaudrate\fP ]
[ \fB\-c\fP ]
[ \fB\-\-copy\fP ]
[ \fB\-d\fP \fIdestination device or file\fP ]
[ \fB\-\-destination\fP \fIdestination device or file\fP ]
[ \fB\-h\fP ]
[ \fB\-\-help\fP ]
[ \fB\-i\fP ]
[ \fB\-\-index\fP ]
[ \fB\-I\fP \fIinit string\fP ]
[ \fB\-\-init\fP \fIinit string\fP ]
[ \fB\-p\fP \fIphonebook name\fP ]
[ \fB\-\-phonebook\fP \fIphonebook name\fP ]
[ \fB\-s\fP \fIsource device or file\fP ]
[ \fB\-\-source\fP \fIsource device or file\fP ]
[ \fB\-t\fP \fIcharacter set\fP ]
[ \fB\-\-charset\fP \fIcharacter set\fP ]
[ \fB\-v\fP ]
[ \fB\-\-version\fP ]
[ \fB\-V\fP ]
[ \fB\-\-verbose\fP ]
[ \fB\-X\fP ]
[ \fB\-\-xonxoff\fP ]
[ \fB\-y\fP ]
[ \fB\-\-synchronize\fP ]
.PP
.SH DESCRIPTION
\fIgsmpb\fP can store or retrieve phonebook entries residing in a GSM
mobile phone's phonebook to or from a file. A synchronization mode is
also available.
.PP
\fIgsmpb\fP reads entries from the source which can be a mobile phone
(if a serial device file is given) or a file (if a file name is
given). The source is never modified. \fIgsmpb\fP writes phonebook
entries to a destination file or device. Depending on the mode the
source is copied to the destination file, thus overwriting the
destination, or the destination is synchronized with regard to the
source which is the default (details see below).
.PP
If "\-" is given as the parameter for the \fB\-\-source\fP or
\fB\-\-destination\fP options, the phonebook is read from standard input
and/or written to standard output, respectively.
.PP
Phonebook entries names are encoded using the GSM default alphabet in
the mobile phone, whereas they are stored using the Latin\-1 encoding
in phonebook files. When reading phonebook entries from a mobile phone
entry names are converted from the GSM default to Latin\-1. Characters
that can not be converted to Latin\-1 are encoded as character code
172 (Latin\-1 boolean "not"). When writing file-based phonebook entries
to a mobile phone a conversion to the GSM default alphabet takes
place. Characters that can not be converted are encoded as GSM delta
(code 16). If the default character set has been changed using the
\fB\-\-charset\fP option no conversion takes place.
.PP
Error messages are printed to the standard error output. If the program
terminates on error the error code 1 is returned.
.PP
.SH OPTIONS
.TP .7i
\fB\-b\fP \fIbaudrate\fP, \fB\-\-baudrate\fP \fIbaudrate\fP
The baud rate to use. The default baudrate is 38400.
.TP .7i
\fB\-c\fP, \fB\-\-copy\fP
This causes the contents of the source to be copied to the
destination. After this operation the destination has exactly the same
contents as the source.
.TP .7i
\fB\-d\fP \fIdestination\fP, \fB\-\-destination\fP \fIdestination\fP
The destination device or file.
.TP .7i
\fB\-h\fP, \fB\-\-help\fP
Prints an option summary.
.TP .7i
\fB\-I\fP \fIinit string\fP, \fB\-\-init\fP \fIinit string\fP
Initialization string to send to the TA (default: "E0"). Note that the
sequence "ATZ" is sent first.
.TP .7i
\fB\-i\fP, \fB\-\-index\fP
If the index position is given, \fIgsmpb\fP preserves the assignment
of entries to memory slots in the mobile phone's phonebook. This can
be used to backup phonebook entries with their position into a
phonebook file or to change the position of entries by editing a
phonebook file and writing them back to the mobile phone.
If this option is given the phonebook file used as the source
must contain indices for every entry. Additionally, these indices must
be unique, ie. it is not allowed to assign one entry twice to a
specific position in the mobile phone's phonebook.
.TP .7i
\fB\-p\fP \fIphonebook\fP, \fB\-\-phonebook\fP \fIphonebook\fP
The name of the phonebook to read from or write to. This is only used
for device sources and destinations. Commonly available phonebooks
are:
.TP .3i
.po +0.7i
.ll 5.8i
\fIFD\fP
SIM fixdialling\-phonebook
.TP .3i
\fILD\fP
SIM last\-dialling\-phonebook
.TP .3i
\fIME\fP
ME phonebook
.TP .3i
\fIMT\fP
combined ME and SIM phonebook
.TP .3i
\fISM\fP
SIM phonebook
.TP .3i
\fITA\fP
TA phonebook
.TP .7i
.po -0.7i
.ll 6.5i
\fB\-s\fP \fIsource\fP, \fB\-\-source\fP \fIsource\fP
The source device or file.
.TP
\fB\-t\fP \fIcharacter set\fP, \fB\-\-charset\fP \fIcharacter set\fP
Set the character set to use for phonebook operations (default is the
GSM default alphabet).
.TP
\fB\-v\fP, \fB\-\-version\fP
Prints the program version.
.TP .7i
\fB\-V\fP, \fB\-\-verbose\fP
Prints out a detailed progress report.
.TP .7i
\fB\-X\fP, \fB\-\-xonxoff\fP
Uses software handshaking (XON/XOFF) for accessing the device.
.TP .7i
\fB\-y\fP, \fB\-\-synchronize\fP
This causes the contents of the source to be synchronized with the
destination (default). Synchronization in this context means:
.TP .2i
.po +0.7i
.ll 5.8i
\-
If the source contains an entry with a name that does not exist in the
destination this entry is added to the destination.
.TP .2i
\-
If the source contains an entry with a name that can also be found in
the destination, the entry in the destination is overwritten (ie. the
telephone number is updated). Exception: More then one entry with the
name exists in the destination. In this case the new entry ist just added.
.TP .2i
\-
Entries in the destination that do not exist in the source are
deleted.
.PP
Note that synchronization has the following properties that differ
from copying: This algorithm does not change the location of unchanged
entries in the destination phonebook. The synchronization function
is not case-sensitive when comparing names.
.PP
.po -0.7i
.ll 6.5i
.SH PHONEBOOK FILE FORMAT
Phonebook entries are stored in phonebook files that are meant to be
human-readable and -editable. There is one phonebook entry per line,
and each line has the format:
.PP
.nf
index|text|phone number
.fi
.PP
The fields have the following meanings:
.TP .7i
\fIindex\fP
The index of the entry which must be a positive number. The index may
also be empty. Indices can be used in conjunction with the
\fB\-\-index\fP option to store the entry into a specific position in
the mobile phone.
.TP .7i
\fItext\fP
Descriptive text for the entry. The text may contain the special
characters '\\', '|', carriage return (ASCII code 13), or line feed
(ASCII code 10). These must be written "\\\\", "\\|", "\\r", "\\n",
respectively. The text should only contain characters that can be
encoded using the GSM default alphabet (see comments above).
.TP .7i
\fIphone number\fP
Phone numbers can only contains the digits 0\-9 and the '+' sign. A '+'
sign denotes an international number.
.PP
.SH EXAMPLES
The following invocation of \fIgsmpb\fP synchronizes the mobile phone's
SIM phonebook with the file $HOME/.phonebook:
.PP
.nf
gsmpb \-\-synchronize \-b 19200 \-d /dev/mobilephone \\
\-s $HOME/.phonebook \-p "SM"
.fi
.PP
.SH AUTHOR
Peter Hofmann <software@pxh.de>
.PP
.SH BUGS
Report bugs to software@pxh.de. Include a complete, self-contained
example that will allow the bug to be reproduced, and say which
version of \fIgsmpb\fP you are using.
.PP
.SH COPYRIGHT
Copyright \(co 1999 Peter Hofmann
.LP
\fIgsmpb\fP is free software; you can redistribute it and/or modify it under
the terms of the GNU Library General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
.LP
\fIgsmpb\fP 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 Library General Public License
for more details.
.LP
You should have received a copy of the GNU Library General Public License along
with \fIgsmpb\fP; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
.PP
.SH "SEE ALSO"
.BR gsminfo(7),
.BR gsmctl(1),
.BR gsmsendsms(1),
.BR gsmsmsd(8),
.BR gsmsmsstore(1).

View File

@ -0,0 +1,154 @@
.\" -*- eval: (nroff-mode) -*-
.de TQ
.br
.ns
.TP \\$1
..
.\" Like TP, but if specified indent is more than half
.\" the current line-length - indent, use the default indent.
.de Tp
.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
.el .TP "\\$1"
..
.TH GSMSENDSMS 8 "##DATE##" "gsmsendsms v##VERSION##"
.PP
.SH NAME
gsmsendsms \- SMS message sender utility
.PP
.SH SYNOPSIS
.B gsmsendsms
[ \fB\-b\fP \fIbaudrate\fP ]
[ \fB\-\-baudrate\fP \fIbaudrate\fP ]
[ \fB\-c\fP \fIconcatenatedID\fP ]
[ \fB\-\-concatenate\fP \fIconcatenatedID\fP ]
[ \fB\-C\fP \fIservice centre address\fP ]
[ \fB\-\-sca\fP \fIservice centre address\fP ]
[ \fB\-d\fP \fIdevice\fP ]
[ \fB\-\-device\fP \fIdevice\fP ]
[ \fB\-h\fP ]
[ \fB\-\-help\fP ]
[ \fB\-I\fP \fIinit string\fP ]
[ \fB\-\-init\fP \fIinit string\fP ]
[ \fB\-r\fP ]
[ \fB\-\-requeststat\fP ]
[ \fB\-t\fP ]
[ \fB\-\-test\fP ]
[ \fB\-v\fP ]
[ \fB\-\-version\fP ]
[ \fB\-X\fP ]
[ \fB\-\-xonxoff\fP ]
\fIphonenumber\fP
[ \fItext\fP ]
.PP
.SH DESCRIPTION
\fIgsmsendsms\fP sends SMS short messages using an GSM mobile phone.
.PP
\fIgsmsendsms\fP attaches itself to the \fIdevice\fP given on the command
line (usually an GSM modem) using the specified \fIbaudrate\fP. If no
\fIdevice\fP is given, the device \fI/dev/mobilephone\fP is used. If
no \fIbaudrate\fP is given, a default baud rate of 38400 is used.
.PP
\fIgsmsendsms\fP accepts a phone number (recipient address) and the
short message text as parameters. The text may have a maximum length
of 160 characters which is the maximum SMS message length. The GSM
default alphabet is used for encoding. ASCII and Latin\-1 characters
that can not be encoded using the GSM default alphabet are converted
to the GSM delta character (GSM code 16).
.PP
Error messages are printed to the standard error output. If the program
terminates on error the error code 1 is returned.
.PP
.SH OPTIONS
.TP
\fB\-b\fP \fIbaudrate\fP, \fB\-\-baudrate\fP \fIbaudrate\fP
The baud rate to use.
.TP
\fB\-c\fP \fIconcatenatedID\fP, \fB\-\-concatenate\fP \fIconcatenatedID\fP
If an ID is given, large SMSs are split into several, concatenated
SMSs. All SMSs have the same ID and are numbered consecutively so that
the receiving phone can assemble them in the correct order. IDs must
be in the range 0..255. Not all receiving phones will support
concatenated SMSs (and display them as separate SMSs),
since all the numbering and ID information is
carried in the user data header element at the beginning of the SMS
user data. This information may show up as garbage in such phones.
.TP
\fB\-C\fP \fIservice centre address\fP, \fB\-\-sca\fP \fIservice centre address\fP
Sets the service centre address to use for all SUBMIT SMSs (may not
work with some phones).
.TP
\fB\-d\fP \fIdevice\fP, \fB\-\-device\fP \fIdevice\fP
The device to which the GSM modem is connected. The default is
\fI/dev/mobilephone\fP.
.TP
\fB\-h\fP, \fB\-\-help\fP
Prints an option summary.
.TP
\fB-I\fP \fIinit string\fP, \fB\-\-init\fP \fIinit string\fP
Initialization string to send to the TA (default: "E0"). Note that the
sequence "ATZ" is sent first.
.TP
\fB\-r\fP, \fB\-\-requeststat\fP
Request status reports for sent SMS.
.TP
\fB\-t\fP, \fB\-\-test\fP
If this option is given the text is converted
to the GSM default alphabet and back to Latin\-1. This option can be
used to find out how ASCII or Latin\-1 texts are converted to the GSM
default alphabet. Characters that can not be converted to the GSM default
alphabet are reported as ASCII code 172 (Latin\-1 boolean "not")
after this double conversion. No SMS messages are sent, a connection
to a mobile phone is not established.
.TP
\fB\-v\fP, \fB\-\-version\fP
Prints the program version.
.TP
\fB\-X\fP, \fB\-\-xonxoff\fP
Uses software handshaking (XON/XOFF) for accessing the device.
.PP
.SH EXAMPLES
The following two invocations of \fIgsmsendsms\fP each send the same
SMS message to the number "1234":
.PP
.nf
gsmsendsms \-d /dev/ttyS2 \-b 19200 1234 "This is a test."
echo "This is a test." | gsmsendsms \-d /dev/ttyS2 \-b 19200 1234
.fi
.PP
.SH FILES
.TP 1.4i
.B /dev/mobilephone
Default mobile phone device.
.PP
.SH AUTHOR
Peter Hofmann <software@pxh.de>
.PP
.SH BUGS
Report bugs to software@pxh.de. Include a complete, self-contained
example that will allow the bug to be reproduced, and say which
version of \fIgsmsendsms\fP you are using.
.PP
.SH COPYRIGHT
Copyright \(co 1999 Peter Hofmann
.LP
\fIgsmsendsms\fP is free software; you can redistribute it and/or modify it under
the terms of the GNU Library General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
.LP
\fIgsmsendsms\fP 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
Library General Public License for more details.
.LP
You should have received a copy of the GNU Library General Public License along
with \fIgsmsendsms\fP; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
.PP
.SH "SEE ALSO"
.BR gsminfo(7),
.BR gsmpb(1),
.BR gsmctl(1),
.BR gsmsmsd(8),
.BR gsmsmsstore(1).

View File

@ -0,0 +1,269 @@
.\" -*- eval: (nroff-mode) -*-
.de TQ
.br
.ns
.TP \\$1
..
.\" Like TP, but if specified indent is more than half
.\" the current line-length - indent, use the default indent.
.de Tp
.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
.el .TP "\\$1"
..
.TH GSMSMSD 8 "##DATE##" "gsmsmsd v##VERSION##"
.PP
.SH NAME
gsmsmsd \- SMS message reception daemon
.PP
.SH SYNOPSIS
.B gsmsmsd
[ \fB\-a\fP \fIaction\fP ]
[ \fB\-\-action\fP \fIaction\fP ]
[ \fB\-b\fP \fIbaudrate\fP ]
[ \fB\-\-baudrate\fP \fIbaudrate\fP ]
[ \fB\-c\fP \fIconcatenatedID\fP ]
[ \fB\-\-concatenate\fP \fIconcatenatedID\fP ]
[ \fB\-C\fP \fIservice centre address\fP ]
[ \fB\-\-sca\fP \fIservice centre address\fP ]
[ \fB\-d\fP \fIdevice\fP ]
[ \fB\-\-device\fP \fIdevice\fP ]
[ \fB\-D\fP ]
[ \fB\-\-direct\fP ]
[ \fB\-f\fP ]
[ \fB\-\-flush\fP ]
[ \fB\-h\fP ]
[ \fB\-\-help\fP ]
[ \fB\-I\fP \fIinit string\fP ]
[ \fB\-\-init\fP \fIinit string\fP ]
[ \fB\-r\fP ]
[ \fB\-\-requeststat\fP ]
[ \fB\-s\fP \fIspool directory\fP ]
[ \fB\-\-spool\fP \fIspool directory\fP ]
[ \fB\-t\fP \fISMS store name\fP ]
[ \fB\-\-store\fP \fISMS store name\fP ]
[ \fB\-v\fP ]
[ \fB\-\-version\fP ]
[ \fB\-X\fP ]
[ \fB\-\-xonxoff\fP ]
{ \fIsms_type\fP }
.PP
.SH DESCRIPTION
\fIgsmsmsd\fP reads new incoming SMS from the mobile phone and
dispatches them to a user-defined action. Additionally it can send SMS
message that it reads from a spooldir.
.PP
\fIgsmsmsd\fP attaches itself to the \fIdevice\fP given on the command
line (usually an GSM modem) using the specified \fIbaudrate\fP and
waits for incoming SMS messages. If no \fIdevice\fP is given, the
device \fI/dev/mobilephone\fP is used. If no \fIbaudrate\fP is given, a
default baud rate of 38400 is used.
.PP
If no action is given, the SMS message is printed to the standard
output. If an \fIaction\fP is specified the \fIaction\fP is excecuted using the
shell and the SMS message is written to the standard input of the action.
.PP
\fIgsmsmsd\fP needs one empty storage slot for SMS messages in the
mobile phone, otherwise SMS reception will not work. The SMS store to
use for temporary storage of incoming SMS can be selected using the
\fB\-\-store\fP option, otherwise the ME default store is used.
.PP
To terminate \fIgsmsmsd\fP cleanly (without losing SMS messages) one
should send either SIGINT (CTRL\-C on the command line) or SIGTERM to
the process.
.PP
Error messages are printed to the standard error output. If the program
terminates on error the error code 1 is returned.
.PP
\fIsms_type\fP may be any combination of:
.TP
\fIsms\fP, \fIno_sms\fP
Controls reception of normal SMS messages.
.TP
\fIcb\fP, \fIno_cb\fP
Controls reception of cell broadcast messages.
.TP
\fIstat\fP, \fIno_stat\fP
Controls reception of status reports.
.PP
The default is \fIsms\fP, \fIcb\fP, and \fIstat\fP.
.PP
.SH OPTIONS
.TP
\fB\-a\fP \fIaction\fP, \fB\-\-action\fP \fIaction\fP
The action to execute for each incoming SMS message. If no action
is given the SMS is written to the standard output.
.TP
\fB\-b\fP \fIbaudrate\fP, \fB\-\-baudrate\fP \fIbaudrate\fP
The baud rate to use.
.TP
\fB\-c\fP \fIconcatenatedID\fP, \fB\-\-concatenate\fP \fIconcatenatedID\fP
If an ID is given, large SMSs are split into several, concatenated
SMSs. All SMSs have the same ID and are numbered consecutively so that
the receiving phone can assemble them in the correct order. IDs must
be in the range 0..255. This number is increased by one for every
outgoing concatenated SMS and wraps around after 255.
Not all receiving phones will support
concatenated SMSs (and display them as separate SMSs),
since all the numbering and ID information is
carried in the user data header element at the beginning of the SMS
user data. This information may show up as garbage in such phones.
.TP
\fB\-C\fP \fIservice centre address\fP, \fB\-\-sca\fP \fIservice centre address\fP
Sets the service centre address to use for all SUBMIT SMSs (may not
work with some phones).
.TP
\fB\-d\fP \fIdevice\fP, \fB\-\-device\fP \fIdevice\fP
The device to which the GSM modem is connected. The default is
\fI/dev/mobilephone\fP.
.TP
\fB\-D\fP, \fB\-\-direct\fP
Enables direct routing of incoming SMS messages to the TE. This is not
supported by many mobile phone/GSM modem combinations. Therefore, the
default is to store incoming SMS temporarily before processing them in
the indicated store.
.TP
\fB\-f\fP, \fB\-\-flush\fP
This option causes \fIgsmsmsd\fP to flush (ie. read and erase)
existing SMS messages from
the SMS store selected by the \fB\-\-store\fP option. The action given
by the \fB\-\-action\fP option is executed on each of the flushed
SMS. This option should be used to ensure that enough space is
available in the SMS store for temporary storage of incoming SMS,
otherwise incoming SMS might be ignored silently by the ME.
.TP
\fB\-h\fP, \fB\-\-help\fP
Prints an option summary.
.TP
\fB\-I\fP \fIinit string\fP, \fB\-\-init\fP \fIinit string\fP
Initialization string to send to the TA (default: "E0"). Note that the
sequence "ATZ" is sent first.
.TP
\fB\-r\fP, \fB\-\-requeststat\fP
Request status reports for sent SMS. Note: This option only makes
sense if the phone supports routing of status reports to the
TE. Otherwise the status reports might show on the phone's display or
get lost.
.TP
\fB\-s\fP \fIspool directory\fP, \fB\-\-spool\fP \fIspool directory\fP
This option sets the spool directory where \fIgsmsmsd\fP expects SMS
messages to send. The format of SMS files is very simple: The first
line contains the phone number of the recipient. Everything else after
the first line is interpreted as the SMS text. Please refer to
.BR gsmsendsms(1)
for details on the SMS text character set and maximum length.
\fIgsmsmsd\fP polls the spool directory every 5 seconds. Sent
SMS message files are removed.
.TP
\fB\-t\fP \fISMS store name\fP, \fB\-\-store\fP \fISMS store name\fP
The name of the SMS store to read from (for the \fB\-\-flush\fP option)
or write to (for temporary SMS storage). This option must
be must be used in conjunction with the \fB\-\-flush\fP option. If this
option is omitted the ME uses it's default SMS store for temporary
storage of incoming SMS. A commonly available message
store is "SM" (SIM card).
.TP
\fB\-v\fP, \fB\-\-version\fP
Prints the program version.
.TP
\fB\-X\fP, \fB\-\-xonxoff\fP
Uses software handshaking (XON/XOFF) for accessing the device.
.PP
.SH EXAMPLES
The following invocation of \fIgsmsmsd\fP sends each incoming SMS message
as a mail to the user "smsadmin":
.PP
.nf
gsmsmsd \-d /dev/ttyS2 \-b 19200 \-a "mail smsadmin"
.fi
.PP
This is the format of SMS deliver messages as output from \fIgsmsmsd\fP:
.PP
.nf
----------------------------------------------------------------
Message type: SMS\-DELIVER
SC address: '491710762100'
More messages to send: 1
Reply path: 0
User data header indicator: 0
Status report indication: 0
Originating address: '01805000102'
Protocol identifier: 0x39
Data coding scheme: default alphabet
SC timestamp: 17.12.98 14:10:55(+0100)
User data length: 159
User data header: 0x
User data: 'Nicht vergessen! Die XtraWeihnachtsverlosung lauft
noch bis zum 24.12. Nutzen Sie jetzt Ihre Gewinnchance und faxen
Sie Ihren Teiln.-Gutschein an 0180/5000 056'
----------------------------------------------------------------
.fi
.PP
This is the format of SMS status report messages as output from \fIgsmsmsd\fP:
.PP
.nf
----------------------------------------------------------------
Message type: SMS\-STATUS\-REPORT
SC address: ''
More messages to send: 0
Status report qualifier: 0
Message reference: 0
Recipient address: ''
SC timestamp: 00.00.00 00:00:00(+0000)
Discharge time: 00.00.00 00:00:00(+0000)
Status: 0x0 'Short message received by the SME'
----------------------------------------------------------------
.fi
.PP
The following invocation of \fIgsmsmsd\fP flushes all existing
messages from the "SM" SMS store and looks in the "/tmp/spooldir"
directory for SMS to send:
.PP
.nf
gsmsmsd \-d /dev/ttyS2 \-\-spool /tmp/spooldir \-f \-\-store sm \\
\-\-action 'mail smsadmin'
.fi
.PP
.SH FILES
.TP 1.4i
.B /dev/mobilephone
Default mobile phone device.
.PP
.SH AUTHOR
Peter Hofmann <software@pxh.de>
.PP
.SH BUGS
Cell broadcast SMS message reception has not been tested, but it has
been enabled in the \fIgsmsmsd\fP daemon.
.PP
The mobile phone device is blocked when the \fIgsmsmsd\fP daemon is
running, ie. it cannot be used for data transfer or from the other
programs of this suite (\fIgsmpb\fP, \fIgsmsms\fP).
.PP
Report bugs to software@pxh.de. Include a complete, self-contained
example that will allow the bug to be reproduced, and say which
version of \fIgsmsmsd\fP you are using.
.PP
.SH COPYRIGHT
Copyright \(co 1999 Peter Hofmann
.LP
\fIgsmsmsd\fP is free software; you can redistribute it and/or modify it under
the terms of the GNU Library General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
.LP
\fIgsmsmsd\fP 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
Library General Public License for more details.
.LP
You should have received a copy of the GNU Library General Public License along
with \fIgsmsmsd\fP; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
.PP
.SH "SEE ALSO"
.BR gsminfo(7),
.BR gsmpb(1),
.BR gsmctl(1),
.BR gsmsendsms(1),
.BR gsmsmsstore(1).

View File

@ -0,0 +1,185 @@
.\" -*- eval: (nroff-mode) -*-
.de TQ
.br
.ns
.TP \\$1
..
.\" Like TP, but if specified indent is more than half
.\" the current line-length - indent, use the default indent.
.de Tp
.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
.el .TP "\\$1"
..
.TH GSMSMSSTORE 8 "##DATE##" "gsmsmsstore v##VERSION##"
.SH NAME
gsmsmsstore \- SMS store manipulation program
.SH SYNOPSIS
.B gsmsmsstore
[ \fB\-a\fP ]
[ \fB\-\-add\fP ]
[ \fB\-b\fP \fIbaudrate\fP ]
[ \fB\-\-baudrate\fP \fIbaudrate\fP ]
[ \fB\-c\fP ]
[ \fB\-\-copy\fP ]
[ \fB\-C\fP \fIservice centre address\fP ]
[ \fB\-\-sca\fP \fIservice centre address\fP ]
[ \fB\-d\fP \fIdestination device or file\fP ]
[ \fB\-\-destination\fP \fIdestination device or file\fP ]
[ \fB\-h\fP ]
[ \fB\-\-help\fP ]
[ \fB\-I\fP \fIinit string\fP ]
[ \fB\-\-init\fP \fIinit string\fP ]
[ \fB\-k\fP ]
[ \fB\-\-backup\fP ]
[ \fB\-l\fP ]
[ \fB\-\-list\fP ]
[ \fB\-s\fP \fIsource device or file\fP ]
[ \fB\-\-source\fP \fIsource device or file\fP ]
[ \fB\-t\fP \fISMS store name\fP ]
[ \fB\-\-store\fP \fISMS store name\fP ]
[ \fB\-v\fP ]
[ \fB\-\-version\fP ]
[ \fB\-V\fP ]
[ \fB\-\-verbose\fP ]
[ \fB\-x\fP ]
[ \fB\-\-delete\fP ]
[ \fB\-X\fP ]
[ \fB\-\-xonxoff\fP ]
{ \fIindices\fP }
[ \fIphonenumber\fP \fItext\fP ]
.PP
.SH DESCRIPTION
\fIgsmsmsstore\fP can store or retrieve SMS messages entries residing
in a GSM mobile phone's SMS store to or from a file, add SMS messages
to a store, or list the store's contents. Additionally, it is possible
to add SMS submit messages to a store.
.PP
\fIgsmsmsstore\fP reads entries from the source which can be a mobile
phone (if a serial device file is given) or a file (if a file name is
given). The source is never modified. \fIgsmsmsstore\fP writes SMS
messages to a destination file or device in the case of \fB\-\-copy\fP,
\fB\-\-backup\fP, and \fB\-\-add\fP.
.PP
The \fB\-\-list\fP option does not change any file but just lists the
contents to standard output.
.PP
The \fB\-\-backup\fP and \fB\-\-copy\fP options require both source and
destination files or devices. The \fB\-\-list\fP option requires a
source. The \fB\-\-add\fP and \fB\-\-delete\fP options require a
destination file or device.
.PP
If "\-" is given as the parameter for the \fB\-\-source\fP or
\fB\-\-destination\fP options, the SMS store is read from standard input
and/or written to standard output, respectively.
.PP
SMS message files are not human-readable.
.PP
Error messages are printed to the standard error output. If the program
terminates on error the error code 1 is returned.
.PP
.SH OPTIONS
.TP
\fB\-a\fP, \fB\-\-add\fP
Adds an SMS submit message with recipient address \fIphonenumber\fP and
text \fItext\fP to the destination.
.TP
\fB\-b\fP \fIbaudrate\fP, \fB\-\-baudrate\fP \fIbaudrate\fP
The baud rate to use. The default baudrate is 38400.
.TP
\fB\-c\fP, \fB\-\-copy\fP
This causes the contents of the source to be copied to the
destination. After this operation the destination has exactly the same
contents as the source. If \fIindices\fP are given on the command
line only those SMS messages denoted by the indices are copied to the
destination.
.TP
\fB\-C\fP \fIservice centre address\fP, \fB\-\-sca\fP \fIservice centre address\fP
Sets the service centre address to use for all SUBMIT SMSs (may not
work with some phones).
.TP
\fB\-d\fP \fIdestination\fP, \fB\-\-destination\fP \fIdestination\fP
The destination device or file.
.TP
\fB\-h\fP, \fB\-\-help\fP
Prints an option summary.
.TP
\fB\-I\fP \fIinit string\fP, \fB\-\-init\fP \fIinit string\fP
Initialization string to send to the TA (default: "E0"). Note that the
sequence "ATZ" is sent first.
.TP
\fB\-k\fP, \fB\-\-backup\fP
This causes those entries to be added from the source to the
destination that are not already present in the destination. If
\fIindices\fP are given on the command line only those SMS messages
denoted by the indices are backed up (ie. added) to the destination.
.TP
\fB\-l\fP, \fB\-\-list\fP
Prints out the entire contents of the source in human-readable form.
.TP
\fB\-s\fP \fIsource\fP, \fB\-\-source\fP \fIsource\fP
The source device or file.
.TP
\fB\-t\fP \fISMS store name\fP, \fB\-\-store\fP \fISMS store name\fP
The name of the SMS store to read from or write to. This information is
only used for device sources and destinations. A commonly available message
store is "SM" (SIM card).
.TP
\fB\-v\fP, \fB\-\-version\fP
Prints the program version.
.TP
\fB\-V\fP, \fB\-\-verbose\fP
Prints out a detailed progress report.
.TP
\fB\-x\fP, \fB\-\-delete\fP
Delete the SMS messages as denoted by the \fIindices\fP from the destination.
.TP
\fB\-X\fP, \fB\-\-xonxoff\fP
Uses software handshaking (XON/XOFF) for accessing the device.
.PP
.SH EXAMPLES
The following command lists all entries in the mobile phone connected
to \fI/dev/mobilephone\fP to the standard output:
.PP
.nf
gsmsmsstore \-b 19200 \-s /dev/mobilephone \-t SM \-l
.fi
.PP
The following adds entries 4, 7, and 10 from the device
\fI/dev/mobilephone\fP to the file \fIsmsstore\fP:
.PP
.nf
gsmsmsstore \-s /dev/mobilephone \-d /home/fred/smsstore
\-t SM \-b 4 7 10
.fi
.PP
.SH AUTHOR
Peter Hofmann <software@pxh.de>
.PP
.SH BUGS
Report bugs to software@pxh.de. Include a complete, self-contained
example that will allow the bug to be reproduced, and say which
version of \fIgsmsmsstore\fP you are using.
.PP
.SH COPYRIGHT
Copyright \(co 1999 Peter Hofmann
.LP
\fIgsmsmsstore\fP is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2, or (at
your option) any later version.
.LP
\fIgsmsmsstore\fP 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
Library General Public License for more details.
.LP
You should have received a copy of the GNU Library General Public License
along with \fIgsmsmsstore\fP; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
.PP
.SH "SEE ALSO"
.BR gsminfo(7),
.BR gsmctl(1),
.BR gsmpb(1),
.BR gsmsendsms(1),
.BR gsmsmsd(8).

View File

@ -0,0 +1,40 @@
## Process this file with automake to produce Makefile.in
# *************************************************************************
# * GSM TA/ME library
# *
# * File: Makefile.am
# *
# * Purpose: Makefile for phone-specific extensions
# *
# * Author: Peter Hofmann (software@pxh.de)
# *
# * Created: 16.12.2001
# *************************************************************************
INCLUDES = -I..
EXTRA_DIST = README.sieme
# build addon library
lib_LTLIBRARIES = libgsmext.la
libgsmext_la_SOURCES = gsm_sie_me.cc
libgsmext_la_LDFLAGS = -version-info $(GSM_VERSION)
gsmincludedir = $(includedir)/gsmlib
gsminclude_HEADERS = gsm_sie_me.h
# build programs
bin_PROGRAMS = gsmsiectl gsmsiexfer
# build gsmsiectl from gsmsiectl.cc and libgsmme.la
gsmsiectl_SOURCES = gsmsiectl.cc
gsmsiectl_LDADD = ../gsmlib/libgsmme.la libgsmext.la $(INTLLIBS)
# build gsmsiexfer from gsmsiexfer.cc and libgsmme.la
gsmsiexfer_SOURCES = gsmsiexfer.cc
gsmsiexfer_LDADD = ../gsmlib/libgsmme.la libgsmext.la $(INTLLIBS)

View File

@ -0,0 +1,480 @@
# Makefile.in generated by automake 1.6.3 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# *************************************************************************
# * GSM TA/ME library
# *
# * File: Makefile.am
# *
# * Purpose: Makefile for phone-specific extensions
# *
# * Author: Peter Hofmann (software@pxh.de)
# *
# * Created: 16.12.2001
# *************************************************************************
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_HEADER = $(INSTALL_DATA)
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
EXEEXT = @EXEEXT@
OBJEXT = @OBJEXT@
PATH_SEPARATOR = @PATH_SEPARATOR@
AMTAR = @AMTAR@
AS = @AS@
AWK = @AWK@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CPP = @CPP@
CXX = @CXX@
DATADIRNAME = @DATADIRNAME@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
ECHO = @ECHO@
GENCAT = @GENCAT@
GLIBC21 = @GLIBC21@
GMSGFMT = @GMSGFMT@
GSM_VERSION = @GSM_VERSION@
HAVE_LIB = @HAVE_LIB@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INSTOBJEXT = @INSTOBJEXT@
INTLBISON = @INTLBISON@
INTLLIBS = @INTLLIBS@
INTLOBJS = @INTLOBJS@
INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
LIB = @LIB@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIB = @LTLIB@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
MKINSTALLDIRS = @MKINSTALLDIRS@
OBJDUMP = @OBJDUMP@
PACKAGE = @PACKAGE@
POSUB = @POSUB@
RANLIB = @RANLIB@
STRIP = @STRIP@
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
am__include = @am__include@
am__quote = @am__quote@
install_sh = @install_sh@
INCLUDES = -I..
EXTRA_DIST = README.sieme
# build addon library
lib_LTLIBRARIES = libgsmext.la
libgsmext_la_SOURCES = gsm_sie_me.cc
libgsmext_la_LDFLAGS = -version-info $(GSM_VERSION)
gsmincludedir = $(includedir)/gsmlib
gsminclude_HEADERS = gsm_sie_me.h
# build programs
bin_PROGRAMS = gsmsiectl gsmsiexfer
# build gsmsiectl from gsmsiectl.cc and libgsmme.la
gsmsiectl_SOURCES = gsmsiectl.cc
gsmsiectl_LDADD = ../gsmlib/libgsmme.la libgsmext.la $(INTLLIBS)
# build gsmsiexfer from gsmsiexfer.cc and libgsmme.la
gsmsiexfer_SOURCES = gsmsiexfer.cc
gsmsiexfer_LDADD = ../gsmlib/libgsmme.la libgsmext.la $(INTLLIBS)
subdir = ext
mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/gsm_config.h
CONFIG_CLEAN_FILES =
LTLIBRARIES = $(lib_LTLIBRARIES)
libgsmext_la_LIBADD =
am_libgsmext_la_OBJECTS = gsm_sie_me.lo
libgsmext_la_OBJECTS = $(am_libgsmext_la_OBJECTS)
bin_PROGRAMS = gsmsiectl$(EXEEXT) gsmsiexfer$(EXEEXT)
PROGRAMS = $(bin_PROGRAMS)
am_gsmsiectl_OBJECTS = gsmsiectl.$(OBJEXT)
gsmsiectl_OBJECTS = $(am_gsmsiectl_OBJECTS)
gsmsiectl_DEPENDENCIES = ../gsmlib/libgsmme.la libgsmext.la
gsmsiectl_LDFLAGS =
am_gsmsiexfer_OBJECTS = gsmsiexfer.$(OBJEXT)
gsmsiexfer_OBJECTS = $(am_gsmsiexfer_OBJECTS)
gsmsiexfer_DEPENDENCIES = ../gsmlib/libgsmme.la libgsmext.la
gsmsiexfer_LDFLAGS =
DEFS = @DEFS@
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
depcomp = $(SHELL) $(top_srcdir)/scripts/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/gsm_sie_me.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsmsiectl.Po ./$(DEPDIR)/gsmsiexfer.Po
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
CXXFLAGS = @CXXFLAGS@
DIST_SOURCES = $(libgsmext_la_SOURCES) $(gsmsiectl_SOURCES) \
$(gsmsiexfer_SOURCES)
HEADERS = $(gsminclude_HEADERS)
DIST_COMMON = $(gsminclude_HEADERS) Makefile.am Makefile.in
SOURCES = $(libgsmext_la_SOURCES) $(gsmsiectl_SOURCES) $(gsmsiexfer_SOURCES)
all: all-am
.SUFFIXES:
.SUFFIXES: .cc .lo .o .obj
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu ext/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
libLTLIBRARIES_INSTALL = $(INSTALL)
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(libdir)
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
if test -f $$p; then \
f="`echo $$p | sed -e 's|^.*/||'`"; \
echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$f"; \
$(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$f; \
else :; fi; \
done
uninstall-libLTLIBRARIES:
@$(NORMAL_UNINSTALL)
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
p="`echo $$p | sed -e 's|^.*/||'`"; \
echo " $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p"; \
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \
done
clean-libLTLIBRARIES:
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test -z "$dir" && dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
libgsmext.la: $(libgsmext_la_OBJECTS) $(libgsmext_la_DEPENDENCIES)
$(CXXLINK) -rpath $(libdir) $(libgsmext_la_LDFLAGS) $(libgsmext_la_OBJECTS) $(libgsmext_la_LIBADD) $(LIBS)
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(bindir)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
if test -f $$p \
|| test -f $$p1 \
; then \
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
rm -f $(DESTDIR)$(bindir)/$$f; \
done
clean-binPROGRAMS:
@list='$(bin_PROGRAMS)'; for p in $$list; do \
f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
echo " rm -f $$p $$f"; \
rm -f $$p $$f ; \
done
gsmsiectl$(EXEEXT): $(gsmsiectl_OBJECTS) $(gsmsiectl_DEPENDENCIES)
@rm -f gsmsiectl$(EXEEXT)
$(CXXLINK) $(gsmsiectl_LDFLAGS) $(gsmsiectl_OBJECTS) $(gsmsiectl_LDADD) $(LIBS)
gsmsiexfer$(EXEEXT): $(gsmsiexfer_OBJECTS) $(gsmsiexfer_DEPENDENCIES)
@rm -f gsmsiexfer$(EXEEXT)
$(CXXLINK) $(gsmsiexfer_LDFLAGS) $(gsmsiexfer_OBJECTS) $(gsmsiexfer_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT) core *.core
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_sie_me.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsmsiectl.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsmsiexfer.Po@am__quote@
distclean-depend:
-rm -rf ./$(DEPDIR)
.cc.o:
@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
.cc.obj:
@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CXXCOMPILE) -c -o $@ `cygpath -w $<`
.cc.lo:
@AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(LTCXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
CXXDEPMODE = @CXXDEPMODE@
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
gsmincludeHEADERS_INSTALL = $(INSTALL_HEADER)
install-gsmincludeHEADERS: $(gsminclude_HEADERS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(gsmincludedir)
@list='$(gsminclude_HEADERS)'; for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f="`echo $$p | sed -e 's|^.*/||'`"; \
echo " $(gsmincludeHEADERS_INSTALL) $$d$$p $(DESTDIR)$(gsmincludedir)/$$f"; \
$(gsmincludeHEADERS_INSTALL) $$d$$p $(DESTDIR)$(gsmincludedir)/$$f; \
done
uninstall-gsmincludeHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(gsminclude_HEADERS)'; for p in $$list; do \
f="`echo $$p | sed -e 's|^.*/||'`"; \
echo " rm -f $(DESTDIR)$(gsmincludedir)/$$f"; \
rm -f $(DESTDIR)$(gsmincludedir)/$$f; \
done
ETAGS = etags
ETAGSFLAGS =
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@list='$(DISTFILES)'; for file in $$list; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
install-binPROGRAMS: install-libLTLIBRARIES
installdirs:
$(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(bindir) $(DESTDIR)$(gsmincludedir)
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
clean-libtool mostlyclean-am
distclean: distclean-am
distclean-am: clean-am distclean-compile distclean-depend \
distclean-generic distclean-libtool distclean-tags
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am: install-gsmincludeHEADERS
install-exec-am: install-binPROGRAMS install-libLTLIBRARIES
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
uninstall-am: uninstall-binPROGRAMS uninstall-gsmincludeHEADERS \
uninstall-info-am uninstall-libLTLIBRARIES
.PHONY: GTAGS all all-am check check-am clean clean-binPROGRAMS \
clean-generic clean-libLTLIBRARIES clean-libtool distclean \
distclean-compile distclean-depend distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am info \
info-am install install-am install-binPROGRAMS install-data \
install-data-am install-exec install-exec-am \
install-gsmincludeHEADERS install-info install-info-am \
install-libLTLIBRARIES install-man install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool tags uninstall \
uninstall-am uninstall-binPROGRAMS uninstall-gsmincludeHEADERS \
uninstall-info-am uninstall-libLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,75 @@
Extended support for Siemens mobile phones via gsmlib
-----------------------------------------------------
* Hardware:
Supported phones: S25, S35, S45, ME45, SL45
Tested phones: S45, ME45
* Feature list:
- ACM: Output ACM (accumulated call meter) and ACMmax => maybe not
- BNR/BNW: Binary read and write => yes, xfer
- CID: Output card ID => maybe
- CKS: Output SIM card status => maybe
- CNI: Output call number information => maybe
- DBR: Database Read => yes, phonebook
- DLD: Delete the "last number redial" memory => maybe dangerous?
- GAUTH: Select Type of Authentication for PPP => no
- ICO: Icon control => no
- LCK: Switch locks on and off => yes, lock/unlock
- LNG: Language settings => maybe
- MGL: List SMS => no
- MGO: SMS overflow indicator => no
- MGR: Read SMS (same as AT+CMGR) => no
- MSO: Switch device off => maybe not
- NFS: Select NF hardware => maybe
- NFV: Set the volume => maybe
- PBC: Seek in telephone book => no
- PBG: Sorted telephone book => yes
- PBS: Select a telephone book => yes
- PIC: Output PIN counter => maybe
- PLM: Read the PLMN list => yes
- PLR/PLW: read/write preferred-operator list => yes
- PST: Play Signal Tone => yes
- PWD: Change password to a lock => maybe
- RTC: Set the ringing tone => yes
- STK: SIM toolkit => no
* Additional References
http://www.s45-world.net/vissie.htm
* Author and contact
Christian W. Zuckschwerdt <zany@triq.net>
http://triq.net/gsm.html

View File

@ -0,0 +1,258 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_sie_me.cc
// *
// * Purpose: Mobile Equipment/Terminal Adapter and SMS functions
// * (According to "AT command set for S45 Siemens mobile phones"
// * v1.8, 26. July 2001 - Common AT prefix is "^S")
// *
// * Author: Christian W. Zuckschwerdt <zany@triq.net>
// *
// * Created: 2001-12-15
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_nls.h>
#include <gsmlib/gsm_me_ta.h>
#include <gsmlib/gsm_parser.h>
#include <gsmlib/gsm_util.h>
#include <gsm_sie_me.h>
#include <iostream>
using namespace std;
using namespace gsmlib;
// SieMe members
void SieMe::init() throw(GsmException)
{
}
SieMe::SieMe(Ref<Port> port) throw(GsmException) : MeTa::MeTa(port)
{
// initialize Siemens ME
init();
}
vector<string> SieMe::getSupportedPhonebooks() throw(GsmException)
{
Parser p(_at->chat("^SPBS=?", "^SPBS:"));
return p.parseStringList();
}
string SieMe::getCurrentPhonebook() throw(GsmException)
{
if (_lastPhonebookName == "")
{
Parser p(_at->chat("^SPBS?", "^SPBS:"));
// answer is e.g. ^SPBS: "SM",41,250
_lastPhonebookName = p.parseString();
p.parseComma();
int _currentNumberOfEntries = p.parseInt();
p.parseComma();
int _maxNumberOfEntries = p.parseInt();
}
return _lastPhonebookName;
}
void SieMe::setPhonebook(string phonebookName) throw(GsmException)
{
if (phonebookName != _lastPhonebookName)
{
_at->chat("^SPBS=\"" + phonebookName + "\"");
_lastPhonebookName = phonebookName;
}
}
IntRange SieMe:: getSupportedSignalTones() throw(GsmException)
{
Parser p(_at->chat("^SPST=?", "^SPST:"));
// ^SPST: (0-4),(0,1)
IntRange typeRange = p.parseRange();
p.parseComma();
vector<bool> volumeList = p.parseIntList();
return typeRange;
}
void SieMe:: playSignalTone(int tone) throw(GsmException)
{
_at->chat("^SPST=" + intToStr(tone) + ",1");
}
void SieMe:: stopSignalTone(int tone) throw(GsmException)
{
_at->chat("^SPST=" + intToStr(tone) + ",0");
}
IntRange SieMe::getSupportedRingingTones() throw(GsmException) // (AT^SRTC=?)
{
Parser p(_at->chat("^SRTC=?", "^SRTC:"));
// ^SRTC: (0-42),(1-5)
IntRange typeRange = p.parseRange();
p.parseComma();
IntRange volumeRange = p.parseRange();
return typeRange;
}
int SieMe::getCurrentRingingTone() throw(GsmException) // (AT^SRTC?)
{
Parser p(_at->chat("^SRTC?", "^SRTC:"));
// ^SRTC: 41,2,0
int type = p.parseInt();
p.parseComma();
int volume = p.parseInt();
p.parseComma();
int ringing = p.parseInt();
return type;
}
void SieMe::setRingingTone(int tone, int volume) throw(GsmException)
{
_at->chat("^SRTC=" + intToStr(tone) + "," + intToStr(volume));
}
void SieMe:: playRingingTone() throw(GsmException)
{
// get ringing bool
Parser p(_at->chat("^SRTC?", "^SRTC:"));
// ^SRTC: 41,2,0
int type = p.parseInt();
p.parseComma();
int volume = p.parseInt();
p.parseComma();
int ringing = p.parseInt();
if (ringing == 0)
toggleRingingTone();
}
void SieMe::stopRingingTone() throw(GsmException)
{
// get ringing bool
Parser p(_at->chat("^SRTC?", "^SRTC:"));
// ^SRTC: 41,2,0
int type = p.parseInt();
p.parseComma();
int volume = p.parseInt();
p.parseComma();
int ringing = p.parseInt();
if (ringing == 1)
toggleRingingTone();
}
void SieMe::toggleRingingTone() throw(GsmException) // (AT^SRTC)
{
_at->chat("^SRTC");
}
// Siemens get supported binary read
vector<ParameterRange> SieMe::getSupportedBinaryReads() throw(GsmException)
{
Parser p(_at->chat("^SBNR=?", "^SBNR:"));
// ^SBNR: ("bmp",(0-3)),("mid",(0-4)),("vcf",(0-500)),("vcs",(0-50))
return p.parseParameterRangeList();
}
// Siemens get supported binary write
vector<ParameterRange> SieMe::getSupportedBinaryWrites() throw(GsmException)
{
Parser p(_at->chat("^SBNW=?", "^SBNW:"));
// ^SBNW: ("bmp",(0-3)),("mid",(0-4)),("vcf",(0-500)),("vcs",(0-50)),("t9d",(0))
return p.parseParameterRangeList();
}
// Siemens Binary Read
BinaryObject SieMe::getBinary(string type, int subtype) throw(GsmException)
{
// expect several response lines
vector<string> result;
result = _at->chatv("^SBNR=\"" + type + "\"," + intToStr(subtype), "^SBNR:");
// "bmp",0,1,5 <CR><LF> pdu <CR><LF> "bmp",0,2,5 <CR><LF> ...
// most likely to be PDUs of 382 chars (191 * 2)
string pdu;
int fragmentCount = 0;
for (vector<string>::iterator i = result.begin(); i != result.end(); ++i)
{
++fragmentCount;
// parse header
Parser p(*i);
string fragmentType = p.parseString();
if (fragmentType != type)
throw GsmException(_("bad PDU type"), ChatError);
p.parseComma();
int fragmentSubtype = p.parseInt();
if (fragmentSubtype != subtype)
throw GsmException(_("bad PDU subtype"), ChatError);
p.parseComma();
int fragmentNumber = p.parseInt();
if (fragmentNumber != fragmentCount)
throw GsmException(_("bad PDU number"), ChatError);
p.parseComma();
int numberOfFragments = p.parseInt();
if (fragmentNumber > numberOfFragments)
throw GsmException(_("bad PDU number"), ChatError);
// concat pdu fragment
++i;
pdu += *i;
}
BinaryObject bnr;
bnr._type = type;
bnr._subtype = subtype;
bnr._size = pdu.length() / 2;
bnr._data = new unsigned char[pdu.length() / 2];
if (! hexToBuf(pdu, bnr._data))
throw GsmException(_("bad hexadecimal PDU format"), ChatError);
return bnr;
}
// Siemens Binary Write
void SieMe::setBinary(string type, int subtype, BinaryObject obj)
throw(GsmException)
{
if (obj._size <= 0)
throw GsmException(_("bad object"), ParameterError);
// Limitation: The maximum pdu size is 176 bytes (or 352 characters)
// this should be a configurable field
int maxPDUsize = 176;
int numberOfPDUs = (obj._size + maxPDUsize - 1) / maxPDUsize;
unsigned char *p = obj._data;
for (int i = 1; i <= numberOfPDUs; ++i)
{
// construct pdu
int size = maxPDUsize;
if (i == numberOfPDUs)
size = obj._size - (numberOfPDUs - 1) * maxPDUsize;
string pdu = bufToHex(p, size);
p += size;
cout << "processing " << i << " of " << numberOfPDUs
<< " of " << size << " bytes." << endl;
cout << "^SBNW=\"" + type + "\"," + intToStr(subtype) + ","
+ intToStr(i) + "," + intToStr(numberOfPDUs) << endl;
cout << pdu << endl;
_at->sendPdu("^SBNW=\"" + type + "\"," + intToStr(subtype) + ","
+ intToStr(i) + "," + intToStr(numberOfPDUs), "",
pdu, true);
cout << "OK" << endl;
}
}

View File

@ -0,0 +1,99 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_sie_me.h
// *
// * Purpose: Mobile Equipment/Terminal Adapter and SMS functions
// * (According to "AT command set for S45 Siemens mobile phones"
// * v1.8, 26. July 2001 - Common AT prefix is "^S")
// *
// * Author: Christian W. Zuckschwerdt <zany@triq.net>
// *
// * Created: 2001-12-15
// *************************************************************************
#ifndef GSM_SIE_ME_H
#define GSM_SIE_ME_H
#include <gsmlib/gsm_error.h>
#include <gsmlib/gsm_at.h>
#include <string>
#include <vector>
using namespace std;
namespace gsmlib
{
// *** Siemens mobile phone binary objects (bitmap, midi, vcal, vcard)
struct BinaryObject
{
string _type; // Object type
int _subtype; // Object subtype (storage number)
unsigned char *_data; // Object binary data
int _size; // Object data size
};
// *** this class allows extended access to Siemens moblie phones
class SieMe : public MeTa
{
private:
// init ME/TA to sensible defaults
void init() throw(GsmException);
public:
// initialize a new MeTa object given the port
SieMe(Ref<Port> port) throw(GsmException);
// get the current phonebook in the Siemens ME
vector<string> getSupportedPhonebooks() throw(GsmException);// (AT^SPBS=?)
// get the current phonebook in the Siemens ME
string getCurrentPhonebook() throw(GsmException); // (AT^SPBS?)
// set the current phonebook in the Siemens ME
// remember the last phonebook set for optimisation
void setPhonebook(string phonebookName) throw(GsmException); // (AT^SPBS=)
// Siemens get supported signal tones
IntRange getSupportedSignalTones() throw(GsmException); // (AT^SPST=?)
// Siemens set ringing tone
void playSignalTone(int tone) throw(GsmException); // (AT^SRTC=x,1)
// Siemens set ringing tone
void stopSignalTone(int tone) throw(GsmException); // (AT^SRTC=x,0)
// Siemens get ringing tone
IntRange getSupportedRingingTones() throw(GsmException); // (AT^SRTC=?)
// Siemens get ringing tone
int getCurrentRingingTone() throw(GsmException); // (AT^SRTC?)
// Siemens set ringing tone
void setRingingTone(int tone, int volume) throw(GsmException);// (AT^SRTC=)
// Siemens set ringing tone on
void playRingingTone() throw(GsmException);
// Siemens set ringing tone of
void stopRingingTone() throw(GsmException);
// Siemens toggle ringing tone
void toggleRingingTone() throw(GsmException); // (AT^SRTC)
// Siemens get supported binary read
vector<ParameterRange> getSupportedBinaryReads() throw(GsmException);
// Siemens get supported binary write
vector<ParameterRange> getSupportedBinaryWrites() throw(GsmException);
// Siemens Binary Read
BinaryObject getBinary(string type, int subtype) throw(GsmException);
// Siemens Binary Write
void setBinary(string type, int subtype, BinaryObject obj)
throw(GsmException);
};
};
#endif // GSM_ME_TA_H

View File

@ -0,0 +1,698 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsmsiectl.cc
// *
// * Purpose: GSM Siemens mobile phone control program
// *
// * Author: Christian W. Zuckschwerdt <zany@triq.net>
// *
// * Created: 2001-12-15
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_nls.h>
#include <string>
#if defined(HAVE_GETOPT_LONG) || defined(WIN32)
#include <getopt.h>
#endif
#include <strstream>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <gsmlib/gsm_me_ta.h>
#include <gsm_sie_me.h>
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_sysdep.h>
#ifdef WIN32
#include <gsmlib/gsm_win32_serial.h>
#else
#include <gsmlib/gsm_unix_serial.h>
#include <unistd.h>
#endif
#include <iostream>
using namespace std;
using namespace gsmlib;
// my ME
static SieMe *m;
// information parameters
enum InfoParameter {AllInfo, // print all info
MeInfo, // MeInfo must be first!
OperatorInfo,
CurrentOperatorInfo,
FacilityLockStateInfo,
FacilityLockCapabilityInfo,
PasswordInfo,
CLIPInfo,
CallForwardingInfo,
BatteryInfo,
BitErrorInfo,
SCAInfo,
CharSetInfo,
PhonebookInfo, // extended Siemens info
SignalToneInfo,
RingingToneInfo,
BinaryInfo,
SignalInfo}; // SignalInfo must be last!
// operation parameters
// FIXME operations not implemented yet
// options
#ifdef HAVE_GETOPT_LONG
static struct option longOpts[] =
{
{"xonxoff", no_argument, (int*)NULL, 'X'},
{"operation", required_argument, (int*)NULL, 'o'},
{"device", required_argument, (int*)NULL, 'd'},
{"baudrate", required_argument, (int*)NULL, 'b'},
{"init", required_argument, (int*)NULL, 'I'},
{"help", no_argument, (int*)NULL, 'h'},
{"version", no_argument, (int*)NULL, 'v'},
{(char*)NULL, 0, (int*)NULL, 0}
};
#else
#define getopt_long(argc, argv, options, longopts, indexptr) \
getopt(argc, argv, options)
#endif
// helper function, prints forwarding info
void printForwardReason(string s, ForwardInfo &info)
{
cout << s << " "
<< (info._active ? _("active ") : _("inactive "))
<< _("number: ") << info._number
<< _(" subaddr: ") << info._subAddr
<< _(" time: ") << info._time << endl;
}
// helper function, prints integer range
void printIntRange(IntRange ir)
{
cout << "(" << ir._low;
if (ir._high != NOT_SET)
cout << "-" << ir._high;
cout << ")";
}
// helper function, prints parameter range
void printParameterRange(ParameterRange pr)
{
cout << "(\"" << pr._parameter << "\",";
printIntRange(pr._range);
cout << ")";
}
// print information
static void printInfo(InfoParameter ip)
{
switch (ip)
{
case MeInfo:
{
MEInfo mei = m->getMEInfo();
cout << _("<ME0> Manufacturer: ") << mei._manufacturer << endl
<< _("<ME1> Model: ") << mei._model << endl
<< _("<ME2> Revision: ") << mei._revision << endl
<< _("<ME3> Serial Number: ") << mei._serialNumber << endl;
break;
}
case OperatorInfo:
{
int count = 0;
vector<OPInfo> opis = m->getAvailableOPInfo();
for (vector<OPInfo>::iterator i = opis.begin(); i != opis.end(); ++i)
{
cout << "<OP" << count << _("> Status: ");
switch (i->_status)
{
case UnknownOPStatus: cout << _("unknown"); break;
case CurrentOPStatus: cout << _("current"); break;
case AvailableOPStatus: cout << _("available"); break;
case ForbiddenOPStatus: cout << _("forbidden"); break;
}
cout << _(" Long name: '") << i->_longName << "' "
<< _(" Short name: '") << i->_shortName << "' "
<< _(" Numeric name: ") << i->_numericName << endl;
++count;
}
break;
}
case CurrentOperatorInfo:
{
OPInfo opi = m->getCurrentOPInfo();
cout << "<CURROP0>"
<< _(" Long name: '") << opi._longName << "' "
<< _(" Short name: '") << opi._shortName << "' "
<< _(" Numeric name: ") << opi._numericName
<< _(" Mode: ");
switch (opi._mode)
{
case AutomaticOPMode: cout << _("automatic"); break;
case ManualOPMode: cout << _("manual"); break;
case DeregisterOPMode: cout << _("deregister"); break;
case ManualAutomaticOPMode: cout << _("manual/automatic"); break;
}
cout << endl;
break;
}
case FacilityLockStateInfo:
{
int count = 0;
vector<string> fclc = m->getFacilityLockCapabilities();
for (vector<string>::iterator i = fclc.begin(); i != fclc.end(); ++i)
if (*i != "AB" && *i != "AG" && *i != "AC")
{
cout << "<FLSTAT" << count << "> '" << *i << "'";
try
{
if (m->getFacilityLockStatus(*i, VoiceFacility))
cout << _(" Voice");
}
catch (GsmException &e)
{
cout << _(" unknown");
}
try
{
if (m->getFacilityLockStatus(*i, DataFacility))
cout << _(" Data");
}
catch (GsmException &e)
{
cout << _(" unknown");
}
try
{
if (m->getFacilityLockStatus(*i, FaxFacility))
cout << _(" Fax");
}
catch (GsmException &e)
{
cout << _(" unknown");
}
cout << endl;
++count;
}
break;
}
case FacilityLockCapabilityInfo:
{
cout << "<FLCAP0> ";
vector<string> fclc = m->getFacilityLockCapabilities();
for (vector<string>::iterator i = fclc.begin(); i != fclc.end(); ++i)
cout << "'" << *i << "' ";
cout << endl;
break;
}
case PasswordInfo:
{
vector<PWInfo> pwi = m->getPasswords();
int count = 0;
for (vector<PWInfo>::iterator i = pwi.begin(); i != pwi.end(); ++i)
{
cout << "<PW" << count << "> '"
<< i->_facility << "' " << i->_maxPasswdLen << endl;
++count;
}
break;
}
case CLIPInfo:
{
cout << "<CLIP0> " << (m->getNetworkCLIP() ? _("on") : _("off")) << endl;
break;
}
case CallForwardingInfo:
{
for (int r = 0; r < 4; ++r)
{
string text;
switch (r)
{
case 0: text = _("UnconditionalReason"); break;
case 1: text = _("MobileBusyReason"); break;
case 2: text = _("NoReplyReason"); break;
case 3: text = _("NotReachableReason"); break;
}
ForwardInfo voice, fax, data;
m->getCallForwardInfo((ForwardReason)r, voice, fax, data);
cout << "<FORW" << r << ".";
printForwardReason("0> " + text + _(" Voice"), voice);
cout << "<FORW" << r << ".";
printForwardReason("1> " + text + _(" Data"), data);
cout << "<FORW" << r << ".";
printForwardReason("2> " + text + _(" Fax"), fax);
}
break;
}
case BatteryInfo:
{
cout << "<BATT0> ";
int bcs = m->getBatteryChargeStatus();
switch (bcs)
{
case 0: cout << _("0 ME is powered by the battery") << endl; break;
case 1: cout << _("1 ME has a battery connected, but is not powered by it")
<< endl; break;
case 2: cout << _("2 ME does not have a battery connected") << endl; break;
case 3:
cout << _("3 Recognized power fault, calls inhibited") << endl;
break;
}
cout << "<BATT1> " << m->getBatteryCharge() << endl;
break;
}
case BitErrorInfo:
{
cout << "<BITERR0> " << m->getBitErrorRate() << endl;
break;
}
case SCAInfo:
{
cout << "<SCA0> " << m->getServiceCentreAddress() << endl;
break;
}
case CharSetInfo:
{
cout << "<CSET0> ";
vector<string> cs = m->getSupportedCharSets();
for (vector<string>::iterator i = cs.begin(); i != cs.end(); ++i)
cout << "'" << *i << "' ";
cout << endl;
cout << "<CSET1> '" << m->getCurrentCharSet() << "'" << endl;
break;
}
case SignalInfo:
{
cout << "<SIG0> " << m->getSignalStrength() << endl;
break;
}
case PhonebookInfo:
{
cout << "<PBOOK0> ";
vector<string> pb = m->getSupportedPhonebooks();
for (vector<string>::iterator i = pb.begin(); i != pb.end(); ++i)
cout << "'" << *i << "' ";
cout << endl;
cout << "<PBOOK1> '" << m->getCurrentPhonebook() << "'" << endl;
break;
}
case SignalToneInfo:
{
cout << "<SIGNAL0> ";
IntRange st = m->getSupportedSignalTones();
printIntRange(st);
cout << endl;
// cout << "<SIGT1> '" << m->getCurrentSignalTone() << "'" << endl;
break;
}
case RingingToneInfo:
{
cout << "<RING0> ";
IntRange rt = m->getSupportedRingingTones();
printIntRange(rt);
cout << endl;
cout << "<RING1> " << m->getCurrentRingingTone() << endl;
break;
}
case BinaryInfo:
{
cout << "<BIN0> ";
vector<ParameterRange> bnr = m->getSupportedBinaryReads();
for (vector<ParameterRange>::iterator i = bnr.begin(); i != bnr.end(); ++i)
{
printParameterRange(*i);
cout << " ";
}
cout << endl;
cout << "<BIN1> ";
vector<ParameterRange> bnw = m->getSupportedBinaryWrites();
for (vector<ParameterRange>::iterator i = bnw.begin(); i != bnw.end(); ++i)
{
printParameterRange(*i);
cout << " ";
}
cout << endl;
break;
}
default:
assert(0);
break;
}
}
// convert facility class string of the form "", "all", or any combination
// of "v" (voice), "d" (data), or "f" (fax) to numeric form
FacilityClass strToFacilityClass(string facilityClassS)
{
facilityClassS = lowercase(facilityClassS);
FacilityClass facilityClass = (FacilityClass)0;
if (facilityClassS == "all" || facilityClassS == "")
return (FacilityClass)ALL_FACILITIES;
// OR in facility class bits
for (unsigned int i = 0; i < facilityClassS.length(); ++i)
if (facilityClassS[i] == 'v')
facilityClass = (FacilityClass)(facilityClass | VoiceFacility);
else if (facilityClassS[i] == 'd')
facilityClass = (FacilityClass)(facilityClass | DataFacility);
else if (facilityClassS[i] == 'f')
facilityClass = (FacilityClass)(facilityClass | FaxFacility);
else
throw GsmException(
stringPrintf(_("unknown facility class parameter '%c'"),
facilityClassS[i]), ParameterError);
return facilityClass;
}
// check if argc - optind is in range min..max
// throw exception otherwise
void checkParamCount(int optind, int argc, int min, int max)
{
int paramCount = argc - optind;
if (paramCount < min)
throw GsmException(stringPrintf(_("not enough parameters, minimum number "
"of parameters is %d"), min),
ParameterError);
else if (paramCount > max)
throw GsmException(stringPrintf(_("too many parameters, maximum number "
"of parameters is %d"), max),
ParameterError);
}
// *** main program
int main(int argc, char *argv[])
{
try
{
// handle command line options
string device = "/dev/mobilephone";
string operation;
string baudrate;
string initString = DEFAULT_INIT_STRING;
bool swHandshake = false;
int opt;
int dummy;
while((opt = getopt_long(argc, argv, "I:o:d:b:hvX", longOpts, &dummy))
!= -1)
switch (opt)
{
case 'X':
swHandshake = true;
break;
case 'I':
initString = optarg;
break;
case 'd':
device = optarg;
break;
case 'o':
operation = optarg;
break;
case 'b':
baudrate = optarg;
break;
case 'v':
cerr << argv[0] << stringPrintf(_(": version %s [compiled %s]"),
VERSION, __DATE__) << endl;
exit(0);
break;
case 'h':
cerr << argv[0] << _(": [-b baudrate][-d device][-h]"
"[-I init string][-o operation]\n"
" [-v][-X]{parameters}") << endl
<< endl
<< _(" -b, --baudrate baudrate to use for device "
"(default: 38400)")
<< endl
<< _(" -d, --device sets the destination device to "
"connect to") << endl
<< _(" -h, --help prints this message") << endl
<< _(" -I, --init device AT init sequence") << endl
<< _(" -o, --operation operation to perform on the mobile \n"
" phone with the specified parameters")
<< endl
<< _(" -v, --version prints version and exits") << endl
<< _(" -X, --xonxoff switch on software handshake") << endl
<< endl
<< _(" parameters parameters to use for the operation\n"
" (if an operation is given) or\n"
" a specification which kind of\n"
" information to read from the mobile "
"phone")
<< endl << endl
<< _("Refer to gsmctl(1) for details on the available parameters"
" and operations.")
<< endl << endl;
exit(0);
break;
case '?':
throw GsmException(_("unknown option"), ParameterError);
break;
}
// open the port and ME/TA
m = new SieMe(new
#ifdef WIN32
Win32SerialPort
#else
UnixSerialPort
#endif
(device,
baudrate == "" ?
DEFAULT_BAUD_RATE :
baudRateStrToSpeed(baudrate),
initString, swHandshake));
if (operation == "")
{ // process info parameters
for (int i = optind; i < argc; ++i)
{
string param = lowercase(argv[i]);
if (param == "all")
for (int ip = MeInfo; ip <= SignalInfo; ++ip)
printInfo((InfoParameter)ip);
else if (param == "me")
printInfo(MeInfo);
else if (param == "op")
printInfo(OperatorInfo);
else if (param == "currop")
printInfo(CurrentOperatorInfo);
else if (param == "flstat")
printInfo(FacilityLockStateInfo);
else if (param == "flcap")
printInfo(FacilityLockCapabilityInfo);
else if (param == "pw")
printInfo(PasswordInfo);
else if (param == "clip")
printInfo(CLIPInfo);
else if (param == "forw")
printInfo(CallForwardingInfo);
else if (param == "batt")
printInfo(BatteryInfo);
else if (param == "biterr")
printInfo(BitErrorInfo);
else if (param == "sig")
printInfo(SignalInfo);
else if (param == "sca")
printInfo(SCAInfo);
else if (param == "cset")
printInfo(CharSetInfo);
else if (param == "pbook")
printInfo(PhonebookInfo);
else if (param == "signal")
printInfo(SignalToneInfo);
else if (param == "ring")
printInfo(RingingToneInfo);
else if (param == "binary")
printInfo(BinaryInfo);
else
throw GsmException(
stringPrintf(_("unknown information parameter '%s'"),
param.c_str()),
ParameterError);
}
}
else
{ // process operation
operation = lowercase(operation);
if (operation == "dial")
{
// dial: number
checkParamCount(optind, argc, 1, 1);
m->dial(argv[optind]);
// wait for keypress from stdin
char c;
read(1, &c, 1);
}
else if (operation == "setop")
{
// setop: opmode numeric FIXME allow long and numeric too
checkParamCount(optind, argc, 2, 2);
string opmodeS = lowercase(argv[optind]);
OPModes opmode;
if (opmodeS == "automatic")
opmode = AutomaticOPMode;
else if (opmodeS == "manual")
opmode = ManualOPMode;
else if (opmodeS == "deregister")
opmode = DeregisterOPMode;
else if (opmodeS == "manualautomatic")
opmode = ManualAutomaticOPMode;
else
throw GsmException(stringPrintf(_("unknown opmode parameter '%s'"),
opmodeS.c_str()), ParameterError);
m->setCurrentOPInfo(opmode, "" , "", checkNumber(argv[optind + 1]));
}
else if (operation == "lock")
{
// lock: facility [facilityclass] [passwd]
checkParamCount(optind, argc, 1, 3);
string passwd = (argc - optind == 3) ?
(string)argv[optind + 2] : (string)"";
m->lockFacility(argv[optind],
(argc - optind >= 2) ?
strToFacilityClass(argv[optind + 1]) :
(FacilityClass)ALL_FACILITIES,
passwd);
}
else if (operation == "unlock")
{
// unlock: facility [facilityclass] [passwd]
checkParamCount(optind, argc, 1, 3);
string passwd = argc - optind == 3 ? argv[optind + 2] : "";
m->unlockFacility(argv[optind],
(argc - optind >= 2) ?
strToFacilityClass(argv[optind + 1]) :
(FacilityClass)ALL_FACILITIES,
passwd);
}
else if (operation == "setpw")
{
// set password: facility oldpasswd newpasswd
checkParamCount(optind, argc, 1, 3);
string oldPasswd = argc - optind >= 2 ? argv[optind + 1] : "";
string newPasswd = argc - optind == 3 ? argv[optind + 2] : "";
m->setPassword(argv[optind], oldPasswd, newPasswd);
}
else if (operation == "forw")
{
// call forwarding: mode reason number [facilityclass] [forwardtime]
checkParamCount(optind, argc, 2, 5);
// get optional parameters facility class and forwardtime
int forwardTime = argc - optind == 5 ? checkNumber(argv[optind + 4]) :
NOT_SET;
FacilityClass facilityClass =
argc - optind >= 4 ? strToFacilityClass(argv[optind + 3]) :
(FacilityClass)ALL_FACILITIES;
// get forward reason
string reasonS = lowercase(argv[optind + 1]);
ForwardReason reason;
if (reasonS == "unconditional")
reason = UnconditionalReason;
else if (reasonS == "mobilebusy")
reason = MobileBusyReason;
else if (reasonS == "noreply")
reason = NoReplyReason;
else if (reasonS == "notreachable")
reason = NotReachableReason;
else if (reasonS == "all")
reason = AllReasons;
else if (reasonS == "allconditional")
reason = AllConditionalReasons;
else
throw GsmException(
stringPrintf(_("unknown forward reason parameter '%s'"),
reasonS.c_str()), ParameterError);
// get mode
string modeS = lowercase(argv[optind]);
ForwardMode mode;
if (modeS == "disable")
mode = DisableMode;
else if (modeS == "enable")
mode = EnableMode;
else if (modeS == "register")
mode = RegistrationMode;
else if (modeS == "erase")
mode = ErasureMode;
else
throw GsmException(
stringPrintf(_("unknown forward mode parameter '%s'"),
modeS.c_str()), ParameterError);
m->setCallForwarding(reason, mode,
(argc - optind >= 3) ? argv[optind + 2] : "",
"", // subaddr
facilityClass, forwardTime);
}
else if (operation == "setsca")
{
// set sca: number
checkParamCount(optind, argc, 1, 1);
m->setServiceCentreAddress(argv[optind]);
}
else if (operation == "cset")
{
// set charset: string
checkParamCount(optind, argc, 1, 1);
m->setCharSet(argv[optind]);
}
else if (operation == "signal")
{
// play signal tone: int
checkParamCount(optind, argc, 1, 1);
int tone = atoi(argv[optind]);
m->playSignalTone(tone);
}
else if (operation == "setrt")
{
// set ringing tone: int int
checkParamCount(optind, argc, 2, 2);
int tone = atoi(argv[optind]);
int volume = atoi(argv[optind + 1]);
m->setRingingTone(tone, volume);
}
else if (operation == "playrt")
{
// play/stop ringing tone
m->toggleRingingTone();
}
else
throw GsmException(stringPrintf(_("unknown operation '%s'"),
operation.c_str()), ParameterError);
}
}
catch (GsmException &ge)
{
cerr << argv[0] << _("[ERROR]: ") << ge.what() << endl;
return 1;
}
return 0;
}

View File

@ -0,0 +1,292 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsmsiexfer.cc
// *
// * Purpose: Siemens ME file transfer program
// *
// * Author: Christian W. Zuckschwerdt <zany@triq.net>
// *
// * Created: 2001-12-16
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_nls.h>
#include <string>
#ifdef WIN32
#include <gsmlib/gsm_win32_serial.h>
#else
#include <gsmlib/gsm_unix_serial.h>
#include <unistd.h>
#endif
#if defined(HAVE_GETOPT_LONG) || defined(WIN32)
#include <getopt.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <gsmlib/gsm_me_ta.h>
#include <gsm_sie_me.h>
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_sorted_phonebook.h>
#include <iostream>
using namespace std;
using namespace gsmlib;
#ifdef HAVE_GETOPT_LONG
static struct option longOpts[] =
{
{"xonxoff", no_argument, (int*)NULL, 'X'},
{"init", required_argument, (int*)NULL, 'I'},
{"destination", required_argument, (int*)NULL, 'd'},
{"source", required_argument, (int*)NULL, 's'},
{"baudrate", required_argument, (int*)NULL, 'b'},
{"type", required_argument, (int*)NULL, 't'},
{"subtype", required_argument, (int*)NULL, 'i'},
{"help", no_argument, (int*)NULL, 'h'},
{"version", no_argument, (int*)NULL, 'v'},
{"verbose", no_argument, (int*)NULL, 'V'},
{(char*)NULL, 0, (int*)NULL, 0}
};
#else
#define getopt_long(argc, argv, options, longopts, indexptr) \
getopt(argc, argv, options)
#endif
// I f*ck up this file IO thing.
// read binary object from stdin
BinaryObject readBinaryFile(istream &ifs, string filename)
{
size_t size = 10000; // Bad coder, no biscuits!
BinaryObject bnr;
bnr._data = new unsigned char[size];
ifs.read((char*)bnr._data, size);
bnr._size = ifs.gcount();
return bnr;
}
// read binary object from file
BinaryObject readFile(string filename)
{
// open the file
ifstream ifs(filename.c_str());
if (ifs.bad())
throw GsmException(stringPrintf(_("cannot open file '%s'"),
filename.c_str()),
OSError);
// and read the file
return readBinaryFile(ifs, filename);
}
// read binary object from stdin
BinaryObject readFile(bool fromStdin)
{
// read from stdin
// if (fromStdin)
return readBinaryFile(cin, (string)_("<STDIN>"));
}
// write binary object to file
void writeBinaryFile(ostream &ofs, string filename, BinaryObject bnw)
{
// well just dump the data
ofs.write((char*)bnw._data, bnw._size);
}
// write binary object
void writeFile(string filename, BinaryObject obj)
{
// open the file
ofstream ofs(filename.c_str());
if (ofs.bad())
throw GsmException(stringPrintf(_("cannot open file '%s'"),
filename.c_str()),
OSError);
// and read the file
writeBinaryFile(ofs, filename, obj);
}
// write binary object to stdout
void writeFile(bool toStdout, BinaryObject obj)
{
// if (toStdout)
writeBinaryFile(cout, (string)_("<STDIN>"), obj);
}
// *** main program
int main(int argc, char *argv[])
{
try
{
// handle command line options
string destination;
string source;
string baudrate;
string type;
string subtype;
int subtypeN;
bool verbose = false;
string initString = DEFAULT_INIT_STRING;
bool swHandshake = false;
Ref<SieMe> sourceMeTa, destMeTa;
BinaryObject sourceObject;
int opt;
int dummy;
while((opt = getopt_long(argc, argv, "XI:s:d:b:hvVt:i:", longOpts,
&dummy))
!= -1)
switch (opt)
{
case 'X':
swHandshake = true;
break;
case 'I':
initString = optarg;
break;
case 'V':
verbose = true;
break;
case 't':
type = optarg;
break;
case 'i':
subtype = optarg;
subtypeN = atoi(optarg);
break;
case 'd':
destination = optarg;
break;
case 's':
source = optarg;
break;
case 'b':
baudrate = optarg;
break;
case 'v':
cerr << argv[0] << stringPrintf(_(": version %s [compiled %s]"),
VERSION, __DATE__) << endl;
exit(0);
break;
case 'h':
cerr << argv[0] << _(": [-b baudrate][-c][-d device or file][-h]"
"[-I init string]\n"
" [-p phonebook name][-s device or file]"
"[-t charset][-v]"
"[-V][-y][-X]") << endl
<< endl
<< _(" -b, --baudrate baudrate to use for device "
"(default: 38400)")
<< endl
<< _(" -c, --copy copy source entries to destination")
<< endl
<< _(" -d, --destination sets the destination device to "
"connect \n"
" to, or the file to write") << endl
<< _(" -D, --destination-backend sets the destination backend")
<< endl
<< _(" -h, --help prints this message") << endl
<< _(" -i, --index takes index positions into account")
<< endl
<< _(" -I, --init device AT init sequence") << endl
<< _(" -p, --phonebook name of phonebook to use") << endl
<< _(" -s, --source sets the source device to connect to,\n"
" or the file to read") << endl
<< _(" -t, --charset sets the character set to use for\n"
" phonebook entries") << endl
<< _(" -S, --source-backend sets the source backend")
<< endl
<< _(" -v, --version prints version and exits") << endl
<< _(" -V, --verbose print detailed progress messages")
<< endl
<< _(" -X, --xonxoff switch on software handshake") << endl
<< _(" -y, --synchronize synchronize destination with source\n"
" entries (destination is overwritten)\n"
" (see gsmpb(1) for details)")
<< endl << endl;
exit(0);
break;
case '?':
throw GsmException(_("unknown option"), ParameterError);
break;
}
// check if all parameters all present
if (destination == "" || source == "")
throw GsmException(_("both source and destination must be given"),
ParameterError);
// start accessing source mobile phone or file
if (source == "-")
sourceObject = readFile(true);
else if (isFile(source))
sourceObject = readFile(source);
else
{
if (type == "")
throw GsmException(_("type be given"), ParameterError);
if (subtype == "")
throw GsmException(_("subtype be given"), ParameterError);
sourceMeTa = new SieMe(new
#ifdef WIN32
Win32SerialPort
#else
UnixSerialPort
#endif
(source,
baudrate == "" ? DEFAULT_BAUD_RATE :
baudRateStrToSpeed(baudrate), initString,
swHandshake));
sourceObject = sourceMeTa->getBinary(type, subtypeN);
}
// make sure destination.c_str file exists
if (destination != "")
{
try
{
ofstream f(destination.c_str(), ios::out | ios::app);
}
catch (exception)
{
}
}
// start accessing destination mobile phone or file
if (destination == "-")
writeFile(true, sourceObject);
else if (isFile(destination))
writeFile(destination, sourceObject);
else
{
if (type == "")
throw GsmException(_("type must be given"), ParameterError);
if (subtype == "")
throw GsmException(_("subtype must be given"), ParameterError);
destMeTa = new SieMe(new
#ifdef WIN32
Win32SerialPort
#else
UnixSerialPort
#endif
(destination,
baudrate == "" ? DEFAULT_BAUD_RATE :
baudRateStrToSpeed(baudrate), initString,
swHandshake));
destMeTa->setBinary(type, subtypeN, sourceObject);
}
}
catch (GsmException &ge)
{
cerr << argv[0] << _("[ERROR]: ") << ge.what() << endl;
return 1;
}
return 0;
}

View File

@ -0,0 +1,29 @@
--- ./gsmlib/gsm_me_ta.h~ 2006-03-09 19:15:59.000000000 +0000
+++ ./gsmlib/gsm_me_ta.h 2006-03-09 19:16:31.000000000 +0000
@@ -291,8 +291,8 @@
// 3 disable phone receive RF circuits only
// 4 disable phone both transmit and receive RF circuits
// 5...127 implementation-defined
- int MeTa::getFunctionalityLevel() throw(GsmException);
- void MeTa::setFunctionalityLevel(int level) throw(GsmException);
+ int getFunctionalityLevel() throw(GsmException);
+ void setFunctionalityLevel(int level) throw(GsmException);
// return battery charge status (+CBC):
// 0 ME is powered by the battery
@@ -386,13 +386,13 @@
void setCallWaitingLockStatus(FacilityClass cl,
bool lock)throw(GsmException);
- void MeTa::setCLIRPresentation(bool enable) throw(GsmException);
+ void setCLIRPresentation(bool enable) throw(GsmException);
//(+CLIR)
// 0:according to the subscription of the CLIR service
// 1:CLIR invocation
// 2:CLIR suppression
- int MeTa::getCLIRPresentation() throw(GsmException);
+ int getCLIRPresentation() throw(GsmException);
friend class Phonebook;
friend class SMSStore;

View File

@ -0,0 +1,344 @@
/* gsm_config.h.in. Generated from configure.in by autoheader. */
/* used by libtool*/
#define PACKAGE 0
/* used by libtool*/
#define VERSION 0
/* Define if getopt_long() available */
#undef HAVE_GETOPT_LONG
/* Define if alarm() available */
#undef HAVE_ALARM
/* Define if netinet/in.h header available */
#undef HAVE_NETINET_IN_H
/* Define if string.h header available */
#undef HAVE_STRING_H
/* Define for NLS */
#undef ENABLE_NLS
#undef HAVE_CATGETS
#undef HAVE_GETTEXT
#undef HAVE_LC_MESSAGES
#undef HAVE_STPCPY
/* Define LOCALEDIR */
#define LOCALEDIR "/usr/share/locale"
/* Define if libintl.h header available */
#undef HAVE_LIBINTL_H
/* Define if vsnprintf() function available */
#undef HAVE_VSNPRINTF
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
#undef CRAY_STACKSEG_END
/* Define to 1 if using `alloca.c'. */
#undef C_ALLOCA
/* Define to 1 if translation of program messages to the user's native
language is requested. */
#undef ENABLE_NLS
/* Define to 1 if you have `alloca', as a function or macro. */
#undef HAVE_ALLOCA
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
#undef HAVE_ALLOCA_H
/* Define to 1 if you have the <argz.h> header file. */
#undef HAVE_ARGZ_H
/* Define to 1 if you have the `asprintf' function. */
#undef HAVE_ASPRINTF
/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
CoreFoundation framework. */
#undef HAVE_CFLOCALECOPYCURRENT
/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in
the CoreFoundation framework. */
#undef HAVE_CFPREFERENCESCOPYAPPVALUE
/* Define if the GNU dcgettext() function is already present or preinstalled.
*/
#undef HAVE_DCGETTEXT
/* Define to 1 if you have the declaration of `feof_unlocked', and to 0 if you
don't. */
#undef HAVE_DECL_FEOF_UNLOCKED
/* Define to 1 if you have the declaration of `fgets_unlocked', and to 0 if
you don't. */
#undef HAVE_DECL_FGETS_UNLOCKED
/* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you
don't. */
#undef HAVE_DECL_GETC_UNLOCKED
/* Define to 1 if you have the declaration of `_snprintf', and to 0 if you
don't. */
#undef HAVE_DECL__SNPRINTF
/* Define to 1 if you have the declaration of `_snwprintf', and to 0 if you
don't. */
#undef HAVE_DECL__SNWPRINTF
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the `fwprintf' function. */
#undef HAVE_FWPRINTF
/* Define to 1 if you have the `getcwd' function. */
#undef HAVE_GETCWD
/* Define to 1 if you have the `getegid' function. */
#undef HAVE_GETEGID
/* Define to 1 if you have the `geteuid' function. */
#undef HAVE_GETEUID
/* Define to 1 if you have the `getgid' function. */
#undef HAVE_GETGID
/* Define to 1 if you have the `getpagesize' function. */
#undef HAVE_GETPAGESIZE
/* Define if the GNU gettext() function is already present or preinstalled. */
#undef HAVE_GETTEXT
/* Define to 1 if you have the `getuid' function. */
#undef HAVE_GETUID
/* Define if you have the iconv() function. */
#undef HAVE_ICONV
/* Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>. */
#undef HAVE_INTMAX_T
/* Define if <inttypes.h> exists and doesn't clash with <sys/types.h>. */
#undef HAVE_INTTYPES_H
/* Define if <inttypes.h> exists, doesn't clash with <sys/types.h>, and
declares uintmax_t. */
#undef HAVE_INTTYPES_H_WITH_UINTMAX
/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
#undef HAVE_LANGINFO_CODESET
/* Define if your <locale.h> file defines LC_MESSAGES. */
#undef HAVE_LC_MESSAGES
/* Define to 1 if you have the `intl' library (-lintl). */
#undef HAVE_LIBINTL
/* Define to 1 if you have the <libintl.h> header file. */
#undef HAVE_LIBINTL_H
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
/* Define if you have the 'long double' type. */
#undef HAVE_LONG_DOUBLE
/* Define if you have the 'long long' type. */
#undef HAVE_LONG_LONG
/* Define to 1 if you have the <malloc.h> header file. */
#undef HAVE_MALLOC_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `mempcpy' function. */
#undef HAVE_MEMPCPY
/* Define to 1 if you have a working `mmap' system call. */
#undef HAVE_MMAP
/* Define to 1 if you have the `munmap' function. */
#undef HAVE_MUNMAP
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define to 1 if you have the <nl_types.h> header file. */
#undef HAVE_NL_TYPES_H
/* Define if your printf() function supports format strings with positions. */
#undef HAVE_POSIX_PRINTF
/* Define to 1 if you have the `putenv' function. */
#undef HAVE_PUTENV
/* Define to 1 if you have the `setenv' function. */
#undef HAVE_SETENV
/* Define to 1 if you have the `setlocale' function. */
#undef HAVE_SETLOCALE
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define if <stdint.h> exists, doesn't clash with <sys/types.h>, and declares
uintmax_t. */
#undef HAVE_STDINT_H_WITH_UINTMAX
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `stpcpy' function. */
#undef HAVE_STPCPY
/* Define to 1 if you have the `strcasecmp' function. */
#undef HAVE_STRCASECMP
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strtoul' function. */
#undef HAVE_STRTOUL
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the `tsearch' function. */
#undef HAVE_TSEARCH
/* Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>. */
#undef HAVE_UINTMAX_T
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define if you have the 'unsigned long long' type. */
#undef HAVE_UNSIGNED_LONG_LONG
/* Define if you have the 'wchar_t' type. */
#undef HAVE_WCHAR_T
/* Define to 1 if you have the `wcslen' function. */
#undef HAVE_WCSLEN
/* Define if you have the 'wint_t' type. */
#undef HAVE_WINT_T
/* Define to 1 if you have the `__argz_count' function. */
#undef HAVE___ARGZ_COUNT
/* Define to 1 if you have the `__argz_next' function. */
#undef HAVE___ARGZ_NEXT
/* Define to 1 if you have the `__argz_stringify' function. */
#undef HAVE___ARGZ_STRINGIFY
/* Define to 1 if you have the `__fsetlocking' function. */
#undef HAVE___FSETLOCKING
/* Define as const if the declaration of iconv() needs const. */
#undef ICONV_CONST
/* Define if integer division by zero raises signal SIGFPE. */
#undef INTDIV0_RAISES_SIGFPE
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define if <inttypes.h> exists and defines unusable PRI* macros. */
#undef PRI_MACROS_BROKEN
/* The size of a `unsigned int', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_INT
/* The size of a `unsigned long int', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_LONG_INT
/* The size of a `unsigned short int', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_SHORT_INT
/* Define as the maximum value of type 'size_t', if the system doesn't define
it. */
#undef SIZE_MAX
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
#undef STACK_DIRECTION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to `long' if <sys/types.h> does not define. */
#undef off_t
/* Define as the type of the result of subtracting two pointers, if the system
doesn't define it. */
#undef ptrdiff_t
/* Define to empty if the C compiler doesn't support this keyword. */
#undef signed
/* Define to `unsigned' if <sys/types.h> does not define. */
#undef size_t
/* Define to unsigned long or unsigned long long if <stdint.h> and
<inttypes.h> don't define. */
#undef uintmax_t

View File

@ -0,0 +1,11 @@
var/spool/sms/queue1
var/spool/sms/queue2
var/spool/sms/queue3
var/spool/sms/sent1
var/spool/sms/sent2
var/spool/sms/sent3
var/spool/sms/failed1
var/spool/sms/failed2
var/spool/sms/failed3
var/spool/sms/tmp
var/run/gsm-utils

View File

@ -0,0 +1,28 @@
#!/bin/sh -e
# create gsmsms group if necessary.
if ! grep -q ^gsmsms: /etc/group; then
# echo Adding system group: gsmsms.
addgroup gsmsms
fi
# create gsmsms user if necessary.
if ! grep -q ^gsmsms: /etc/passwd; then
# echo Adding system user: gsmsms.
adduser --system --ingroup gsmsms \
--no-create-home --home /var/spool/sms gsmsms
fi
# allow gsmsms to use serial lines
if ! groups gsmsms | grep -q dialout ; then
adduser gsmsms dialout
fi
# echo Updating spool directory structure: /var/spool/sms
chown -R gsmsms:gsmsms /var/spool/sms /var/run/gsm-utils
chmod 700 /var/spool/sms/*
chmod 750 /var/spool/sms
chmod 730 /var/spool/sms/queue* /var/spool/sms/tmp
# Add the rest automatically..
#DEBHELPER#

View File

@ -0,0 +1,7 @@
#!/bin/sh -e
deluser gsmsms || true
delgroup gsmsms || true
# Add the rest automatically..
#DEBHELPER#

View File

@ -0,0 +1,92 @@
%define LIBVER 1.0.4
Summary: Library to access GSM mobile phones through GSM modems
Name: gsmlib
Version: 1.10
Release: 1
Source: gsmlib-%{version}.tar.gz
Group: System Environment/Libraries
Copyright: GNU LIBRARY GENERAL PUBLIC LICENSE
URL: http://www.pxh.de/fs/gsmlib/
Vendor: Peter Hofmann <software@pxh.de>
Buildroot: /var/tmp/gsmlib-root
%package devel
Summary: Development tools for programs which will use the gsmlib library.
Group: Development/Libraries
Requires: gsmlib
%package ext
Summary: Extensions to gsmlib to support non-standard phone features.
Group: Development/Libraries
Requires: gsmlib
%description
This distribution contains a library to access
GSM mobile phones through GSM modems. Features include:
* modification of phonebooks stored in the
mobile phone or on the SIM card
* reading and writing of SMS messages stored in
the mobile phone
* sending and reception of SMS messages
Additionally, some simple command line programs are
provided to use these functionalities.
%description devel
The gsmlib-devel package includes the header files and static libraries
necessary for developing programs which use the gsmlib library.
%description ext
The extension package of gsmlib contains programs, libraries, and
documentation to support non-standard features of GSM phones. The
following phones/phone types are currently supported:
* Siemens GSM phones
%prep
%setup
%build
CXXFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=/usr
make
%install
make DESTDIR="$RPM_BUILD_ROOT" install
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
/usr/lib/libgsmme.so
/usr/lib/libgsmme.so.%{LIBVER}
/usr/bin/gsmsmsstore
/usr/bin/gsmctl
/usr/bin/gsmsmsd
/usr/bin/gsmpb
/usr/bin/gsmsendsms
/usr/man/man1/gsmctl.1.gz
/usr/man/man7/gsminfo.7.gz
/usr/man/man1/gsmpb.1.gz
/usr/man/man1/gsmsendsms.1.gz
/usr/man/man8/gsmsmsd.8.gz
/usr/man/man1/gsmsmsstore.1.gz
/usr/share/locale/de/LC_MESSAGES/gsmlib.mo
%doc README INSTALL ABOUT-NLS AUTHORS COPYING NEWS TODO
%doc doc/README.NLS doc/README.developers doc/FAQ ChangeLog
%files devel
%defattr(-,root,root)
/usr/lib/libgsmme.a
/usr/include/gsmlib
%files ext
/usr/bin/gsmsiectl
/usr/bin/gsmsiexfer
/usr/lib/libgsmext.so
/usr/lib/libgsmext.so.%{LIBVER}
%doc ext/README.sieme

View File

@ -0,0 +1,38 @@
## Process this file with automake to produce Makefile.in
# *************************************************************************
# * GSM TA/ME library
# *
# * File: Makefile.am
# *
# * Purpose: GSM library Makefile
# *
# * Author: Peter Hofmann (software@pxh.de)
# *
# * Created: 5.5.1999
# *************************************************************************
INCLUDES = -I..
lib_LTLIBRARIES = libgsmme.la
libgsmme_la_SOURCES = gsm_phonebook.cc gsm_util.cc gsm_unix_serial.cc \
gsm_me_ta.cc gsm_at.cc gsm_error.cc gsm_parser.cc \
gsm_sms.cc gsm_sms_codec.cc gsm_sms_store.cc \
gsm_event.cc gsm_sorted_phonebook.cc \
gsm_sorted_sms_store.cc gsm_nls.cc \
gsm_sorted_phonebook_base.cc gsm_cb.cc
gsmincludedir = $(includedir)/gsmlib
gsminclude_HEADERS = gsm_at.h gsm_parser.h gsm_sms.h gsm_unix_serial.h \
gsm_error.h gsm_phonebook.h gsm_sms_codec.h \
gsm_util.h gsm_me_ta.h gsm_port.h gsm_sms_store.h \
gsm_event.h gsm_sorted_phonebook.h \
gsm_sorted_sms_store.h gsm_map_key.h \
gsm_sorted_phonebook_base.h gsm_cb.h
noinst_HEADERS = gsm_nls.h gsm_sysdep.h
libgsmme_la_LDFLAGS = -version-info $(GSM_VERSION)
EXTRA_DIST = gsm_win32_serial.h gsm_win32_serial.cc

View File

@ -0,0 +1,461 @@
# Makefile.in generated by automake 1.6.3 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# *************************************************************************
# * GSM TA/ME library
# *
# * File: Makefile.am
# *
# * Purpose: GSM library Makefile
# *
# * Author: Peter Hofmann (software@pxh.de)
# *
# * Created: 5.5.1999
# *************************************************************************
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_HEADER = $(INSTALL_DATA)
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
EXEEXT = @EXEEXT@
OBJEXT = @OBJEXT@
PATH_SEPARATOR = @PATH_SEPARATOR@
AMTAR = @AMTAR@
AS = @AS@
AWK = @AWK@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CPP = @CPP@
CXX = @CXX@
DATADIRNAME = @DATADIRNAME@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
ECHO = @ECHO@
GENCAT = @GENCAT@
GLIBC21 = @GLIBC21@
GMSGFMT = @GMSGFMT@
GSM_VERSION = @GSM_VERSION@
HAVE_LIB = @HAVE_LIB@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INSTOBJEXT = @INSTOBJEXT@
INTLBISON = @INTLBISON@
INTLLIBS = @INTLLIBS@
INTLOBJS = @INTLOBJS@
INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
LIB = @LIB@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIB = @LTLIB@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
MKINSTALLDIRS = @MKINSTALLDIRS@
OBJDUMP = @OBJDUMP@
PACKAGE = @PACKAGE@
POSUB = @POSUB@
RANLIB = @RANLIB@
STRIP = @STRIP@
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
am__include = @am__include@
am__quote = @am__quote@
install_sh = @install_sh@
INCLUDES = -I..
lib_LTLIBRARIES = libgsmme.la
libgsmme_la_SOURCES = gsm_phonebook.cc gsm_util.cc gsm_unix_serial.cc \
gsm_me_ta.cc gsm_at.cc gsm_error.cc gsm_parser.cc \
gsm_sms.cc gsm_sms_codec.cc gsm_sms_store.cc \
gsm_event.cc gsm_sorted_phonebook.cc \
gsm_sorted_sms_store.cc gsm_nls.cc \
gsm_sorted_phonebook_base.cc gsm_cb.cc
gsmincludedir = $(includedir)/gsmlib
gsminclude_HEADERS = gsm_at.h gsm_parser.h gsm_sms.h gsm_unix_serial.h \
gsm_error.h gsm_phonebook.h gsm_sms_codec.h \
gsm_util.h gsm_me_ta.h gsm_port.h gsm_sms_store.h \
gsm_event.h gsm_sorted_phonebook.h \
gsm_sorted_sms_store.h gsm_map_key.h \
gsm_sorted_phonebook_base.h gsm_cb.h
noinst_HEADERS = gsm_nls.h gsm_sysdep.h
libgsmme_la_LDFLAGS = -version-info $(GSM_VERSION)
EXTRA_DIST = gsm_win32_serial.h gsm_win32_serial.cc
subdir = gsmlib
mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/gsm_config.h
CONFIG_CLEAN_FILES =
LTLIBRARIES = $(lib_LTLIBRARIES)
libgsmme_la_LIBADD =
am_libgsmme_la_OBJECTS = gsm_phonebook.lo gsm_util.lo gsm_unix_serial.lo \
gsm_me_ta.lo gsm_at.lo gsm_error.lo gsm_parser.lo gsm_sms.lo \
gsm_sms_codec.lo gsm_sms_store.lo gsm_event.lo \
gsm_sorted_phonebook.lo gsm_sorted_sms_store.lo gsm_nls.lo \
gsm_sorted_phonebook_base.lo gsm_cb.lo
libgsmme_la_OBJECTS = $(am_libgsmme_la_OBJECTS)
DEFS = @DEFS@
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
depcomp = $(SHELL) $(top_srcdir)/scripts/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/gsm_at.Plo ./$(DEPDIR)/gsm_cb.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_error.Plo ./$(DEPDIR)/gsm_event.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_me_ta.Plo ./$(DEPDIR)/gsm_nls.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_parser.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_phonebook.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_sms.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_sms_codec.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_sms_store.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_sorted_phonebook.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_sorted_phonebook_base.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_sorted_sms_store.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_unix_serial.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_util.Plo
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
CXXFLAGS = @CXXFLAGS@
DIST_SOURCES = $(libgsmme_la_SOURCES)
HEADERS = $(gsminclude_HEADERS) $(noinst_HEADERS)
DIST_COMMON = $(gsminclude_HEADERS) $(noinst_HEADERS) Makefile.am \
Makefile.in
SOURCES = $(libgsmme_la_SOURCES)
all: all-am
.SUFFIXES:
.SUFFIXES: .cc .lo .o .obj
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu gsmlib/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
libLTLIBRARIES_INSTALL = $(INSTALL)
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(libdir)
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
if test -f $$p; then \
f="`echo $$p | sed -e 's|^.*/||'`"; \
echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$f"; \
$(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$f; \
else :; fi; \
done
uninstall-libLTLIBRARIES:
@$(NORMAL_UNINSTALL)
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
p="`echo $$p | sed -e 's|^.*/||'`"; \
echo " $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p"; \
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \
done
clean-libLTLIBRARIES:
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test -z "$dir" && dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
libgsmme.la: $(libgsmme_la_OBJECTS) $(libgsmme_la_DEPENDENCIES)
$(CXXLINK) -rpath $(libdir) $(libgsmme_la_LDFLAGS) $(libgsmme_la_OBJECTS) $(libgsmme_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT) core *.core
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_at.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_cb.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_error.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_event.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_me_ta.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_nls.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_parser.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_phonebook.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_sms.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_sms_codec.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_sms_store.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_sorted_phonebook.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_sorted_phonebook_base.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_sorted_sms_store.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_unix_serial.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_util.Plo@am__quote@
distclean-depend:
-rm -rf ./$(DEPDIR)
.cc.o:
@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
.cc.obj:
@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CXXCOMPILE) -c -o $@ `cygpath -w $<`
.cc.lo:
@AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(LTCXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
CXXDEPMODE = @CXXDEPMODE@
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
gsmincludeHEADERS_INSTALL = $(INSTALL_HEADER)
install-gsmincludeHEADERS: $(gsminclude_HEADERS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(gsmincludedir)
@list='$(gsminclude_HEADERS)'; for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f="`echo $$p | sed -e 's|^.*/||'`"; \
echo " $(gsmincludeHEADERS_INSTALL) $$d$$p $(DESTDIR)$(gsmincludedir)/$$f"; \
$(gsmincludeHEADERS_INSTALL) $$d$$p $(DESTDIR)$(gsmincludedir)/$$f; \
done
uninstall-gsmincludeHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(gsminclude_HEADERS)'; for p in $$list; do \
f="`echo $$p | sed -e 's|^.*/||'`"; \
echo " rm -f $(DESTDIR)$(gsmincludedir)/$$f"; \
rm -f $(DESTDIR)$(gsmincludedir)/$$f; \
done
ETAGS = etags
ETAGSFLAGS =
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@list='$(DISTFILES)'; for file in $$list; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) $(HEADERS)
installdirs:
$(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(gsmincludedir)
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
mostlyclean-am
distclean: distclean-am
distclean-am: clean-am distclean-compile distclean-depend \
distclean-generic distclean-libtool distclean-tags
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am: install-gsmincludeHEADERS
install-exec-am: install-libLTLIBRARIES
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
uninstall-am: uninstall-gsmincludeHEADERS uninstall-info-am \
uninstall-libLTLIBRARIES
.PHONY: GTAGS all all-am check check-am clean clean-generic \
clean-libLTLIBRARIES clean-libtool distclean distclean-compile \
distclean-depend distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am info info-am install \
install-am install-data install-data-am install-exec \
install-exec-am install-gsmincludeHEADERS install-info \
install-info-am install-libLTLIBRARIES install-man \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
tags uninstall uninstall-am uninstall-gsmincludeHEADERS \
uninstall-info-am uninstall-libLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,444 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_at.cc
// *
// * Purpose: Utility classes for AT command sequence handling
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 3.5.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_at.h>
#include <gsmlib/gsm_nls.h>
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_error.h>
#include <gsmlib/gsm_event.h>
#include <gsmlib/gsm_me_ta.h>
#include <ctype.h>
#include <strstream>
using namespace std;
using namespace gsmlib;
// GsmAt members
bool GsmAt::matchResponse(string answer, string responseToMatch)
{
if (answer.substr(0, responseToMatch.length()) == responseToMatch)
return true;
else
// some TAs omit the ':' at the end of the response
if (_meTa.getCapabilities()._omitsColon &&
responseToMatch[responseToMatch.length() - 1] == ':' &&
answer.substr(0, responseToMatch.length() - 1) ==
responseToMatch.substr(0, responseToMatch.length() - 1))
return true;
return false;
}
string GsmAt::cutResponse(string answer, string responseToMatch)
{
if (answer.substr(0, responseToMatch.length()) == responseToMatch)
return normalize(answer.substr(responseToMatch.length(),
answer.length() -
responseToMatch.length()));
else
// some TAs omit the ':' at the end of the response
if (_meTa.getCapabilities()._omitsColon &&
responseToMatch[responseToMatch.length() - 1] == ':' &&
answer.substr(0, responseToMatch.length() - 1) ==
responseToMatch.substr(0, responseToMatch.length() - 1))
return normalize(answer.substr(responseToMatch.length() - 1,
answer.length() -
responseToMatch.length() + 1));
assert(0);
return "";
}
void GsmAt::throwCmeException(string s) throw(GsmException)
{
if (matchResponse(s, "ERROR"))
throw GsmException(_("unspecified ME/TA error"), ChatError);
bool meError = matchResponse(s, "+CME ERROR:");
if (meError)
s = cutResponse(s, "+CME ERROR:");
else
s = cutResponse(s, "+CMS ERROR:");
istrstream is(s.c_str());
int error;
is >> error;
throw GsmException(_("ME/TA error '") +
(meError ? getMEErrorText(error) :
getSMSErrorText(error)) +
"' " +
stringPrintf(_("(code %s)"), s.c_str()),
ChatError, error);
}
GsmAt::GsmAt(MeTa &meTa) :
_meTa(meTa), _port(meTa.getPort()), _eventHandler(NULL)
{
}
string GsmAt::chat(string atCommand, string response,
bool ignoreErrors, bool acceptEmptyResponse)
throw(GsmException)
{
string dummy;
return chat(atCommand, response, dummy, ignoreErrors, false,
acceptEmptyResponse);
}
string GsmAt::chat(string atCommand, string response, string &pdu,
bool ignoreErrors, bool expectPdu,
bool acceptEmptyResponse) throw(GsmException)
{
string s;
bool gotOk = false; // special handling for empty SMS entries
// send AT command
putLine("AT" + atCommand);
// and gobble up CR/LF (and possibly echoed characters if echo can't be
// switched off)
// Also, some mobiles (e.g., Sony Ericsson K800i) respond to commands
// like "at+cmgf=0" with "+CMGF: 0" on success as well as the "OK"
// status -- so gobble that (but not if that sort of response was expected)
// FIXME: this is a gross hack, should be done via capabilities or sth
#include <string>
string::size_type loc = atCommand.find( "=", 1 );
string expect;
if (loc != string::npos) {
expect = atCommand;
expect.replace(loc, 1, " ");
expect.insert(loc, ":");
} else {
expect = "";
}
do
{
s = normalize(getLine());
}
while (s.length() == 0 || s == "AT" + atCommand ||
((response.length() == 0 || !matchResponse(s, response)) &&
(expect.length() > 0 && matchResponse(s, expect))));
// handle errors
if (matchResponse(s, "+CME ERROR:") || matchResponse(s, "+CMS ERROR:"))
if (ignoreErrors)
return "";
else
throwCmeException(s);
if (matchResponse(s, "ERROR"))
if (ignoreErrors)
return "";
else
throw GsmException(_("ME/TA error '<unspecified>' (code not known)"),
ChatError, -1);
// return if response is "OK" and caller says this is OK
if (acceptEmptyResponse && s == "OK")
return "";
// handle PDU if one is expected
if (expectPdu)
{
string ps;
do
{
ps = normalize(getLine());
}
while (ps.length() == 0 && ps != "OK");
if (ps == "OK")
gotOk = true;
else
{
pdu = ps;
// remove trailing zero added by some devices (e.g. Falcom A2-1)
if (pdu.length() > 0 && pdu[pdu.length() - 1] == 0)
pdu.erase(pdu.length() - 1);
}
}
// handle expected response
if (response.length() == 0) // no response expected
{
if (s == "OK") return "";
// else fall through to error
}
else
{
string result;
// some TA/TEs don't prefix their response with the response string
// as proscribed by the standard: just handle either case
if (matchResponse(s, response))
result = cutResponse(s, response);
else
result = s;
if (gotOk)
return result;
else
{
// get the final "OK"
do
{
s = normalize(getLine());
}
while (s.length() == 0);
if (s == "OK") return result;
// else fall through to error
}
}
throw GsmException(
stringPrintf(_("unexpected response '%s' when sending 'AT%s'"),
s.c_str(), atCommand.c_str()),
ChatError);
}
vector<string> GsmAt::chatv(string atCommand, string response,
bool ignoreErrors) throw(GsmException)
{
string s;
vector<string> result;
// send AT command
putLine("AT" + atCommand);
// and gobble up CR/LF (and possibly echoed characters if echo can't be
// switched off)
do
{
s = normalize(getLine());
}
while (s.length() == 0 || s == "AT" + atCommand);
// handle errors
if (matchResponse(s, "+CME ERROR:") || matchResponse(s, "+CMS ERROR:"))
if (ignoreErrors)
return result;
else
throwCmeException(s);
if (matchResponse(s, "ERROR"))
if (ignoreErrors)
return result;
else
throw GsmException(_("ME/TA error '<unspecified>' (code not known)"),
ChatError, -1);
// push all lines that are not empty
// cut response prefix if it is there
// stop when an OK line is read
while (1)
{
if (s == "OK")
return result;
// some TA/TEs don't prefix their response with the response string
// as proscribed by the standard: just handle either case
if (response.length() != 0 && matchResponse(s, response))
result.push_back(cutResponse(s, response));
else
result.push_back(s);
// get next line
do
{
s = normalize(getLine());
}
while (s.length() == 0);
reportProgress();
}
// never reached
assert(0);
return result;
}
string GsmAt::normalize(string s)
{
size_t start = 0, end = s.length();
bool changed = true;
while (start < end && changed)
{
changed = false;
if (isspace(s[start]))
{
++start;
changed = true;
}
else
if (isspace(s[end - 1]))
{
--end;
changed = true;
}
}
return s.substr(start, end - start);
}
string GsmAt::sendPdu(string atCommand, string response, string pdu,
bool acceptEmptyResponse) throw(GsmException)
{
string s;
bool errorCondition;
bool retry = false;
int tries = 5; // How many error conditions do we accept
int c;
do
{
errorCondition = false;
putLine("AT" + atCommand);
do
{
retry = false;
try
{
do
{
// read first of two bytes "> "
c = readByte();
}
// there have been reports that some phones give spurious CRs
// LF separates CDSI messages if there are more than one
while (c == CR || c == LF);
}
catch (GsmException &e)
{
c = '-';
errorCondition = true; // TA does not expect PDU anymore, retry
}
if (c == '+' || c == 'E') // error or unsolicited result code
{
_port->putBack(c);
s = normalize(getLine());
errorCondition = (s != "");
retry = ! errorCondition;
}
}
while (retry);
}
while (errorCondition && tries--);
if (! errorCondition)
{
if (c != '>' || readByte() != ' ')
throw GsmException(_("unexpected character in PDU handshake"),
ChatError);
putLine(pdu + "\032", false); // write pdu followed by CTRL-Z
// some phones (Ericcson T68, T39) send spurious zero characters after
// accepting the PDU
c = readByte();
if (c != 0)
_port->putBack(c);
// loop while empty lines (maybe with a zero, Ericsson T39m)
// or an echo of the pdu (with or without CTRL-Z)
// is read
do
{
s = normalize(getLine());
}
while (s.length() == 0 || s == pdu || s == (pdu + "\032") ||
(s.length() == 1 && s[0] == 0));
}
// handle errors
if (matchResponse(s, "+CME ERROR:") || matchResponse(s, "+CMS ERROR:"))
throwCmeException(s);
if (matchResponse(s, "ERROR"))
throw GsmException(_("ME/TA error '<unspecified>' (code not known)"),
ChatError, -1);
// return if response is "OK" and caller says this is OK
if (acceptEmptyResponse && s == "OK")
return "";
if (matchResponse(s, response))
{
string result = cutResponse(s, response);
// get the final "OK"
do
{
s = normalize(getLine());
}
while (s.length() == 0);
if (s == "OK") return result;
// else fall through to error
}
throw GsmException(
stringPrintf(_("unexpected response '%s' when sending 'AT%s'"),
s.c_str(), atCommand.c_str()),
ChatError);
}
string GsmAt::getLine() throw(GsmException)
{
if (_eventHandler == (GsmEvent*)NULL)
return _port->getLine();
else
{
bool eventOccurred;
string result;
do
{
eventOccurred = false;
result = _port->getLine();
string s = normalize(result);
if (matchResponse(s, "+CMT:") ||
matchResponse(s, "+CBM:") ||
matchResponse(s, "+CDS:") ||
matchResponse(s, "+CMTI:") ||
matchResponse(s, "+CBMI:") ||
matchResponse(s, "+CDSI:") ||
matchResponse(s, "RING") ||
matchResponse(s, "NO CARRIER") ||
// hack: the +CLIP? sequence returns +CLIP: n,m
// which is NOT an unsolicited result code
(matchResponse(s, "+CLIP:") && s.length() > 10))
{
_eventHandler->dispatch(s, *this);
eventOccurred = true;
}
}
while (eventOccurred);
return result;
}
}
void GsmAt::putLine(string line,
bool carriageReturn) throw(GsmException)
{
_port->putLine(line, carriageReturn);
// remove empty echo line
if (carriageReturn)
getLine();
}
bool GsmAt::wait(GsmTime timeout) throw(GsmException)
{
return _port->wait(timeout);
}
int GsmAt::readByte() throw(GsmException)
{
return _port->readByte();
}
GsmEvent *GsmAt::setEventHandler(GsmEvent *newHandler)
{
GsmEvent *result = _eventHandler;
_eventHandler = newHandler;
return result;
}

View File

@ -0,0 +1,104 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_at.h
// *
// * Purpose: Utility classes for AT command sequence handling
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 3.5.1999
// *************************************************************************
#ifndef GSM_AT_H
#define GSM_AT_H
#include <gsmlib/gsm_port.h>
#include <string>
#include <vector>
using namespace std;
namespace gsmlib
{
// forward declarations
class GsmEvent;
class MeTa;
// utiliy class to handle AT sequences
class GsmAt : public RefBase
{
protected:
MeTa &_meTa;
Ref<Port> _port;
GsmEvent *_eventHandler;
// return true if response matches
bool matchResponse(string answer, string responseToMatch);
// cut response and normalize
string cutResponse(string answer, string responseToMatch);
// parse CME error contained in string and throw MeTaException
void throwCmeException(string s) throw(GsmException);
public:
GsmAt(MeTa &meTa);
// return MeTa object for this AT object
MeTa &getMeTa() {return _meTa;}
// the following sequence functions recognize asynchronous messages
// from the TA and return the appropriate event
// send AT command, wait for response response, returns response line
// without response match
// if response == "" only an OK is expected
// white space at beginning or end are removed
// +CME ERROR or ERROR raises exception (if ignoreErrors == true)
// additionally, accept empty responses (just an OK)
// if acceptEmptyResponse == true
// in this case an empty string is returned
string chat(string atCommand = "",
string response = "",
bool ignoreErrors = false,
bool acceptEmptyResponse = false) throw(GsmException);
// same as chat() above but also get pdu if expectPdu == true
string chat(string atCommand,
string response,
string &pdu,
bool ignoreErrors = false,
bool expectPdu = true,
bool acceptEmptyResponse = false) throw(GsmException);
// same as above, but expect several response lines
vector<string> chatv(string atCommand = "",
string response = "",
bool ignoreErrors = false)
throw(GsmException);
// removes whitespace at beginning and end of string
string normalize(string s);
// send pdu (wait for <CR><LF><greater_than><space> and send <CTRL-Z>
// at the end
// return text after response
string sendPdu(string atCommand, string response, string pdu,
bool acceptEmptyResponse = false) throw(GsmException);
// functions from class Port
string getLine() throw(GsmException);
void putLine(string line,
bool carriageReturn = true) throw(GsmException);
bool wait(GsmTime timeout) throw(GsmException);
int readByte() throw(GsmException);
// set event handler class, return old one
GsmEvent *setEventHandler(GsmEvent *newHandler);
};
};
#endif // GSM_AT_H

View File

@ -0,0 +1,176 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_cb.cc
// *
// * Purpose: Cell Broadcast Message Implementation
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 4.8.2001
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_sysdep.h>
#include <gsmlib/gsm_cb.h>
#include <gsmlib/gsm_nls.h>
#include <strstream>
using namespace std;
using namespace gsmlib;
// local constants
static const string dashes =
"---------------------------------------------------------------------------";
// CBDataCodingScheme members
CBDataCodingScheme::CBDataCodingScheme(unsigned char dcs) : _dcs(dcs)
{
if ((_dcs & 0xf0) <= 0x30) // bits 7..4 in the range 0000..0011
if ((_dcs & 0x30) == 0)
_language = (Language)_dcs;
else
_language = Unknown;
}
string CBDataCodingScheme::toString() const
{
string result;
if (compressed()) result += _("compressed ");
switch (getLanguage())
{
case German:
result += _("German");
break;
case English:
result += _("English");
break;
case Italian:
result += _("Italian");
break;
case French:
result += _("French");
break;
case Spanish:
result += _("Spanish");
break;
case Dutch:
result += _("Dutch");
break;
case Swedish:
result += _("Swedish");
break;
case Danish:
result += _("Danish");
break;
case Portuguese:
result += _("Portuguese");
break;
case Finnish:
result += _("Finnish");
break;
case Norwegian:
result += _("Norwegian");
break;
case Greek:
result += _("Greek");
break;
case Turkish:
result += _("Turkish");
break;
}
result += " ";
switch (getAlphabet())
{
case DCS_DEFAULT_ALPHABET:
result += _("default alphabet");
break;
case DCS_EIGHT_BIT_ALPHABET:
result += _("8-bit alphabet");
break;
case DCS_SIXTEEN_BIT_ALPHABET:
result += _("16-bit alphabet");
break;
case DCS_RESERVED_ALPHABET:
result += _("reserved alphabet");
break;
}
return result;
}
// CBMessage members
CBMessage::CBMessage(string pdu) throw(GsmException)
{
SMSDecoder d(pdu);
_messageCode = d.getInteger(6) << 4;
_geographicalScope = (GeographicalScope)d.get2Bits();
_updateNumber = d.getInteger(4);
_messageCode |= d.getInteger(4);
_messageIdentifier = d.getInteger(8) << 8;
_messageIdentifier |= d.getInteger(8);
_dataCodingScheme = CBDataCodingScheme(d.getOctet());
_totalPageNumber = d.getInteger(4);
_currentPageNumber = d.getInteger(4);
// the values 82 and 93 come from ETSI GSM 03.41, section 9.3
d.markSeptet();
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
{
_data = d.getString(93);
_data = gsmToLatin1(_data);
}
else
{
unsigned char *s =
(unsigned char*)alloca(sizeof(unsigned char) * 82);
d.getOctets(s, 82);
_data.assign((char*)s, (unsigned int)82);
}
}
string CBMessage::toString() const
{
ostrstream os;
os << dashes << endl
<< _("Message type: CB") << endl
<< _("Geographical scope: ");
switch (_geographicalScope)
{
case CellWide:
os << "Cell wide" << endl;
break;
case PLMNWide:
os << "PLMN wide" << endl;
break;
case LocationAreaWide:
os << "Location area wide" << endl;
break;
case CellWide2:
os << "Cell wide (2)" << endl;
break;
}
// remove trailing \r characters for output
string data = _data;
string::iterator i;
for (i = data.end(); i > data.begin() && *(i - 1) == '\r';
--i);
data.erase(i, data.end());
os << _("Message Code: ") << _messageCode << endl
<< _("Update Number: ") << _updateNumber << endl
<< _("Message Identifer: ") << _messageIdentifier << endl
<< _("Data coding scheme: ") << _dataCodingScheme.toString() << endl
<< _("Total page number: ") << _totalPageNumber << endl
<< _("Current page number: ") << _currentPageNumber << endl
<< _("Data: '") << data << "'" << endl
<< dashes << endl << endl << ends;
char *ss = os.str();
string result(ss);
delete[] ss;
return result;
}

View File

@ -0,0 +1,106 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_cb.h
// *
// * Purpose: Cell Broadcast Message Implementation
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 4.8.2001
// *************************************************************************
#ifndef GSM_CB_H
#define GSM_CB_H
#include <gsmlib/gsm_sms_codec.h>
#include <gsmlib/gsm_util.h>
#include <string>
using namespace std;
namespace gsmlib
{
// representation of DataCodingScheme
// The data coding scheme is described in detail in ETSI GSM 03.38, section 5
// This class reuses the DCS_* constants from DataCodingScheme in
// gsm_sms_codec
class CBDataCodingScheme
{
public:
enum Language {German = 0, English = 1, Italian = 2, French = 3,
Spanish = 4, Dutch = 5, Swedish = 6, Danish = 7,
Portuguese = 8, Finnish = 9, Norwegian = 10, Greek = 11,
Turkish = 12, Unknown = 1000};
private:
unsigned char _dcs;
Language _language;
public:
// initialize with data coding scheme octet
CBDataCodingScheme(unsigned char dcs);
// default constructor
CBDataCodingScheme() : _dcs(DCS_DEFAULT_ALPHABET), _language(English) {}
// return language of CBM
Language getLanguage() const {return _language;}
// return compression level (if language == Unknown)
bool compressed() const {return (_dcs & DCS_COMPRESSED) == DCS_COMPRESSED;}
// return type of alphabet used
// (DCS_DEFAULT_ALPHABET, DCS_EIGHT_BIT_ALPHABET, DCS_SIXTEEN_BIT_ALPHABET,
// DCS_RESERVED_ALPHABET)
unsigned char getAlphabet() const
{return _language == Unknown ? _dcs & (3 << 2) : DCS_DEFAULT_ALPHABET;}
// create textual representation of CB data coding scheme
string toString() const;
};
// representation of Cell Broadcast message (CBM)
// The CBM format is described in detail in ETSI GSM 03.41, section 9.3
class CBMessage : public RefBase
{
public:
enum GeographicalScope {CellWide, PLMNWide, LocationAreaWide,
CellWide2};
private:
// fields parsed from the CB TPDU
GeographicalScope _geographicalScope;
int _messageCode;
int _updateNumber;
int _messageIdentifier;
CBDataCodingScheme _dataCodingScheme;
int _totalPageNumber;
int _currentPageNumber;
string _data;
public:
// constructor with given pdu
CBMessage(string pdu) throw(GsmException);
// accessor functions
GeographicalScope getGeographicalScope() const {return _geographicalScope;}
int getMessageCode() const {return _messageCode;}
int getUpdateNumber() const {return _updateNumber;}
int getMessageIdentifier() const {return _messageIdentifier;}
CBDataCodingScheme getDataCodingScheme() const {return _dataCodingScheme;}
int getTotalPageNumber() const {return _totalPageNumber;}
int getCurrentPageNumber() const {return _currentPageNumber;}
string getData() const {return _data;}
// create textual representation of CBM
string toString() const;
};
// some useful typdefs
typedef Ref<CBMessage> CBMessageRef;
};
#endif // GSM_CB_H

View File

@ -0,0 +1,424 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_error.cc
// *
// * Purpose: Error codes and error handling functions
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 11.5.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_nls.h>
#include <gsmlib/gsm_error.h>
#include <gsmlib/gsm_util.h>
#include <strstream>
using namespace std;
using namespace gsmlib;
string gsmlib::getMEErrorText(const int errorCode) throw(GsmException)
{
switch (errorCode)
{
case ME_PHONE_FAILURE:
return _("phone failure");
break;
case ME_NO_CONNECTION_TO_PHONE:
return _("no connection to phone");
break;
case ME_PHONE_ADAPTOR_LINK_RESERVED:
return _("phone adaptor link reserved");
break;
case ME_OPERATION_NOT_ALLOWED:
return _("operation not allowed");
break;
case ME_OPERATION_NOT_SUPPORTED:
return _("operation not supported");
break;
case ME_PH_SIM_PIN_REQUIRED:
return _("ph SIM PIN required");
break;
case ME_SIM_NOT_INSERTED:
return _("SIM not inserted");
break;
case ME_SIM_PIN_REQUIRED:
return _("SIM PIN required");
break;
case ME_SIM_PUK_REQUIRED:
return _("SIM PUK required");
break;
case ME_SIM_FAILURE:
return _("SIM failure");
break;
case ME_SIM_BUSY:
return _("SIM busy");
break;
case ME_SIM_WRONG:
return _("SIM wrong");
break;
case ME_INCORRECT_PASSWORD:
return _("incorrect password");
break;
case ME_SIM_PIN2_REQUIRED:
return _("SIM PIN2 required");
break;
case ME_SIM_PUK2_REQUIRED:
return _("SIM PUK2 required");
break;
case ME_MEMORY_FULL:
return _("memory full");
break;
case ME_INVALID_INDEX:
return _("invalid index");
break;
case ME_NOT_FOUND:
return _("not found");
break;
case ME_MEMORY_FAILURE:
return _("memory failure");
break;
case ME_TEXT_STRING_TOO_LONG:
return _("text string too long");
break;
case ME_INVALID_CHARACTERS_IN_TEXT_STRING:
return _("invalid characters in text string");
break;
case ME_DIAL_STRING_TOO_LONG:
return _("dial string too long");
break;
case ME_INVALID_CHARACTERS_IN_DIAL_STRING:
return _("invalid characters in dial string");
break;
case ME_NO_NETWORK_SERVICE:
return _("no network service");
break;
case ME_NETWORK_TIMEOUT:
return _("network timeout");
break;
case ME_UNKNOWN:
return _("unknown");
break;
default:
throw GsmException(stringPrintf(_("invalid ME error %d"), errorCode),
OtherError);
}
}
string gsmlib::getSMSErrorText(const int errorCode) throw(GsmException)
{
switch (errorCode)
{
case SMS_UNASSIGNED_OR_UNALLOCATED_NUMBER:
return _("Unassigned (unallocated) number");
break;
case SMS_OPERATOR_DETERMINED_BARRING:
return _("Operator determined barring");
break;
case SMS_CALL_BARRED:
return _("Call barred");
break;
case SMS_NETWORK_FAILURE:
return _("Network failure");
break;
case SMS_SHORT_MESSAGE_TRANSFER_REJECTED:
return _("Short message transfer rejected");
break;
case SMS_CONGESTION:
case SMS_CONGESTION2:
return _("Congestion");
break;
case SMS_DESTINATION_OUT_OF_SERVICE:
return _("Destination out of service");
break;
case SMS_UNIDENTIFIED_SUBSCRIBER:
return _("Unidentified subscriber");
break;
case SMS_FACILITY_REJECTED:
return _("Facility rejected");
break;
case SMS_UNKNOWN_SUBSCRIBER:
return _("Unknown subscriber");
break;
case SMS_NETWORK_OUT_OF_ORDER:
return _("Network out of order");
break;
case SMS_TEMPORARY_FAILURE:
return _("Temporary failure");
break;
case SMS_RESOURCES_UNAVAILABLE_UNSPECIFIED:
return _("Resources unavailable, unspecified");
break;
case SMS_REQUESTED_FACILITY_NOT_SUBSCRIBED:
return _("Requested facility not subscribed");
break;
case SMS_REQUESTED_FACILITY_NOT_IMPLEMENTED:
return _("Requested facility not implemented");
break;
case SMS_INVALID_TRANSACTION_IDENTIFIER:
return _("Invalid Transaction Identifier");
break;
case SMS_SEMANTICALLY_INCORRECT_MESSAGE:
return _("Semantically incorrect message");
break;
case SMS_INVALID_MANDATORY_INFORMATION:
return _("Invalid mandatory information");
break;
case SMS_MESSAGE_TYPE_NONEXISTENT_OR_NOT_IMPLEMENTED:
return _("Message type non-existent or not implemented");
break;
case SMS_MESSAGE_NOT_COMPATIBLE_WITH_SHORT_MESSAGE_PROTOCOL_STATE:
return _("Message not compatible with short message protocol state");
break;
case SMS_INFORMATION_ELEMENT_NONEXISTENT_OR_NOT_IMPLEMENTED:
return _("Information element non-existent or not implemented");
break;
case SMS_UNSPECIFIED_PROTOCOL_ERROR:
return _("Protocol error, unspecified");
break;
case SMS_UNSPECIFIED_INTERWORKING_ERROR:
return _("Interworking, unspecified");
break;
case SMS_TELEMATIC_INTERWORKING_NOT_SUPPORTED:
return _("Telematic interworking not supported");
break;
case SMS_SHORT_MESSAGE_TYPE_0_NOT_SUPPORTED:
return _("Short message Type 0 not supported");
break;
case SMS_CANNOT_REPLACE_SHORT_MESSAGE:
return _("Cannot replace short message");
break;
case SMS_UNSPECIFIED_TP_PID_ERROR:
return _("Unspecified TP-PID error");
break;
case SMS_DATA_CODING_SCHEME_NOT_SUPPORTED:
return _("Data coding scheme (alphabet) not supported");
break;
case SMS_MESSAGE_CLASS_NOT_SUPPORTED:
return _("Message class not supported");
break;
case SMS_UNSPECIFIEC_TP_DCS_ERROR:
return _("Unspecifiec TP-DCS error");
break;
case SMS_COMMAND_CANNOT_BE_ACTIONED:
return _("Command cannot be actioned");
break;
case SMS_COMMAND_UNSUPPORTED:
return _("Command unsupported");
break;
case SMS_UNSPECIFIED_TP_COMMAND_ERROR:
return _("Unspecified TP-Command error");
break;
case SMS_TPDU_NOT_SUPPORTED:
return _("TPDU not supported");
break;
case SMS_SC_BUSY:
return _("SC busy");
break;
case SMS_NO_SC_SUBSCRIPTION:
return _("No SC subscription");
break;
case SMS_SC_SYSTEM_FAILURE:
return _("SC system failure");
break;
case SMS_INVALID_SME_ADDRESS:
return _("Invalid SME address");
break;
case SMS_DESTINATION_SME_BARRED:
return _("Destination SME barred");
break;
case SMS_SM_REJECTED_DUPLICATED_SM:
return _("SM Rejected-Duplicated SM");
break;
case SMS_SIM_SMS_STORAGE_FULL:
return _("SIM SMS storage full");
break;
case SMS_NO_SMS_STORAGE_CAPABILITY_IN_SIM:
return _("No SMS storage capability in SIM");
break;
case SMS_ERROR_IN_MS:
return _("Error in MS");
break;
case SMS_MEMORY_CAPACITY_EXCEED:
return _("Memory Capacity Exceed");
break;
case SMS_UNSPECIFIED_ERROR_CAUSE:
return _("Unspecified error cause");
break;
case SMS_ME_FAILURE:
return _("ME failure");
break;
case SMS_SMS_SERVICE_OF_ME_RESERVED:
return _("SMS service of ME reserved");
break;
case SMS_OPERATION_NOT_ALLOWED:
return _("operation not allowed");
break;
case SMS_OPERATION_NOT_SUPPORTED:
return _("operation not supported");
break;
case SMS_INVALID_PDU_MODE_PARAMETER:
return _("invalid PDU mode parameter");
break;
case SMS_INVALID_TEXT_MODE_PARAMETER:
return _("invalid text mode parameter");
break;
case SMS_SIM_NOT_INSERTED:
return _("SIM not inserted");
break;
case SMS_SIM_PIN_REQUIRED:
return _("SIM PIN required");
break;
case SMS_PH_SIM_PIN_REQUIRED:
return _("PH-SIM PIN required");
break;
case SMS_SIM_FAILURE:
return _("SIM failure");
break;
case SMS_SIM_BUSY:
return _("SIM busy");
break;
case SMS_SIM_WRONG:
return _("SIM wrong");
break;
case SMS_SIM_PUK_REQUIRED:
return _("SIM PUK required");
break;
case SMS_SIM_PIN2_REQUIRED:
return _("SIM PIN2 required");
break;
case SMS_SIM_PUK2_REQUIRED:
return _("SIM PUK2 required");
break;
case SMS_MEMORY_FAILURE:
return _("memory failure");
break;
case SMS_INVALID_MEMORY_INDEX:
return _("invalid memory index");
break;
case SMS_MEMORY_FULL:
return _("memory full");
break;
case SMS_SMSC_ADDRESS_UNKNOWN:
return _("SMSC address unknown");
break;
case SMS_NO_NETWORK_SERVICE:
return _("no network service");
break;
case SMS_NETWORK_TIMEOUT:
return _("network timeout");
break;
case SMS_NO_CNMA_ACKNOWLEDGEMENT_EXPECTED:
return _("no +CNMA acknowledgement expected");
break;
case SMS_UNKNOWN_ERROR:
return _("unknown error");
break;
default:
throw GsmException(stringPrintf(_("invalid SMS error %d"), errorCode),
OtherError);
}
}
string gsmlib::getSMSStatusString(unsigned char status)
{
string result;
if (status < SMS_STATUS_TEMPORARY_BIT)
{
switch (status)
{
case SMS_STATUS_RECEIVED:
result = _("Short message received by the SME");
break;
case SMS_STATUS_FORWARDED:
result = _("Short message forwarded by the SC to the SME but the SC "
"is unable to confirm delivery");
break;
case SMS_STATUS_SM_REPLACES:
result = _("Short message replaced by the SC");
break;
default:
result = _("reserved");
break;
}
return result;
}
else if (status & SMS_STATUS_TEMPORARY_BIT)
{
switch (status & ~(SMS_STATUS_TEMPORARY_BIT | SMS_STATUS_PERMANENT_BIT))
{
case SMS_STATUS_CONGESTION:
result = _("Congestion");
break;
case SMS_STATUS_SME_BUSY:
result = _("SME busy");
break;
case SMS_STATUS_NO_RESPONSE_FROM_SME:
result = _("No response from SME");
break;
case SMS_STATUS_SERVICE_REJECTED:
result = _("Service rejected");
break;
case SMS_STATUS_QUALITY_OF_SERVICE_UNAVAILABLE:
result = _("Quality of service not available");
break;
case SMS_STATUS_ERROR_IN_SME:
result = _("Error in SME");
break;
default:
result = _("reserved");
break;
}
if (status & SMS_STATUS_PERMANENT_BIT)
return result + _(" (Temporary error, SC is not making any "
"more transfer attempts)");
else
return result + _(" (Temporary error, SC still trying to "
"transfer SM)");
}
else
{
switch (status & ~SMS_STATUS_PERMANENT_BIT)
{
case SMS_STATUS_REMOTE_PROCECURE_ERROR:
result = _("Remote Procedure Error");
break;
case SMS_STATUS_INCOMPATIBLE_DESTINATION:
result = _("Incompatible destination");
break;
case SMS_STATUS_CONNECTION_REJECTED_BY_SME:
result = _("Connection rejected by SME");
break;
case SMS_STATUS_NOT_OBTAINABLE:
result = _("Not obtainable");
break;
case SMS_STATUS_QUALITY_OF_SERVICE_UNAVAILABLE:
result = _("Quality of service not available");
break;
case SMS_STATUS_NO_INTERWORKING_AVAILABLE:
result = _("No interworking available");
break;
case SMS_STATUS_SM_VALIDITY_PERDIOD_EXPIRED:
result = _("SM validity period expired");
break;
case SMS_STATUS_SM_DELETED_BY_ORIGINATING_SME:
result = _("SM deleted by originating SME");
break;
case SMS_STATUS_SM_DELETED_BY_ADMINISTRATION:
result = _("SM deleted by SC administration");
break;
case SMS_STATUS_SM_DOES_NOT_EXIST:
result = _("SM does not exit");
break;
default:
result = _("reserved");
break;
}
return result + _(" (Permanent Error, SC is not making any "
"more transfer attempts)");
}
}

View File

@ -0,0 +1,209 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_error.h
// *
// * Purpose: Error codes and error handling functions
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 4.5.1999
// *************************************************************************
#ifndef GSM_ERROR_H
#define GSM_ERROR_H
#include <string>
#include <stdexcept>
using namespace std;
namespace gsmlib
{
// different classes of GSM errors
enum GsmErrorClass{OSError, // error caused by OS call (eg. file handling)
ParserError, // error when parsing AT response
ChatError, // error in chat sequence (ME/TA/SMS error)
ParameterError, // gsmlib function called with bad params
NotImplementedError, // feature not implemented
MeTaCapabilityError, // non-existent capability in ME
SMSFormatError, // SMS format error
InterruptException, // gsmlib was interrupted()
OtherError}; // all other errors
// all gsmlib exceptions
class GsmException : public runtime_error
{
private:
GsmErrorClass _errorClass;
int _errorCode;
public:
GsmException(string errorText, GsmErrorClass errorClass) :
runtime_error(errorText), _errorClass(errorClass), _errorCode(-1) {}
GsmException(string errorText, GsmErrorClass errorClass, int errorCode) :
runtime_error(errorText), _errorClass(errorClass),
_errorCode(errorCode) {}
int getErrorCode() const {return _errorCode;}
GsmErrorClass getErrorClass() const {return _errorClass;}
};
// error codes returned by TA/ME (+CMEE)
const int ME_PHONE_FAILURE = 0;
const int ME_NO_CONNECTION_TO_PHONE = 1;
const int ME_PHONE_ADAPTOR_LINK_RESERVED = 2;
const int ME_OPERATION_NOT_ALLOWED = 3;
const int ME_OPERATION_NOT_SUPPORTED = 4;
const int ME_PH_SIM_PIN_REQUIRED = 5;
const int ME_SIM_NOT_INSERTED = 10;
const int ME_SIM_PIN_REQUIRED = 11;
const int ME_SIM_PUK_REQUIRED = 12;
const int ME_SIM_FAILURE = 13;
const int ME_SIM_BUSY = 14;
const int ME_SIM_WRONG = 15;
const int ME_INCORRECT_PASSWORD = 16;
const int ME_SIM_PIN2_REQUIRED = 17;
const int ME_SIM_PUK2_REQUIRED = 18;
const int ME_MEMORY_FULL = 20;
const int ME_INVALID_INDEX = 21;
const int ME_NOT_FOUND = 22;
const int ME_MEMORY_FAILURE = 23;
const int ME_TEXT_STRING_TOO_LONG = 24;
const int ME_INVALID_CHARACTERS_IN_TEXT_STRING = 25;
const int ME_DIAL_STRING_TOO_LONG = 26;
const int ME_INVALID_CHARACTERS_IN_DIAL_STRING = 27;
const int ME_NO_NETWORK_SERVICE = 30;
const int ME_NETWORK_TIMEOUT = 31;
const int ME_UNKNOWN = 100;
// return descriptive text for the given error code
// the text is already translated
extern string getMEErrorText(const int errorCode) throw(GsmException);
// SMS error codes
// error codes from ETSI GSM 04.11, Annex E
const int SMS_UNASSIGNED_OR_UNALLOCATED_NUMBER = 1;
const int SMS_OPERATOR_DETERMINED_BARRING = 8;
const int SMS_CALL_BARRED = 10;
const int SMS_NETWORK_FAILURE = 17;
const int SMS_SHORT_MESSAGE_TRANSFER_REJECTED = 21;
const int SMS_CONGESTION = 22;
const int SMS_DESTINATION_OUT_OF_SERVICE = 27;
const int SMS_UNIDENTIFIED_SUBSCRIBER = 28;
const int SMS_FACILITY_REJECTED = 29;
const int SMS_UNKNOWN_SUBSCRIBER = 30;
const int SMS_NETWORK_OUT_OF_ORDER = 38;
const int SMS_TEMPORARY_FAILURE = 41;
const int SMS_CONGESTION2 = 42;
const int SMS_RESOURCES_UNAVAILABLE_UNSPECIFIED = 47;
const int SMS_REQUESTED_FACILITY_NOT_SUBSCRIBED = 50;
const int SMS_REQUESTED_FACILITY_NOT_IMPLEMENTED = 69;
const int SMS_INVALID_TRANSACTION_IDENTIFIER = 81;
const int SMS_SEMANTICALLY_INCORRECT_MESSAGE = 95;
const int SMS_INVALID_MANDATORY_INFORMATION = 96;
const int SMS_MESSAGE_TYPE_NONEXISTENT_OR_NOT_IMPLEMENTED = 97;
const int SMS_MESSAGE_NOT_COMPATIBLE_WITH_SHORT_MESSAGE_PROTOCOL_STATE = 98;
const int SMS_INFORMATION_ELEMENT_NONEXISTENT_OR_NOT_IMPLEMENTED = 99;
const int SMS_UNSPECIFIED_PROTOCOL_ERROR = 111;
const int SMS_UNSPECIFIED_INTERWORKING_ERROR = 127;
// error codes from ETSI GSM 03.40, section 9.2.3.22
const int SMS_TELEMATIC_INTERWORKING_NOT_SUPPORTED = 0x80;
const int SMS_SHORT_MESSAGE_TYPE_0_NOT_SUPPORTED = 0x81;
const int SMS_CANNOT_REPLACE_SHORT_MESSAGE = 0x82;
const int SMS_UNSPECIFIED_TP_PID_ERROR = 0x8f;
const int SMS_DATA_CODING_SCHEME_NOT_SUPPORTED = 0x90;
const int SMS_MESSAGE_CLASS_NOT_SUPPORTED = 0x91;
const int SMS_UNSPECIFIEC_TP_DCS_ERROR = 0x9f;
const int SMS_COMMAND_CANNOT_BE_ACTIONED = 0xa0;
const int SMS_COMMAND_UNSUPPORTED = 0xa1;
const int SMS_UNSPECIFIED_TP_COMMAND_ERROR = 0xaf;
const int SMS_TPDU_NOT_SUPPORTED = 0xb0;
const int SMS_SC_BUSY = 0xc0;
const int SMS_NO_SC_SUBSCRIPTION = 0xc1;
const int SMS_SC_SYSTEM_FAILURE = 0xc2;
const int SMS_INVALID_SME_ADDRESS = 0xc3;
const int SMS_DESTINATION_SME_BARRED = 0xc4;
const int SMS_SM_REJECTED_DUPLICATED_SM = 0xc5;
const int SMS_SIM_SMS_STORAGE_FULL = 0xd0;
const int SMS_NO_SMS_STORAGE_CAPABILITY_IN_SIM = 0xd1;
const int SMS_ERROR_IN_MS = 0xd2;
const int SMS_MEMORY_CAPACITY_EXCEED = 0xd3;
const int SMS_UNSPECIFIED_ERROR_CAUSE = 0xff;
// error codes from ETSI GSM 07.05, section 3.2.5
const int SMS_ME_FAILURE = 300;
const int SMS_SMS_SERVICE_OF_ME_RESERVED = 301;
const int SMS_OPERATION_NOT_ALLOWED = 302;
const int SMS_OPERATION_NOT_SUPPORTED = 303;
const int SMS_INVALID_PDU_MODE_PARAMETER = 304;
const int SMS_INVALID_TEXT_MODE_PARAMETER = 305;
const int SMS_SIM_NOT_INSERTED = 310;
const int SMS_SIM_PIN_REQUIRED = 311;
const int SMS_PH_SIM_PIN_REQUIRED = 312;
const int SMS_SIM_FAILURE = 313;
const int SMS_SIM_BUSY = 314;
const int SMS_SIM_WRONG = 315;
const int SMS_SIM_PUK_REQUIRED = 316;
const int SMS_SIM_PIN2_REQUIRED = 317;
const int SMS_SIM_PUK2_REQUIRED = 318;
const int SMS_MEMORY_FAILURE = 320;
const int SMS_INVALID_MEMORY_INDEX = 321;
const int SMS_MEMORY_FULL = 322;
const int SMS_SMSC_ADDRESS_UNKNOWN = 330;
const int SMS_NO_NETWORK_SERVICE = 331;
const int SMS_NETWORK_TIMEOUT = 332;
const int SMS_NO_CNMA_ACKNOWLEDGEMENT_EXPECTED = 340;
const int SMS_UNKNOWN_ERROR = 500;
// return descriptive text for the given error code
// the text is already translated
extern string getSMSErrorText(const int errorCode) throw(GsmException);
// SMS status handling
// success codes
const int SMS_STATUS_RECEIVED = 0;
const int SMS_STATUS_FORWARDED = 1;
const int SMS_STATUS_SM_REPLACES = 2;
// if this bit is set, the error is only temporary and
// the SC is still trying to transfer the SM
const int SMS_STATUS_TEMPORARY_BIT = 32;
// if this bit is set, the error is only temporary and
// the SC is still trying to transfer the SM
const int SMS_STATUS_PERMANENT_BIT = 64;
// both bits may be set at once
// temporary errors (both bits may be set)
const int SMS_STATUS_CONGESTION = 0;
const int SMS_STATUS_SME_BUSY = 1;
const int SMS_STATUS_NO_RESPONSE_FROM_SME = 2;
const int SMS_STATUS_SERVICE_REJECTED = 3;
const int SMS_STATUS_QUALITY_OF_SERVICE_UNAVAILABLE = 4;
const int SMS_STATUS_ERROR_IN_SME = 5;
// permanent errors (SMS_STATUS_PERMANENT_BIT is set)
const int SMS_STATUS_REMOTE_PROCECURE_ERROR = 0;
const int SMS_STATUS_INCOMPATIBLE_DESTINATION = 1;
const int SMS_STATUS_CONNECTION_REJECTED_BY_SME = 2;
const int SMS_STATUS_NOT_OBTAINABLE = 3;
// const int SMS_STATUS_QUALITY_OF_SERVICE_UNAVAILABLE = 4;
const int SMS_STATUS_NO_INTERWORKING_AVAILABLE = 5;
const int SMS_STATUS_SM_VALIDITY_PERDIOD_EXPIRED = 6;
const int SMS_STATUS_SM_DELETED_BY_ORIGINATING_SME = 7;
const int SMS_STATUS_SM_DELETED_BY_ADMINISTRATION = 8;
const int SMS_STATUS_SM_DOES_NOT_EXIST = 9;
// return text for SMS status code
// the text is already translated
string getSMSStatusString(unsigned char status);
};
#endif // GSM_ERROR_H

View File

@ -0,0 +1,174 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_event.cc
// *
// * Purpose: Event handler interface
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 7.6.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_nls.h>
#include <gsmlib/gsm_event.h>
#include <gsmlib/gsm_parser.h>
#include <gsmlib/gsm_at.h>
#include <gsmlib/gsm_me_ta.h>
using namespace std;
using namespace gsmlib;
// GsmEvent members
void GsmEvent::dispatch(string s, GsmAt &at) throw(GsmException)
{
SMSMessageType messageType;
bool indication = false;
if (s.substr(0, 5) == "+CMT:")
messageType = NormalSMS;
else if (s.substr(0, 5) == "+CBM:")
messageType = CellBroadcastSMS;
else if (s.substr(0, 5) == "+CDS:")
{
// workaround for phones that report CDS when they actually mean CDSI
indication = at.getMeTa().getCapabilities()._CDSmeansCDSI;
messageType = StatusReportSMS;
}
else if (s.substr(0, 6) == "+CMTI:")
{
indication = true;
messageType = NormalSMS;
}
else if (s.substr(0, 6) == "+CBMI:")
{
indication = true;
messageType = CellBroadcastSMS;
}
else if (s.substr(0, 6) == "+CDSI:")
{
indication = true;
messageType = StatusReportSMS;
}
else if (s.substr(0, 4) == "RING")
{
ringIndication();
return;
}
// handling NO CARRIER
else if (s.substr(0, 10) == "NO CARRIER")
{
noAnswer();
return;
}
else if (s.substr(0, 6) == "+CLIP:")
{
// <number>,<type>[,<subaddr>,<satype>[,<alpha>]]
s = s.substr(6);
Parser p(s);
string num = p.parseString();
if (p.parseComma(true))
{
unsigned int numberFormat;
if ((numberFormat = p.parseInt()) == InternationalNumberFormat)
num = "+" + num;
else if (numberFormat != UnknownNumberFormat)
throw GsmException(stringPrintf(_("unexpected number format %d"),
numberFormat), OtherError);
}
string subAddr;
string alpha;
if (p.parseComma(true))
{
subAddr = p.parseString(true);
p.parseComma();
p.parseInt(true); // FIXME subaddr type ignored
if (p.parseComma(true))
alpha = p.parseString(true);
}
// call the event handler
callerLineID(num, subAddr, alpha);
return;
}
else
throw GsmException(stringPrintf(_("unexpected unsolicited event '%s'"),
s.c_str()), OtherError);
if (indication)
{
// handle SMS storage indication
s = s.substr(6);
Parser p(s);
string storeName = p.parseString();
p.parseComma();
unsigned int index = p.parseInt();
SMSReceptionIndication(storeName, index - 1, messageType);
}
else
if (messageType == CellBroadcastSMS)
{
// handle CB message
string pdu = at.getLine();
CBMessageRef cb = new CBMessage(pdu);
// call the event handler
CBReception(cb);
}
else
{
// handle SMS
string pdu = at.getLine();
// add missing service centre address if required by ME
if (! at.getMeTa().getCapabilities()._hasSMSSCAprefix)
pdu = "00" + pdu;
SMSMessageRef sms = SMSMessage::decode(pdu);
// send acknowledgement if necessary
if (at.getMeTa().getCapabilities()._sendAck)
at.chat("+CNMA");
// call the event handler
SMSReception(sms, messageType);
}
}
void GsmEvent::callerLineID(string number, string subAddr, string alpha)
{
// ignore event
}
void GsmEvent::SMSReception(SMSMessageRef newMessage,
SMSMessageType messageType)
{
// ignore event
}
void GsmEvent::CBReception(CBMessageRef newMessage)
{
// ignore event
}
void GsmEvent::SMSReceptionIndication(string storeName, unsigned int index,
SMSMessageType messageType)
{
// ignore event
}
void GsmEvent::ringIndication()
{
// ignore event
}
void GsmEvent::noAnswer()
{
// ignore event
}

View File

@ -0,0 +1,68 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_event.h
// *
// * Purpose: Event handler interface
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 7.6.1999
// *************************************************************************
#ifndef GSM_EVENT_H
#define GSM_EVENT_H
#include <gsmlib/gsm_sms.h>
#include <gsmlib/gsm_cb.h>
using namespace std;
namespace gsmlib
{
// forward declarations
class GsmAt;
// event handler interface
class GsmEvent
{
private:
// dispatch CMT/CBR/CDS/CLIP etc.
void dispatch(string s, GsmAt &at) throw(GsmException);
public:
// for SMSReception, type of SMS
enum SMSMessageType {NormalSMS, CellBroadcastSMS, StatusReportSMS};
// caller line identification presentation
// only called if setCLIPEvent(true) is set
virtual void callerLineID(string number, string subAddr, string alpha);
// called if the string NO CARRIER is read
virtual void noAnswer();
// SMS reception
// only called if setSMSReceptionEvent(...true...) is set
virtual void SMSReception(SMSMessageRef newMessage,
SMSMessageType messageType);
// CB reception
// only called if setSMSReceptionEvent(...true...) is set
// storage of CBM in ME is not supported by the standard
virtual void CBReception(CBMessageRef newMessage);
// SMS reception indication (called when SMS is not delivered to TE
// but stored in ME memory)
virtual void SMSReceptionIndication(string storeName, unsigned int index,
SMSMessageType messageType);
// RING indication
virtual void ringIndication();
friend class gsmlib::GsmAt;
};
};
#endif // GSM_EVENT_H

View File

@ -0,0 +1,128 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_map_key.h
// *
// * Purpose: Common MapKey implementation for the multimaps in
// * gsm_sorted_sms_store and gsm_sorted_phonebook
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 5.11.1999
// *************************************************************************
#ifndef GSM_MAP_KEY_H
#define GSM_MAP_KEY_H
#include <gsmlib/gsm_sms_codec.h>
namespace gsmlib
{
// sort order for MapKeys
enum SortOrder {ByText = 0, ByTelephone = 1, ByIndex = 2, ByDate = 3,
ByType = 4, ByAddress = 5};
// wrapper for map key, can access Sortedtore to get sortOrder()
template <class SortedStore> class MapKey
{
public:
SortedStore &_myStore; // my store
// different type keys
Address _addressKey;
Timestamp _timeKey;
int _intKey;
string _strKey;
public:
// constructors for the different sort keys
MapKey(SortedStore &myStore, Address key) :
_myStore(myStore), _addressKey(key) {}
MapKey(SortedStore &myStore, Timestamp key) :
_myStore(myStore), _timeKey(key) {}
MapKey(SortedStore &myStore, int key) :
_myStore(myStore), _intKey(key) {}
MapKey(SortedStore &myStore, string key) :
_myStore(myStore), _strKey(key) {}
/*
friend
bool operator<
#ifndef WIN32
<>
#endif
(const MapKey<SortedStore> &x,
const MapKey<SortedStore> &y);
friend
bool operator==
#ifndef WIN32
<>
#endif
(const MapKey<SortedStore> &x,
const MapKey<SortedStore> &y);
*/
};
// compare two keys
template <class SortedStore>
extern bool operator<(const MapKey<SortedStore> &x,
const MapKey<SortedStore> &y);
template <class SortedStore>
extern bool operator==(const MapKey<SortedStore> &x,
const MapKey<SortedStore> &y);
// MapKey members
template <class SortedStore>
bool operator<(const MapKey<SortedStore> &x,
const MapKey<SortedStore> &y)
{
assert(&x._myStore == &y._myStore);
switch (x._myStore.sortOrder())
{
case ByDate:
return x._timeKey < y._timeKey;
case ByAddress:
return x._addressKey < y._addressKey;
case ByIndex:
case ByType:
return x._intKey < y._intKey;
case ByTelephone:
return Address(x._strKey) < Address(y._strKey);
case ByText:
return x._strKey < y._strKey;
default:
assert(0);
return true;
}
}
template <class SortedStore>
bool operator==(const MapKey<SortedStore> &x,
const MapKey<SortedStore> &y)
{
assert(&x._myStore == &y._myStore);
switch (x._myStore.sortOrder())
{
case ByDate:
return x._timeKey == y._timeKey;
case ByAddress:
return x._addressKey == y._addressKey;
case ByIndex:
case ByType:
return x._intKey == y._intKey;
case ByTelephone:
return Address(x._strKey) == Address(y._strKey);
case ByText:
return x._strKey == y._strKey;
default:
assert(0);
return true;
}
}
};
#endif // GSM_MAP_KEY_H

View File

@ -0,0 +1,402 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_me_ta.h
// *
// * Purpose: Mobile Equipment/Terminal Adapter and SMS functions
// * (ETSI GSM 07.07 and 07.05)
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 3.5.1999
// *************************************************************************
#ifndef GSM_ME_TA_H
#define GSM_ME_TA_H
#include <gsmlib/gsm_error.h>
#include <gsmlib/gsm_event.h>
#include <gsmlib/gsm_phonebook.h>
#include <gsmlib/gsm_sms_store.h>
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_at.h>
#include <gsmlib/gsm_sms.h>
#include <string>
#include <vector>
using namespace std;
namespace gsmlib
{
// *** phone capability description (you could also call it phone quirks)
struct Capabilities
{
bool _hasSMSSCAprefix; // SMS have service centre address prefix
int _cpmsParamCount; // number of SMS store parameters to
// CPMS command
bool _omitsColon; // omits trailing ':' in AT responses
bool _veryShortCOPSanswer; // Falcom A2-1
bool _wrongSMSStatusCode; // Motorola Timeport 260
bool _CDSmeansCDSI; // Nokia Cellular Card Phone RPE-1 GSM900
bool _sendAck; // send ack for directly routed SMS
Capabilities(); // constructor, set default behaviours
};
// *** auxiliary structs
// Static ME information (AT command sequences given in brackets)
struct MEInfo
{
string _manufacturer; // (+CGMI)
string _model; // (+CGMM)
string _revision; // (+CGMR)
string _serialNumber; // (+CGSN), IMEI
};
// modes for network operation selection
enum OPModes {AutomaticOPMode = 0, ManualOPMode = 1,
DeregisterOPMode = 2, ManualAutomaticOPMode = 4};
// status codes or network operaton selection
enum OPStatus {UnknownOPStatus = 0, AvailableOPStatus = 1,
CurrentOPStatus = 2, ForbiddenOPStatus = 3};
// network operator info
struct OPInfo
{
OPModes _mode;
OPStatus _status;
string _longName;
string _shortName;
int _numericName; // may be NOT_SET
OPInfo() : _status(UnknownOPStatus), _numericName(NOT_SET) {}
};
// facility classes
enum FacilityClass {VoiceFacility = 1, DataFacility = 2, FaxFacility = 4};
const int ALL_FACILITIES = VoiceFacility | DataFacility | FaxFacility;
// struct to hold password info
struct PWInfo
{
string _facility;
int _maxPasswdLen;
};
// call forward reasons
// AllReasons encompasses 0..3
// AllConditionalReasons encompasses 1..3
enum ForwardReason {UnconditionalReason = 0, MobileBusyReason = 1,
NoReplyReason = 2, NotReachableReason = 3,
AllReasons = 4, AllConditionalReasons = 5, NoReason = 6};
// call forward modes
enum ForwardMode {DisableMode = 0, EnableMode = 1,
RegistrationMode = 3, ErasureMode = 4};
// call forward info
struct ForwardInfo
{
bool _active; // status in the network
FacilityClass _cl; // voice, fax, or data
string _number; // telephone number
string _subAddr; // subaddress
int _time; // time in the range 1..30 (for NoReplyReason)
ForwardReason _reason; // reason for the forwarding
};
// SMS types
typedef Ref<SMSStore> SMSStoreRef;
typedef vector<SMSStoreRef> SMSStoreVector;
// this class allows access to all functions of a ME/TA as described
// in sections 5-8 of ETSI GSM 07.07
// Note: If the ME is changed (ie. disconnected an another one connected
// to the TA), a new ME object must be created
// (Mobile equipment = ME, terminal adapter = TA)
class MeTa : public RefBase
{
protected:
Ref<Port> _port; // port the ME/TA is connected to
Ref<GsmAt> _at; // chat object for the port
PhonebookVector _phonebookCache; // cache of all used phonebooks
SMSStoreVector _smsStoreCache; // cache of all used phonebooks
string _lastPhonebookName; // remember last phonebook set on ME/TA
string _lastSMSStoreName; // remember last SMS store set on ME/TA
Capabilities _capabilities; // ME/TA quirks
GsmEvent _defaultEventHandler; // default event handler
// see comments in MeTa::init()
string _lastCharSet; // remember last character set
// init ME/TA to sensible defaults
void init() throw(GsmException);
public:
// initialize a new MeTa object given the port
MeTa(Ref<Port> port) throw(GsmException);
// initialize a new MeTa object given the AT handler
//MeTa(Ref<GsmAt> at) throw(GsmException);
// set the current phonebook in the ME
// remember the last phonebook set for optimisation
void setPhonebook(string phonebookName) throw(GsmException);
// set the current SMS store in the ME
// set storeTypes to
// 1 to set store for reading and deleting
// 2 to set store for writing and sending (includes type 1)
// 3 to preferred store for receiving SMS (includes types 1 and 2)
// remember the last SMS store set for optimisation
// if needResultCode is set this optimisation is not done
string setSMSStore(string smsStore, int storeTypes,
bool needResultCode = false)
throw(GsmException);
// get current SMS store settings
void getSMSStore(string &readDeleteStore,
string &writeSendStore,
string &receiveStore) throw(GsmException);
// get capabilities of this ME/TA
Capabilities getCapabilities() const {return _capabilities;}
// return my port
Ref<Port> getPort() {return _port;}
// return my at handler
Ref<GsmAt> getAt() {return _at;}
// set event handler for unsolicited result codes
GsmEvent *setEventHandler(GsmEvent *newHandler)
{return _at->setEventHandler(newHandler);}
// wait for an event
void waitEvent(GsmTime timeout) throw(GsmException);
// *** ETSI GSM 07.07 Section 5: "General Commands"
// return ME information
MEInfo getMEInfo() throw(GsmException);
// return available character sets
vector<string> getSupportedCharSets() throw(GsmException);// (+CSCS=?)
// return current character set (default: GSM)
string getCurrentCharSet() throw(GsmException);// (+CSCS?)
// set character set to use
void setCharSet(string charSetName) throw(GsmException);// (+CSCS=)
// *** ETSI GSM 07.07 Section 6: "Call control commands and methods"
// get extended error report
string getExtendedErrorReport() throw(GsmException);// (+CEER)
// dial a number, CLI presentation as defined in network
void dial(string number) throw(GsmException);// (ATD)
// answer
void answer() throw(GsmException); // (ATA)
// hangup
void hangup() throw(GsmException); // (ATH)
// set Personal Identification Number
void setPIN(string number) throw(GsmException);// (+CPIN)
// get PIN Status
string getPINStatus() throw(GsmException);// (+CPIN?)
// *** ETSI GSM 07.07 Section 7: "Network service related commands"
// return available network operators
// this fills in all fields of OPInfo with the exception of _mode
vector<OPInfo> getAvailableOPInfo() throw(GsmException); // (+COPS=?)
// return current network operators
// this fills in all the fields of OPInfo with the exception of _status
OPInfo getCurrentOPInfo() throw(GsmException);
// set network operator
// caller must fill in ALL names it has read from previous calls
// of getCurrentOPInfo() or getAvailableOPInfo()
// (because ME/TA might not implement all names)
void setCurrentOPInfo(OPModes mode,
string longName = "",
string shortName = "",
int numericName = NOT_SET) throw(GsmException);
// get facility lock capabilities (+CLCK)
vector<string> getFacilityLockCapabilities() throw(GsmException);
// query facility lock status for named facility
bool getFacilityLockStatus(string facility, FacilityClass cl)
throw(GsmException);
// lock facility
void lockFacility(string facility, FacilityClass cl, string passwd = "")
throw(GsmException);
// unlock facility
void unlockFacility(string facility, FacilityClass cl, string passwd = "")
throw(GsmException);
// return names of facility for which a password can be set
// and the maximum length of the respective password
vector<PWInfo> getPasswords() throw(GsmException);// (+CPWD=?)
// set password for the given facility
void setPassword(string facility, string oldPasswd, string newPasswd)
throw(GsmException);
// (+CPWD=)
// get CLIP (caller line identification presentation) in the network
bool getNetworkCLIP() throw(GsmException);// (+CLIP?)
// set CLIP presentation on or off
// enables GsmEvent::callerLineID
void setCLIPPresentation(bool enable) throw(GsmException);// (+CLIP=)
// returns if the above is enable
bool getCLIPPresentation() throw(GsmException);// (+CLIP?)
// set call forwarding
void setCallForwarding(ForwardReason reason,
ForwardMode mode,
string number,
string subaddr,
FacilityClass cl = (FacilityClass)ALL_FACILITIES,
int forwardTime = NOT_SET)
throw(GsmException); // (+CCFC=)
// get Information of currently set CF in the network
// the caller must give the reason to query
void getCallForwardInfo(ForwardReason reason,
ForwardInfo &voice,
ForwardInfo &fax,
ForwardInfo &data)
throw(GsmException); // (+CCFC=)
// *** ETSI GSM 07.07 Section 8: "Mobile Equipment control
// and status commands"
// return/set ME functionality level (+CFUN):
// 0 Minimum functionality
// 1 full functionality
// 2 disable phone transmit RF circuits only
// 3 disable phone receive RF circuits only
// 4 disable phone both transmit and receive RF circuits
// 5...127 implementation-defined
int getFunctionalityLevel() throw(GsmException);
void setFunctionalityLevel(int level) throw(GsmException);
// return battery charge status (+CBC):
// 0 ME is powered by the battery
// 1 ME has a battery connected, but is not powered by it
// 2 ME does not have a battery connected
// 3 Recognized power fault, calls inhibited
int getBatteryChargeStatus() throw(GsmException);
// return battery charge (range 0..100) (+CBC)
int getBatteryCharge() throw(GsmException);
// get signal strength indication (+CSQ):
// 0 -113 dBm or less
// 1 -111 dBm
// 2...30 -109... -53 dBm
// 31 -51 dBm or greater
// 99 not known or not detectable
int getSignalStrength() throw(GsmException);
// get channel bit error rate (+CSQ):
// 0...7 as RXQUAL values in the table in GSM 05.08 [20] subclause 8.2.4
// 99 not known or not detectable
int getBitErrorRate() throw(GsmException);
// get available phone book memory storage strings (+CPBS=?)
vector<string> getPhoneBookStrings() throw(GsmException);
// get phone book given the phone book memory storage string
PhonebookRef getPhonebook(string phonebookString,
bool preload = false) throw(GsmException);
// *** ETSI GSM 07.05 SMS functions
// return service centre address (+CSCA?)
string getServiceCentreAddress() throw(GsmException);
// set service centre address (+CSCA=)
void setServiceCentreAddress(string sca) throw(GsmException);
// return names of available message stores (<mem1>, +CPMS=?)
vector<string> getSMSStoreNames() throw(GsmException);
// return SMS store given the name
SMSStoreRef getSMSStore(string storeName) throw(GsmException);
// send a single SMS message
void sendSMS(Ref<SMSSubmitMessage> smsMessage) throw(GsmException);
// send one or several (concatenated) SMS messages
// The SUBMIT message template must have all options set, only
// the userData and the userDataHeader are changed.
// If oneSMS is true, only one SMS is sent. Otherwise several SMSs
// are sent. If concatenatedMessageId is != -1 this is used as the message
// ID for concatenated SMS (for this a user data header as defined in
// GSM GTS 3.40 is used, the old UDH in the template is overwritten).
void sendSMSs(Ref<SMSSubmitMessage> smsTemplate, string text,
bool oneSMS = false,
int concatenatedMessageId = -1)
throw(GsmException);
// set SMS service level
// if set to 1 send commands return ACK PDU, 0 is the default
void setMessageService(int serviceLevel) throw(GsmException);
// return SMS service level
unsigned int getMessageService() throw(GsmException);
// return true if any of the thre message types GsmEvent::SMSMessageType
// is routed directly to the TA and not stored in the ME
void getSMSRoutingToTA(bool &smsRouted, // (+CNMI?)
bool &cbsRouted,
bool &statusReportsRouted) throw(GsmException);
// sets routing of SMS to TA to true for all supported SMSMessageTypes
// if onlyReceptionIndication is set to true
// only GsmEvent::SMSReceptionIndication is called
// this has two reasons: GSM 07.05 section 3.4.1 does not recommend
// direct routing of new SMS to the TA
// I cannot test direct routing of SMS because it does not work with
// my hardware
void setSMSRoutingToTA(bool enableSMS, bool enableCBS,
bool enableStatReport,
bool onlyReceptionIndication = true)
throw(GsmException);
// (+CNMI=)
bool getCallWaitingLockStatus(FacilityClass cl)
throw(GsmException);
void setCallWaitingLockStatus(FacilityClass cl,
bool lock)throw(GsmException);
void setCLIRPresentation(bool enable) throw(GsmException);
//(+CLIR)
// 0:according to the subscription of the CLIR service
// 1:CLIR invocation
// 2:CLIR suppression
int getCLIRPresentation() throw(GsmException);
friend class Phonebook;
friend class SMSStore;
};
};
#endif // GSM_ME_TA_H

View File

@ -0,0 +1,32 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_nls.cc
// *
// * Purpose: Groups macros, initialization and includes
// * for National Language Support (NLS)
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 3.11.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_nls.h>
#include <string>
using namespace std;
#ifdef ENABLE_NLS
using namespace gsmlib;
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
bool InitNLS::initialized = false;
#endif // ENABLE_NLS

View File

@ -0,0 +1,71 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_nls.h
// *
// * Purpose: Groups macros, initialization and includes
// * for National Language Support (NLS)
// *
// * Warning: Only include this header from gsmlib .cc-files
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 3.11.1999
// *************************************************************************
#ifndef GSM_NLS_H
#define GSM_NLS_H
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#ifdef ENABLE_NLS
#ifdef HAVE_LIBINTL_H
#include <libintl.h>
#else
#include "../intl/libintl.h"
#endif
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
#define _(String) dgettext(PACKAGE, String)
// this causes automatic NLS initialization if one file of the library
// includes gsm_nls.h
namespace gsmlib
{
const class InitNLS
{
static bool initialized;
public:
InitNLS()
{
if (! initialized) // do only once
{
setlocale(LC_ALL, "");
#ifdef LOCAL_TRANSLATIONS
bindtextdomain(PACKAGE, "../po");
#else
bindtextdomain(PACKAGE, LOCALEDIR);
#endif
textdomain(PACKAGE);
initialized = true;
}
}
} initNLS;
};
#else
#define _(String) (String)
#endif // ENABLE_NLS
#define N_(String) (String)
#endif // GSM_NLS_H

View File

@ -0,0 +1,381 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_parser.cc
// *
// * Purpose: Parser to parse MA/TA result strings
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 13.5.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_parser.h>
#include <gsmlib/gsm_nls.h>
#include <ctype.h>
#include <assert.h>
#include <strstream>
using namespace std;
using namespace gsmlib;
// Parser members
int Parser::nextChar(bool skipWhiteSpace)
{
if (skipWhiteSpace)
while (_i < _s.length() && isspace(_s[_i])) ++_i;
if (_i == _s.length())
{
_eos = true;
return -1;
}
return _s[_i++];
}
bool Parser::checkEmptyParameter(bool allowNoParameter) throw(GsmException)
{
int c = nextChar();
if (c == ',' || c == -1)
if (allowNoParameter)
{
putBackChar();
return true;
}
else
throwParseException(_("expected parameter"));
putBackChar();
return false;
}
string Parser::parseString2(bool stringWithQuotationMarks)
throw(GsmException)
{
int c;
string result;
if (parseChar('"', true)) // OK, string starts and ends with quotation mark
if (stringWithQuotationMarks)
{
// read till end of line
while ((c = nextChar(false)) != -1)
result += c;
// check for """ at end of line
if (result.length() == 0 || result[result.length() - 1] != '"')
throwParseException(_("expected '\"'"));
// remove """ at the end
result.resize(result.length() - 1);
}
else
{
// read till next """
while ((c = nextChar(false)) != '"')
if (c == -1)
throwParseException();
else
result += c;
}
else // string ends with "," or EOL
{
c = nextChar(false);
while (c != ',' && c != -1)
{
result += c;
c = nextChar(false);
}
if (c == ',') putBackChar();
}
return result;
}
int Parser::parseInt2() throw(GsmException)
{
string s;
int c;
int result;
while (isdigit(c = nextChar())) s += c;
putBackChar();
if (s.length() == 0)
throwParseException(_("expected number"));
istrstream is(s.c_str());
is >> result;
return result;
}
void Parser::throwParseException(string message) throw(GsmException)
{
ostrstream os;
if (message.length() == 0)
throw GsmException(stringPrintf(_("unexpected end of string '%s'"),
_s.c_str()), ParserError);
else
throw GsmException(message +
stringPrintf(_(" (at position %d of string '%s')"), _i,
_s.c_str()), ParserError);
}
Parser::Parser(string s) : _i(0), _s(s), _eos(false)
{
}
bool Parser::parseChar(char c, bool allowNoChar) throw(GsmException)
{
if (nextChar() != c)
if (allowNoChar)
{
putBackChar();
return false;
}
else
throwParseException(stringPrintf(_("expected '%c'"), c));
return true;
}
vector<string> Parser::parseStringList(bool allowNoList)
throw(GsmException)
{
// handle case of empty parameter
vector<string> result;
if (checkEmptyParameter(allowNoList)) return result;
parseChar('(');
if (nextChar() != ')')
{
putBackChar();
while (1)
{
result.push_back(parseString());
int c = nextChar();
if (c == ')')
break;
if (c == -1)
throwParseException();
if (c != ',')
throwParseException(_("expected ')' or ','"));
}
}
return result;
}
vector<bool> Parser::parseIntList(bool allowNoList)
throw(GsmException)
{
// handle case of empty parameter
bool isRange = false;
vector<bool> result;
int resultCapacity = 0;
unsigned int saveI = _i;
if (checkEmptyParameter(allowNoList)) return result;
// check for the case of a integer list consisting of only one parameter
// some TAs omit the parentheses in this case
if (isdigit(nextChar()))
{
putBackChar();
int num = parseInt();
result.resize(num + 1, false);
result[num] = true;
return result;
}
putBackChar();
// run in two passes
// pass 0: find capacity needed for result
// pass 1: resize result and fill it in
for (int pass = 0; pass < 2; ++pass)
{
if (pass == 1)
{
_i = saveI;
result.resize(resultCapacity + 1, false);
}
parseChar('(');
if (nextChar() != ')')
{
putBackChar();
int lastInt = -1;
while (1)
{
int thisInt = parseInt();
if (isRange)
{
assert(lastInt != -1);
if (lastInt <= thisInt)
for (int i = lastInt; i < thisInt; ++i)
{
if (i > resultCapacity)
resultCapacity = i;
if (pass == 1)
result[i] = true;
}
else
for (int i = thisInt; i < lastInt; ++i)
{
if (i > resultCapacity)
resultCapacity = i;
if (pass == 1)
result[i] = true;
}
isRange = false;
}
if (thisInt > resultCapacity)
resultCapacity = thisInt;
if (pass == 1)
result[thisInt] = true;
lastInt = thisInt;
int c = nextChar();
if (c == ')')
break;
if (c == -1)
throwParseException();
if (c != ',' && c != '-')
throwParseException(_("expected ')', ',' or '-'"));
if (c == ',')
isRange = false;
else // is '-'
if (isRange)
throwParseException(_("range of the form a-b-c not allowed"));
else
isRange = true;
}
}
}
if (isRange)
throwParseException(_("range of the form a- no allowed"));
return result;
}
vector<ParameterRange> Parser::parseParameterRangeList(bool allowNoList)
throw(GsmException)
{
// handle case of empty parameter
vector<ParameterRange> result;
if (checkEmptyParameter(allowNoList)) return result;
result.push_back(parseParameterRange());
while (parseComma(true))
{
result.push_back(parseParameterRange());
}
return result;
}
ParameterRange Parser::parseParameterRange(bool allowNoParameterRange)
throw(GsmException)
{
// handle case of empty parameter
ParameterRange result;
if (checkEmptyParameter(allowNoParameterRange)) return result;
parseChar('(');
result._parameter = parseString();
parseComma();
result._range = parseRange(false, true);
parseChar(')');
return result;
}
IntRange Parser::parseRange(bool allowNoRange, bool allowNonRange)
throw(GsmException)
{
// handle case of empty parameter
IntRange result;
if (checkEmptyParameter(allowNoRange)) return result;
parseChar('(');
result._low = parseInt();
// allow non-ranges is allowNonRange == true
if (parseChar('-', allowNonRange))
result._high = parseInt();
parseChar(')');
return result;
}
int Parser::parseInt(bool allowNoInt) throw(GsmException)
{
// handle case of empty parameter
int result = NOT_SET;
if (checkEmptyParameter(allowNoInt)) return result;
result = parseInt2();
return result;
}
string Parser::parseString(bool allowNoString,
bool stringWithQuotationMarks)
throw(GsmException)
{
// handle case of empty parameter
string result;
if (checkEmptyParameter(allowNoString)) return result;
result = parseString2(stringWithQuotationMarks);
return result;
}
bool Parser::parseComma(bool allowNoComma) throw(GsmException)
{
if (nextChar() != ',')
if(allowNoComma)
{
putBackChar();
return false;
}
else
throwParseException(_("expected comma"));
return true;
}
string Parser::parseEol() throw(GsmException)
{
string result;
int c;
while ((c = nextChar()) != -1) result += c;
return result;
}
void Parser::checkEol() throw(GsmException)
{
if (nextChar() != -1)
{
putBackChar();
throwParseException(_("expected end of line"));
}
}
string Parser::getEol()
{
string result;
int c;
unsigned int saveI = _i;
bool saveEos = _eos;
while ((c = nextChar()) != -1) result += c;
_i = saveI;
_eos = saveEos;
return result;
}

View File

@ -0,0 +1,125 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_parser.h
// *
// * Purpose: Parser to parse MA/TA result strings
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 13.5.1999
// *************************************************************************
#ifndef GSM_PARSER_H
#define GSM_PARSER_H
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_error.h>
#include <string>
#include <vector>
using namespace std;
namespace gsmlib
{
class Parser : public RefBase
{
private:
unsigned int _i; // index into _s, next character
string _s; // string to parse
bool _eos; // true if end-of-string reached in nextChar()
// return next character or -1 if end of string
int nextChar(bool skipWhiteSpace = true);
// "puts back" a character
void putBackChar() {if (! _eos) --_i;}
// check for empty parameter (ie. "," or end of string)
// skips white space
// returns true if no parameter
// or throw an GsmException if allowNoParameter == false
bool checkEmptyParameter(bool allowNoParameter) throw(GsmException);
// parse a string (like "string")
// throw an exception if not well-formed
string parseString2(bool stringWithQuotationMarks) throw(GsmException);
// parse a int (like 1234)
// throw an exception if not well-formed
int parseInt2() throw(GsmException);
// throw a parser exception
void throwParseException(string message = "") throw(GsmException);
public:
Parser(string s);
// the following functions skip white space
// parse a character, if absent throw a GsmException
// return false if allowNoChar == true and character not encountered
bool parseChar(char c, bool allowNoChar = false) throw(GsmException);
// parse a list of the form "("ABC", DEF")"
// the list can be empty (ie. == "" ) if allowNoList == true
vector<string> parseStringList(bool allowNoList = false)
throw(GsmException);
// parse a list of the form "(12, 14)" or "(1-4, 10)"
// the result is returned as a bit vector where for each integer
// in the list and/or range(s) a bit is set
// the list can be empty (ie. == "") if allowNoList == true
vector<bool> parseIntList(bool allowNoList = false)
throw(GsmException);
// parse a list of parameter ranges (see below)
// the list can be empty (ie. == "" ) if allowNoList == true
vector<ParameterRange> parseParameterRangeList(bool allowNoList = false)
throw(GsmException);
// parse a string plus its valid integer range of the
// form "("string",(1-125))"
// the parameter range may be absent if allowNoParameterRange == true
ParameterRange parseParameterRange(bool allowNoParameterRange = false)
throw(GsmException);
// parse an integer range of the form "(1-125)"
// the range may be absent if allowNoRange == true
// then IntRange::_high and _low are set to NOT_SET
// the range may be short if allowNonRange == true
// then IntRange::_high is set to NOT_SET
IntRange parseRange(bool allowNoRange = false, bool allowNonRange = false)
throw(GsmException);
// parse an integer of the form "1234"
// allow absent int if allowNoInt == true
// then it returns NOT_SET
int parseInt(bool allowNoInt = false) throw(GsmException);
// parse a string of the form ""string""
// allow absent string if allowNoString == true
// then it returns ""
// if stringWithQuotationMarks == true the string may contain """
// the string is then parsed till the end of the line
string parseString(bool allowNoString = false,
bool stringWithQuotationMarks = false)
throw(GsmException);
// parse a single ","
// the comma may be absent if allowNoComma == true
// returns true if there was a comma
bool parseComma(bool allowNoComma = false) throw(GsmException);
// parse till end of line, return result without whitespace
string parseEol() throw(GsmException);
// check that end of line is reached
void checkEol() throw(GsmException);
// return string till end of line without whitespace
// (does not change internal state)
string getEol();
};
};
#endif // GSM_PARSER_H

View File

@ -0,0 +1,585 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_phonebook.cc
// *
// * Purpose: Phonebook management functions
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 6.5.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_nls.h>
#include <gsmlib/gsm_sysdep.h>
#include <gsmlib/gsm_phonebook.h>
#include <gsmlib/gsm_parser.h>
#include <gsmlib/gsm_me_ta.h>
#include <strstream>
#include <iostream>
#include <assert.h>
#include <ctype.h>
using namespace std;
using namespace gsmlib;
// PhonebookEntry members
PhonebookEntry::PhonebookEntry(const PhonebookEntryBase &e)
throw(GsmException) : _cached(true), _myPhonebook(NULL)
{
set(e.telephone(), e.text(), e.index(), e.useIndex());
}
void PhonebookEntry::set(string telephone, string text, int index,
bool useIndex)
throw(GsmException)
{
checkTextAndTelephone(text, telephone);
if (_myPhonebook != NULL)
{
if (text.length() > _myPhonebook->getMaxTextLen())
throw GsmException(
stringPrintf(_("length of text '%s' exceeds maximum text "
"length (%d characters) of phonebook '%s'"),
text.c_str(), _myPhonebook->getMaxTextLen(),
_myPhonebook->name().c_str()),
ParameterError);
if (telephone.length() > _myPhonebook->getMaxTelephoneLen())
throw GsmException(
stringPrintf(_("length of telephone number '%s' "
"exceeds maximum telephone number "
"length (%d characters) of phonebook '%s'"),
telephone.c_str(), _myPhonebook->getMaxTelephoneLen(),
_myPhonebook->name().c_str()),
ParameterError);
_myPhonebook->writeEntry(_index, telephone, text);
}
else
_index = index;
_useIndex = useIndex;
_cached = true;
_telephone = telephone;
_text = text;
_changed = true;
}
string PhonebookEntry::text() const throw(GsmException)
{
if (! cached())
{
assert(_myPhonebook != NULL);
// these operations are at least "logically const"
PhonebookEntry *thisEntry = const_cast<PhonebookEntry*>(this);
_myPhonebook->readEntry(_index, thisEntry->_telephone, thisEntry->_text);
thisEntry->_cached = true;
}
return _text;
}
string PhonebookEntry::telephone() const throw(GsmException)
{
if (! cached())
{
assert(_myPhonebook != NULL);
// these operations are at least "logically const"
PhonebookEntry *thisEntry = const_cast<PhonebookEntry*>(this);
_myPhonebook->readEntry(_index, thisEntry->_telephone, thisEntry->_text);
thisEntry->_cached = true;
}
return _telephone;
}
bool PhonebookEntry::cached() const
{
if (_myPhonebook == NULL)
return _cached;
else
return _cached && _myPhonebook->_useCache;
}
PhonebookEntry::PhonebookEntry(const PhonebookEntry &e) throw(GsmException)
{
set(e._telephone, e._text, e._index, e._useIndex);
}
PhonebookEntry &PhonebookEntry::operator=(const PhonebookEntry &e)
throw(GsmException)
{
set(e._telephone, e._text, e._index, e._useIndex);
return *this;
}
// Phonebook members
int Phonebook::parsePhonebookEntry(string response,
string &telephone, string &text)
{
// this is a workaround for a bug that occurs with my ME/TA combination
// some texts are truncated and don't have a trailing "
if (response.length() > 0 && response[response.length() - 1] != '"')
response += '"';
Parser p(response);
int index = p.parseInt();
p.parseComma();
// handle case of empty entry
if (p.getEol().substr(0, 5) == "EMPTY")
{
telephone = "";
text = "";
return index;
}
telephone = p.parseString();
p.parseComma();
unsigned int numberFormat = p.parseInt();
if (numberFormat != UnknownNumberFormat &&
numberFormat != InternationalNumberFormat)
cerr << "*** GSMLIB WARNING: Unexpected number format when reading from "
<< "phonebook: " << numberFormat << " ***" << endl;
p.parseComma();
text = p.parseString(false, true);
if (lowercase(_myMeTa.getCurrentCharSet()) == "gsm")
text = gsmToLatin1(text);
if (numberFormat == InternationalNumberFormat)
{
// skip leading "+" signs that may already exist
while (telephone.length() > 0 && telephone[0] == '+')
telephone = telephone.substr(1);
telephone = "+" + telephone;
}
return index;
}
void Phonebook::readEntry(int index, string &telephone, string &text)
throw(GsmException)
{
// select phonebook
_myMeTa.setPhonebook(_phonebookName);
// read entry
string response = _at->chat("+CPBR=" + intToStr(index), "+CPBR:",
false, // dont't ignore errors
true); // but accept empty responses
// (the latter is necessary for some mobile phones that return nothing
// if the entry is empty)
if (response.length() == 0) // OK phone returned empty response
{
telephone = text = ""; // then the entry is empty as well
}
else
parsePhonebookEntry(response, telephone, text);
#ifndef NDEBUG
if (debugLevel() >= 1)
cerr << "*** Reading PB entry " << index << " number " << telephone
<< " text " << text << endl;
#endif
}
void Phonebook::findEntry(string text, int &index, string &telephone)
throw(GsmException)
{
// select phonebook
_myMeTa.setPhonebook(_phonebookName);
// read entry
string response = _at->chat("+CPBF=\"" + text + "\"", "+CPBF:",
false, // dont't ignore errors
true); // but accept empty responses
// (the latter is necessary for some mobile phones that return nothing
// if the entry is empty)
if (response.length() == 0) // OK phone returned empty response
{
telephone = ""; // then the entry is empty as well
index = 0;
}
else
index=parsePhonebookEntry(response, telephone, text);
#ifndef NDEBUG
if (debugLevel() >= 1)
cerr << "*** Finding PB entry " << text << " number " << telephone
<< " index " << index << endl;
#endif
}
void Phonebook::writeEntry(int index, string telephone, string text)
throw(GsmException)
{
#ifndef NDEBUG
if (debugLevel() >= 1)
cerr << "*** Writing PB entry #" << index << " number '" << telephone
<< "' text '" << text << "'" << endl;
#endif
// select phonebook
_myMeTa.setPhonebook(_phonebookName);
// write entry
string s;
if (telephone == "" && text == "")
{
ostrstream os;
os << "+CPBW=" << index;
os << ends;
char *ss = os.str();
s = string(ss);
delete[] ss;
}
else
{
int type;
if (telephone.find('+') == string::npos)
type = UnknownNumberFormat;
else
type = InternationalNumberFormat;
string gsmText = text;
if (lowercase(_myMeTa.getCurrentCharSet()) == "gsm")
gsmText = latin1ToGsm(gsmText);
ostrstream os;
os << "+CPBW=" << index << ",\"" << telephone << "\"," << type
<< ",\"";
os << ends;
char *ss = os.str();
s = string(ss);
delete[] ss;
// this cannot be added with ostrstream because the gsmText can
// contain a zero (GSM default alphabet for '@')
s += gsmText + "\"";
}
_at->chat(s);
}
Phonebook::iterator Phonebook::insertFirstEmpty(string telephone, string text)
throw(GsmException)
{
for (int i = 0; i < _maxSize; i++)
if (_phonebook[i].empty())
{
_phonebook[i].set(telephone, text);
adjustSize(1);
return begin() + i;
}
throw GsmException(_("phonebook full"), OtherError);
}
Phonebook::iterator Phonebook::insert(const string telephone,
const string text,
const int index)
{
for (int i = 0; i < _maxSize; i++)
if (_phonebook[i].index() == index)
if (_phonebook[i].empty())
{
_phonebook[i].set(telephone, text);
adjustSize(1);
return begin() + i;
}
else
throw GsmException(_("attempt to overwrite phonebook entry"),
OtherError);
return end();
}
Phonebook::Phonebook(string phonebookName, Ref<GsmAt> at, MeTa &myMeTa,
bool preload) throw(GsmException) :
_phonebookName(phonebookName), _at(at), _myMeTa(myMeTa), _useCache(true)
{
// select phonebook
_myMeTa.setPhonebook(_phonebookName);
// query size and maximum capacity of phonebook
_size = -1; // -1 means not known yet
_maxSize = -1;
Parser q(_at->chat("+CPBS?", "+CPBS:"));
string dummy = q.parseString();
if (q.parseComma(true)) // this means that
{ // used and total result is supported by ME
_size = q.parseInt();
q.parseComma();
_maxSize = q.parseInt();
}
// get basic phonebook info from ME
Parser p(_at->chat("+CPBR=?", "+CPBR:"));
// get index of actually available entries in the phonebook
vector<bool> availablePositions = p.parseIntList();
p.parseComma();
_maxNumberLength = p.parseInt();
p.parseComma();
_maxTextLength = p.parseInt();
// find out capacity of phonebook in ME
// Note: The phonebook in the ME may be sparse, eg. the range of
// allowed index numbers may be something like (3-4, 20-100, 120).
// The standard allows this, even though it is unlikely to be
// implemented like that by anyone.
// In memory we store only phonebook entries that may actually be
// used, ie. the phonebook in memory is not sparse.
// Each entry has a member _index that corresponds to the index in the ME.
if (_maxSize == -1)
{
_maxSize = 0;
for (vector<bool>::iterator i = availablePositions.begin();
i != availablePositions.end(); ++i)
if (*i) ++_maxSize;
}
// for use with preload below
int *meToPhonebookIndexMap =
(int*)alloca(sizeof(int) * (availablePositions.size() + 1));
// initialize phone book entries
if (_maxSize == 0)
_phonebook = NULL;
else
_phonebook = new PhonebookEntry[_maxSize];
int nextAvailableIndex = 0;
int i;
for (i = 0; i < _maxSize; i++)
{
while (! availablePositions[nextAvailableIndex])
nextAvailableIndex++;
_phonebook[i]._index = nextAvailableIndex;
_phonebook[i]._cached = false;
_phonebook[i]._myPhonebook = this;
meToPhonebookIndexMap[nextAvailableIndex++] = i;
}
// find out first index number of phonebook
int firstIndex = -1;
for (i = 0; i < _maxSize; i++)
if (availablePositions[i])
{
firstIndex = i;
break;
}
// preload phonebook
// Note: this contains a workaround for the bug that
// some MEs can not return the entire phonebook with one AT command
// To detect this condition, _size must be known
// also, this code only handles non-sparse phonebooks
if (preload && _size != -1 &&
(int)availablePositions.size() == _maxSize + firstIndex)
{
int entriesRead = 0;
int startIndex = firstIndex;
while (entriesRead < _size)
{
reportProgress(0, _maxSize); // chatv also calls reportProgress()
vector<string> responses =
_at->chatv("+CPBR=" + intToStr(startIndex) +
"," + intToStr(_maxSize + firstIndex - 1),
"+CPBR:", true);
// this means that we have read nothing even though not all
// entries have been retrieved (entriesRead < _size)
// this could be due to a malfunction of the ME...
// anyway, missing entries can be read later by readEntry()
if (responses.size() == 0)
{
#ifndef NDEBUG
if (debugLevel() >= 1)
cerr << "*** error when preloading phonebook: "
"not all entries returned" << endl;
#endif
break;
}
for (vector<string>::iterator i = responses.begin();
i != responses.end(); ++i)
{
string telephone, text;
int meIndex = parsePhonebookEntry(*i, telephone, text);
_phonebook[meToPhonebookIndexMap[meIndex]]._cached = true;
_phonebook[meToPhonebookIndexMap[meIndex]]._telephone = telephone;
_phonebook[meToPhonebookIndexMap[meIndex]]._text = text;
assert(_phonebook[meToPhonebookIndexMap[meIndex]]._index == meIndex);
++entriesRead;
startIndex = meIndex + 1;
#ifndef NDEBUG
if (debugLevel() >= 1)
cerr << "*** Preloading PB entry " << meIndex
<< " number " << telephone
<< " text " << text << endl;
#endif
}
}
}
}
Phonebook::iterator Phonebook::begin()
{
return &_phonebook[0];
}
Phonebook::const_iterator Phonebook::begin() const
{
return &_phonebook[0];
}
Phonebook::iterator Phonebook::end()
{
return &_phonebook[_maxSize];
}
Phonebook::const_iterator Phonebook::end() const
{
return &_phonebook[_maxSize];
}
Phonebook::reference Phonebook::operator[](int n)
{
return _phonebook[n];
}
Phonebook::const_reference Phonebook::operator[](int n) const
{
return _phonebook[n];
}
Phonebook::reference Phonebook::front()
{
return _phonebook[0];
}
Phonebook::const_reference Phonebook::front() const
{
return _phonebook[0];
}
Phonebook::reference Phonebook::back()
{
return _phonebook[_maxSize - 1];
}
Phonebook::const_reference Phonebook::back() const
{
return _phonebook[_maxSize - 1];
}
int Phonebook::size() const throw(GsmException)
{
if (_size != -1)
return _size;
else
{
int result = 0;
for (int i = 0; i < _maxSize; i++)
if (! _phonebook[i].empty())
result++;
Phonebook *thisPhonebook = const_cast<Phonebook*>(this);
thisPhonebook->_size = result;
return result;
}
}
Phonebook::iterator Phonebook::insert(iterator position,
const PhonebookEntry& x)
throw(GsmException)
{
if (x.useIndex() && x.index() != -1)
return insert(x.telephone(), x.text(), x.index());
else
return insertFirstEmpty(x.telephone(), x.text());
}
void Phonebook::insert (iterator pos, int n, const PhonebookEntry& x)
throw(GsmException)
{
for (int i = 0; i < n; i++)
if (x.useIndex() && x.index() != -1)
insert(x.telephone(), x.text(), x.index());
else
insertFirstEmpty(x.telephone(), x.text());
}
void Phonebook::insert (iterator pos, long n, const PhonebookEntry& x)
throw(GsmException)
{
for (long i = 0; i < n; i++)
if (x.useIndex() && x.index() != -1)
insert(x.telephone(), x.text(), x.index());
else
insertFirstEmpty(x.telephone(), x.text());
}
Phonebook::iterator Phonebook::erase(iterator position)
throw(GsmException)
{
if (! position->empty())
{
position->set("", "");
adjustSize(-1);
}
return position + 1;
}
Phonebook::iterator Phonebook::erase(iterator first, iterator last)
throw(GsmException)
{
iterator i;
for (i = first; i != last; ++i)
erase(i);
return i;
}
void Phonebook::clear() throw(GsmException)
{
for (iterator i = begin(); i != end(); ++i)
erase(i);
}
Phonebook::iterator Phonebook::find(string text) throw(GsmException)
{
int index;
string telephone;
int i;
for (i = 0; i < _maxSize; i++)
if (_phonebook[i].text() == text)
return begin() + i;
findEntry(text, index, telephone);
for (i = 0; i < _maxSize; i++)
if (_phonebook[i].index() == index)
if (_phonebook[i].cached())
{
// if entry was already (= cached) and is now different
// the SIM card or it's contents were changed
if (_phonebook[i]._telephone != telephone ||
_phonebook[i]._text != text)
throw GsmException(_("SIM card changed while accessing phonebook"),
OtherError);
}
else
{
_phonebook[i]._cached = true;
_phonebook[i]._telephone = telephone;
_phonebook[i]._text = text;
return begin() + i;
}
return end();
}
Phonebook::~Phonebook()
{
delete []_phonebook;
}

View File

@ -0,0 +1,195 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_phonebook.h
// *
// * Purpose: Phonebook management functions
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 4.5.1999
// *************************************************************************
#ifndef GSM_PHONEBOOK_H
#define GSM_PHONEBOOK_H
#include <gsmlib/gsm_sorted_phonebook_base.h>
#include <gsmlib/gsm_at.h>
#include <gsmlib/gsm_util.h>
#include <string>
#include <iterator>
#include <vector>
using namespace std;
namespace gsmlib
{
// forward declarations
class Phonebook;
// a single entry in the phonebook that corresponds to an ME entry
class PhonebookEntry : public PhonebookEntryBase
{
private:
// this constructor is only used by Phonebook
PhonebookEntry() {}
bool _cached; // true, if this entry corresponds to info
// in the ME
Phonebook *_myPhonebook;
public:
PhonebookEntry(string telephone, string text) :
PhonebookEntryBase(telephone, text),
_cached(true), _myPhonebook(NULL) {}
PhonebookEntry(const PhonebookEntryBase &e) throw(GsmException);
// accessor functions, inherited from PhonebookEntryBase
// set() does not use the index argument
void set(string telephone, string text, int index = -1,
bool useIndex = false)
throw(GsmException);
string text() const throw(GsmException);
string telephone() const throw(GsmException);
// return true if entry is cached (and caching is enabled)
bool cached() const;
PhonebookEntry(const PhonebookEntry &e) throw(GsmException);
PhonebookEntry &operator=(const PhonebookEntry &e) throw(GsmException);
virtual ~PhonebookEntry() {}
friend class Phonebook;
};
// this class corresponds to a phonebook in the ME
// all functions directly update storage in the ME
// if the ME is exchanged, the storage may become corrupted because
// of internal buffering in the Phonebook class
class Phonebook : public RefBase, public NoCopy
{
public:
// iterator defs
typedef PhonebookEntry *iterator;
typedef const PhonebookEntry *const_iterator;
typedef PhonebookEntry &reference;
typedef const PhonebookEntry &const_reference;
private:
PhonebookEntry *_phonebook; // array of size _maxSize of entries
int _maxSize; // maximum size of pb (-1 == not known yet)
int _size; // current size of pb (-1 == not known yet)
string _phonebookName; // name of the phonebook, 2-byte like "ME"
unsigned int _maxNumberLength; // maximum length of telephone number
unsigned int _maxTextLength; // maximum length of descriptive text
Ref<GsmAt> _at; // my GsmAt class
vector<int> _positionMap; // maps in-memory index to ME index
MeTa &_myMeTa; // the MeTa object that created this Phonebook
bool _useCache; // true if entries should be cached
// helper function, parse phonebook response returned by ME/TA
// returns index of entry
int parsePhonebookEntry(string response, string &telephone, string &text);
// internal access functions
// read/write/find entry from/to ME
void readEntry(int index, string &telephone, string &text)
throw(GsmException);
void writeEntry(int index, string telephone, string text)
throw(GsmException);
void findEntry(string text, int &index, string &telephone)
throw(GsmException);
// adjust size only if it was set once
void adjustSize(int sizeAdjust)
{
if (_size != -1) _size += sizeAdjust;
}
// insert into first empty position and return position where inserted
iterator insertFirstEmpty(const string telephone, const string text)
throw(GsmException);
// insert into specified index position
iterator insert(const string telephone, const string text,
const int index);
// used my class MeTa
// load phonebook name phonebookName, use AT handler at
// preload entire phonebook if preload == true
Phonebook(string phonebookName, Ref<GsmAt> at,
MeTa &myMeTa, bool preload = false) throw(GsmException);
public:
// set cache mode on or off
void setCaching(bool useCache) {_useCache = useCache;}
// return name of this phonebook (2-character string)
string name() const {return _phonebookName;}
// return maximum telephone number length
unsigned int getMaxTelephoneLen() const {return _maxNumberLength;}
// return maximum entry description length
unsigned int getMaxTextLen() const { return _maxTextLength;}
// phonebook traversal commands
// these are suitable to use stdc++ lib algorithms and iterators
// ME have fixed storage space implemented as memory slots
// that may either be empty or used
// traversal commands
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reference front();
const_reference front() const;
reference back();
const_reference back() const;
reference operator[](int n);
const_reference operator[](int n) const;
// the size macros return the number of used entries
int size() const throw(GsmException);
int max_size() const {return _maxSize;}
int capacity() const {return _maxSize;}
bool empty() const throw(GsmException) {return size() == 0;}
// insert iterators insert into the first empty cell regardless of position
// - existing iterators are not invalidated after an insert operation
// - return position where it was actually inserted (may be != position)
// - insert only writes to available positions
// - throw an exception if size() == max_size() (ie. not empty slots)
iterator insert(iterator position, const PhonebookEntry& x)
throw(GsmException);
// insert n times, same procedure as above
void insert(iterator pos, int n, const PhonebookEntry& x)
throw(GsmException);
void insert(iterator pos, long n, const PhonebookEntry& x)
throw(GsmException);
// erase operators set used slots to "empty"
iterator erase(iterator position) throw(GsmException);
iterator erase(iterator first, iterator last) throw(GsmException);
void clear() throw(GsmException);
// finds an entry given the text
iterator find(string text) throw(GsmException);
// destructor
virtual ~Phonebook();
friend class PhonebookEntry;
friend class MeTa;
};
// useful phonebook types
typedef Ref<Phonebook> PhonebookRef;
typedef vector<PhonebookRef> PhonebookVector;
};
#endif // GSM_PHONEBOOK_H

View File

@ -0,0 +1,58 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_port.h
// *
// * Purpose: Abstract port definition
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 3.5.1999
// *************************************************************************
#ifndef GSM_PORT_H
#define GSM_PORT_H
#include <gsmlib/gsm_error.h>
#include <gsmlib/gsm_util.h>
#include <string>
using namespace std;
namespace gsmlib
{
// TA defaults
const int TIMEOUT_SECS = 60;
const char DEFAULT_INIT_STRING[] = "E0";
const int DEFAULT_BAUD_RATE = 38400;
class Port : public RefBase
{
public:
// read line from port(including eol characters)
virtual string getLine() throw(GsmException) =0;
// write line to port
virtual void putLine(string line,
bool carriageReturn = true) throw(GsmException) =0;
// wait for new data to become available, return after timeout
// if timeout == 0, wait forever
// return true if data available
virtual bool wait(GsmTime timeout) throw(GsmException) =0;
// put back one byte that can be read by a subsequent call to readByte()
virtual void putBack(unsigned char c) =0;
// read a single byte, return -1 if error or file closed
virtual int readByte() throw(GsmException) =0;
// set timeout for the readByte(), getLine(), and putLine() functions
// (globally for ALL ports)
virtual void setTimeOut(unsigned int timeout) =0;
virtual ~Port() {}
};
};
#endif // GSM_PORT_H

View File

@ -0,0 +1,863 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_sms.cc
// *
// * Purpose: SMS functions
// * (ETSI GSM 07.05)
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 16.5.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_nls.h>
#include <gsmlib/gsm_sysdep.h>
#include <gsmlib/gsm_sms.h>
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_parser.h>
#include <gsmlib/gsm_me_ta.h>
#include <strstream>
#include <string>
using namespace std;
using namespace gsmlib;
// local constants
static const string dashes =
"---------------------------------------------------------------------------";
// SMSMessage members
Ref<SMSMessage> SMSMessage::decode(string pdu,
bool SCtoMEdirection,
GsmAt *at) throw(GsmException)
{
Ref<SMSMessage> result;
SMSDecoder d(pdu);
d.getAddress(true);
MessageType messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
if (SCtoMEdirection)
// TPDUs from SC to ME
switch (messageTypeIndicator)
{
case SMS_DELIVER:
result = new SMSDeliverMessage(pdu);
break;
case SMS_STATUS_REPORT:
result = new SMSStatusReportMessage(pdu);
break;
case SMS_SUBMIT_REPORT:
// observed with Motorola Timeport 260, the SCtoMEdirection can
// be wrong in this case
if (at != NULL && at->getMeTa().getCapabilities()._wrongSMSStatusCode)
result = new SMSSubmitMessage(pdu);
else
result = new SMSSubmitReportMessage(pdu);
break;
default:
throw GsmException(_("unhandled SMS TPDU type"), OtherError);
}
else
// TPDUs from ME to SC
switch (messageTypeIndicator)
{
case SMS_SUBMIT:
result = new SMSSubmitMessage(pdu);
break;
case SMS_DELIVER_REPORT:
result = new SMSDeliverReportMessage(pdu);
break;
case SMS_COMMAND:
result = new SMSCommandMessage(pdu);
break;
default:
throw GsmException(_("unhandled SMS TPDU type"), OtherError);
}
result->_at = at;
return result;
}
Ref<SMSMessage> SMSMessage::decode(istream& s) throw(gsmlib::GsmException)
{
string pdu;
unsigned char ScToMe;
s >> ScToMe;
s >> pdu;
return decode(pdu,ScToMe=='S');
}
unsigned char SMSMessage::send(Ref<SMSMessage> &ackPdu)
throw(GsmException)
{
if (_messageTypeIndicator != SMS_SUBMIT &&
_messageTypeIndicator != SMS_COMMAND)
throw GsmException(_("can only send SMS-SUBMIT and SMS-COMMAND TPDUs"),
ParameterError);
if (_at.isnull())
throw GsmException(_("no device given for sending SMS"), ParameterError);
string pdu = encode();
Parser p(_at->sendPdu("+CMGS=" +
intToStr(pdu.length() / 2 - getSCAddressLen()),
"+CMGS:", pdu));
unsigned char messageReference = p.parseInt();
if (p.parseComma(true))
{
string pdu = p.parseEol();
// add missing service centre address if required by ME
if (! _at->getMeTa().getCapabilities()._hasSMSSCAprefix)
pdu = "00" + pdu;
ackPdu = SMSMessage::decode(pdu);
}
else
ackPdu = SMSMessageRef();
return messageReference;
}
unsigned char SMSMessage::send() throw(GsmException)
{
SMSMessageRef mref;
return send(mref);
}
unsigned int SMSMessage::getSCAddressLen()
{
SMSEncoder e;
e.setAddress(_serviceCentreAddress, true);
return e.getLength();
}
unsigned char SMSMessage::userDataLength() const
{
unsigned int udhl = _userDataHeader.length();
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
return _userData.length() + (udhl ? ((1 + udhl) * 8 + 6) / 7 : 0);
else
return _userData.length() + (udhl ? (1 + udhl) : 0);
}
ostream& SMSMessage::operator<<(ostream& s)
{
unsigned char ScToMe;
if (dynamic_cast<SMSDeliverMessage*>(this) ||
dynamic_cast<SMSStatusReportMessage*>(this) ||
dynamic_cast<SMSSubmitReportMessage*>(this))
{
ScToMe = 'S';
}
else if (dynamic_cast<SMSSubmitMessage*>(this) ||
dynamic_cast<SMSCommandMessage*>(this) ||
dynamic_cast<SMSDeliverReportMessage*>(this))
{
ScToMe = 'M';
}
else
{
throw GsmException(_("unhandled SMS TPDU type"), OtherError);
}
s << ScToMe;
return s << encode();
}
// SMSMessage::SMSMessage(SMSMessage &m)
// {
// _at = m._at;
// }
// SMSMessage &SMSMessage::operator=(SMSMessage &m)
// {
// }
SMSMessage::~SMSMessage() {}
// SMSDeliverMessage members
void SMSDeliverMessage::init()
{
_messageTypeIndicator = SMS_DELIVER;
_moreMessagesToSend = false;
_replyPath = false;
_statusReportIndication = false;
_protocolIdentifier = 0;
}
SMSDeliverMessage::SMSDeliverMessage()
{
init();
}
SMSDeliverMessage::SMSDeliverMessage(string pdu) throw(GsmException)
{
SMSDecoder d(pdu);
_serviceCentreAddress = d.getAddress(true);
_messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
assert(_messageTypeIndicator == SMS_DELIVER);
_moreMessagesToSend = d.getBit(); // bit 2
d.getBit(); // bit 3
d.getBit(); // bit 4
_statusReportIndication = d.getBit(); // bit 5
bool userDataHeaderIndicator = d.getBit(); // bit 6
_replyPath = d.getBit(); // bit 7
_originatingAddress = d.getAddress();
_protocolIdentifier = d.getOctet();
_dataCodingScheme = d.getOctet();
_serviceCentreTimestamp = d.getTimestamp();
unsigned char userDataLength = d.getOctet();
d.markSeptet();
if (userDataHeaderIndicator)
{
_userDataHeader.decode(d);
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
userDataLength -= ((_userDataHeader.length() + 1) * 8 + 6) / 7;
else
userDataLength -= ((string)_userDataHeader).length() + 1;
}
else
_userDataHeader = UserDataHeader();
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
{ // userDataLength is length in septets
_userData = d.getString(userDataLength);
_userData = gsmToLatin1(_userData);
}
else
{ // userDataLength is length in octets
unsigned char *s =
(unsigned char*)alloca(sizeof(unsigned char) * userDataLength);
d.getOctets(s, userDataLength);
_userData.assign((char*)s, (unsigned int)userDataLength);
}
}
string SMSDeliverMessage::encode()
{
SMSEncoder e;
e.setAddress(_serviceCentreAddress, true);
e.set2Bits(_messageTypeIndicator); // bits 0..1
e.setBit(_moreMessagesToSend); // bit 2
e.setBit(); // bit 3
e.setBit(); // bit 4
e.setBit(_statusReportIndication); // bit 5
e.setBit(_userDataHeader.length() != 0); // bit 6
e.setBit(_replyPath); // bit 7
e.setAddress(_originatingAddress);
e.setOctet(_protocolIdentifier);
e.setOctet(_dataCodingScheme);
e.setTimestamp(_serviceCentreTimestamp);
e.setOctet(userDataLength());
e.markSeptet();
if (_userDataHeader.length()) _userDataHeader.encode(e);
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
e.setString(latin1ToGsm(_userData));
else
e.setOctets((unsigned char*)_userData.data(), _userData.length());
return e.getHexString();
}
string SMSDeliverMessage::toString() const
{
ostrstream os;
os << dashes << endl
<< _("Message type: SMS-DELIVER") << endl
<< _("SC address: '") << _serviceCentreAddress._number << "'" << endl
<< _("More messages to send: ") << _moreMessagesToSend << endl
<< _("Reply path: ") << _replyPath << endl
<< _("User data header indicator: ")
<< (_userDataHeader.length()!=0) << endl
<< _("Status report indication: ") << _statusReportIndication << endl
<< _("Originating address: '") << _originatingAddress._number
<< "'" << endl
<< _("Protocol identifier: 0x") << hex
<< (unsigned int)_protocolIdentifier << dec << endl
<< _("Data coding scheme: ") << _dataCodingScheme.toString() << endl
<< _("SC timestamp: ") << _serviceCentreTimestamp.toString() << endl
<< _("User data length: ") << (int)userDataLength() << endl
<< _("User data header: 0x")
<< bufToHex((unsigned char*)
((string)_userDataHeader).data(),
((string)_userDataHeader).length())
<< endl
<< _("User data: '") << _userData << "'" << endl
<< dashes << endl << endl
<< ends;
char *ss = os.str();
string result(ss);
delete[] ss;
return result;
}
Address SMSDeliverMessage::address() const
{
return _originatingAddress;
}
Ref<SMSMessage> SMSDeliverMessage::clone()
{
Ref<SMSMessage> result = new SMSDeliverMessage(*this);
return result;
}
// SMSSubmitMessage members
void SMSSubmitMessage::init()
{
// set everything to sensible default values
_messageTypeIndicator = SMS_SUBMIT;
_validityPeriodFormat = TimePeriod::Relative;
_validityPeriod._format = TimePeriod::Relative;
_validityPeriod._relativeTime = 168; // 2 days
_statusReportRequest = false;
_replyPath = false;
_rejectDuplicates = true;
_messageReference = 0;
_protocolIdentifier = 0;
}
SMSSubmitMessage::SMSSubmitMessage()
{
init();
}
SMSSubmitMessage::SMSSubmitMessage(string pdu) throw(GsmException)
{
SMSDecoder d(pdu);
_serviceCentreAddress = d.getAddress(true);
_messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
assert(_messageTypeIndicator == SMS_SUBMIT);
_rejectDuplicates = d.getBit(); // bit 2
_validityPeriodFormat = (TimePeriod::Format)d.get2Bits(); // bits 3..4
_statusReportRequest = d.getBit(); // bit 5
bool userDataHeaderIndicator = d.getBit(); // bit 6
_replyPath = d.getBit(); // bit 7
_messageReference = d.getOctet();
_destinationAddress = d.getAddress();
_protocolIdentifier = d.getOctet();
_dataCodingScheme = d.getOctet();
if (_validityPeriodFormat != TimePeriod::NotPresent)
_validityPeriod = d.getTimePeriod(_validityPeriodFormat);
unsigned char userDataLength = d.getOctet();
d.markSeptet();
if (userDataHeaderIndicator)
{
_userDataHeader.decode(d);
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
userDataLength -= ((_userDataHeader.length() + 1) * 8 + 6) / 7;
else
userDataLength -= ((string)_userDataHeader).length() + 1;
}
else
_userDataHeader = UserDataHeader();
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
{ // userDataLength is length in septets
_userData = d.getString(userDataLength);
_userData = gsmToLatin1(_userData);
}
else
{ // _userDataLength is length in octets
unsigned char *s =
(unsigned char*)alloca(sizeof(unsigned char) * userDataLength);
d.getOctets(s, userDataLength);
_userData.assign((char*)s, userDataLength);
}
}
SMSSubmitMessage::SMSSubmitMessage(string text, string number)
{
init();
_destinationAddress = Address(number);
_userData = text;
}
string SMSSubmitMessage::encode()
{
SMSEncoder e;
e.setAddress(_serviceCentreAddress, true);
e.set2Bits(_messageTypeIndicator); // bits 0..1
e.setBit(_rejectDuplicates); // bit 2
e.set2Bits(_validityPeriodFormat); // bits 3..4
e.setBit(_statusReportRequest); // bit 5
bool userDataHeaderIndicator = _userDataHeader.length() != 0;
e.setBit(userDataHeaderIndicator); // bit 6
e.setBit(_replyPath); // bit 7
e.setOctet(_messageReference);
e.setAddress(_destinationAddress);
e.setOctet(_protocolIdentifier);
e.setOctet(_dataCodingScheme);
e.setTimePeriod(_validityPeriod);
e.setOctet(userDataLength());
e.markSeptet();
if (userDataHeaderIndicator) _userDataHeader.encode(e);
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
e.setString(latin1ToGsm(_userData));
else
e.setOctets((unsigned char*)_userData.data(), _userData.length());
return e.getHexString();
}
string SMSSubmitMessage::toString() const
{
ostrstream os;
os << dashes << endl
<< _("Message type: SMS-SUBMIT") << endl
<< _("SC address: '") << _serviceCentreAddress._number << "'" << endl
<< _("Reject duplicates: ") << _rejectDuplicates << endl
<< _("Validity period format: ");
switch (_validityPeriodFormat)
{
case TimePeriod::NotPresent:
os << _("not present");
break;
case TimePeriod::Relative:
os << _("relative");
break;
case TimePeriod::Absolute:
os << _("absolute");
break;
default:
os << _("unknown");
break;
}
os << endl
<< _("Reply path: ") << _replyPath << endl
<< _("User data header indicator: ")
<< (_userDataHeader.length()!=0) << endl
<< _("Status report request: ") << _statusReportRequest << endl
<< _("Message reference: ") << (unsigned int)_messageReference << endl
<< _("Destination address: '") << _destinationAddress._number
<< "'" << endl
<< _("Protocol identifier: 0x") << hex
<< (unsigned int)_protocolIdentifier << dec << endl
<< _("Data coding scheme: ") << _dataCodingScheme.toString() << endl
<< _("Validity period: ") << _validityPeriod.toString() << endl
<< _("User data length: ") << (int)userDataLength() << endl
<< _("User data header: 0x") << bufToHex((unsigned char*)
((string)_userDataHeader).data(),
_userDataHeader.length())
<< endl
<< _("User data: '") << _userData << "'" << endl
<< dashes << endl << endl
<< ends;
char *ss = os.str();
string result(ss);
delete[] ss;
return result;
}
Address SMSSubmitMessage::address() const
{
return _destinationAddress;
}
Ref<SMSMessage> SMSSubmitMessage::clone()
{
Ref<SMSMessage> result = new SMSSubmitMessage(*this);
return result;
}
// SMSStatusReportMessage members
void SMSStatusReportMessage::init()
{
_messageTypeIndicator = SMS_STATUS_REPORT;
_moreMessagesToSend = false;
_statusReportQualifier = false;
_messageReference = 0;
_status = SMS_STATUS_RECEIVED;
}
SMSStatusReportMessage::SMSStatusReportMessage(string pdu) throw(GsmException)
{
SMSDecoder d(pdu);
_serviceCentreAddress = d.getAddress(true);
_messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
assert(_messageTypeIndicator == SMS_STATUS_REPORT);
_moreMessagesToSend = d.getBit(); // bit 2
d.getBit(); // bit 3
d.getBit(); // bit 4
_statusReportQualifier = d.getBit(); // bit 5
_messageReference = d.getOctet();
_recipientAddress = d.getAddress();
_serviceCentreTimestamp = d.getTimestamp();
_dischargeTime = d.getTimestamp();
_status = d.getOctet();
}
string SMSStatusReportMessage::encode()
{
SMSEncoder e;
e.setAddress(_serviceCentreAddress, true);
e.set2Bits(_messageTypeIndicator); // bits 0..1
e.setBit(_moreMessagesToSend); // bit 2
e.setBit(); // bit 3
e.setBit(); // bit 4
e.setBit(_statusReportQualifier); // bit 5
e.setOctet(_messageReference);
e.setAddress(_recipientAddress);
e.setTimestamp(_serviceCentreTimestamp);
e.setTimestamp(_dischargeTime);
e.setOctet(_status);
return e.getHexString();
}
string SMSStatusReportMessage::toString() const
{
ostrstream os;
os << dashes << endl
<< _("Message type: SMS-STATUS-REPORT") << endl
<< _("SC address: '") << _serviceCentreAddress._number << "'" << endl
<< _("More messages to send: ") << _moreMessagesToSend << endl
<< _("Status report qualifier: ") << _statusReportQualifier << endl
<< _("Message reference: ") << (unsigned int)_messageReference << endl
<< _("Recipient address: '") << _recipientAddress._number << "'" << endl
<< _("SC timestamp: ") << _serviceCentreTimestamp.toString() << endl
<< _("Discharge time: ") << _dischargeTime.toString() << endl
<< _("Status: 0x") << hex << (unsigned int)_status << dec
<< " '" << getSMSStatusString(_status) << "'" << endl
<< dashes << endl << endl
<< ends;
char *ss = os.str();
string result(ss);
delete[] ss;
return result;
}
Address SMSStatusReportMessage::address() const
{
return _recipientAddress;
}
Ref<SMSMessage> SMSStatusReportMessage::clone()
{
Ref<SMSMessage> result = new SMSStatusReportMessage(*this);
return result;
}
// SMSCommandMessage members
void SMSCommandMessage::init()
{
_messageTypeIndicator = SMS_COMMAND;
_messageReference = 0;
_statusReportRequest = true;
_protocolIdentifier = 0;
_commandType = EnquireSM;
_messageNumber = 0;
_commandDataLength = 0;
}
SMSCommandMessage::SMSCommandMessage(string pdu) throw(GsmException)
{
SMSDecoder d(pdu);
_serviceCentreAddress = d.getAddress(true);
_messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
assert(_messageTypeIndicator == SMS_COMMAND);
d.getBit(); // bit 2
d.getBit(); // bit 3
d.getBit(); // bit 4
_statusReportRequest = d.getBit(); // bit 5
_messageReference = d.getOctet();
_protocolIdentifier = d.getOctet();
_commandType = d.getOctet();
_messageNumber = d.getOctet();
_destinationAddress = d.getAddress();
_commandDataLength = d.getOctet();
unsigned char *s =
(unsigned char*)alloca(sizeof(unsigned char) * _commandDataLength);
d.getOctets(s, _commandDataLength);
}
string SMSCommandMessage::encode()
{
SMSEncoder e;
e.setAddress(_serviceCentreAddress, true);
e.set2Bits(_messageTypeIndicator); // bits 0..1
e.setBit(); // bit 2
e.setBit(); // bit 3
e.setBit(); // bit 4
e.setBit(_statusReportRequest); // bit 5
e.setOctet(_messageReference);
e.setOctet(_protocolIdentifier);
e.setOctet(_commandType);
e.setOctet(_messageNumber);
e.setAddress(_destinationAddress);
e.setOctet(_commandData.length());
e.setOctets((const unsigned char*)_commandData.data(),
(short unsigned int)_commandData.length());
return e.getHexString();
}
string SMSCommandMessage::toString() const
{
ostrstream os;
os << dashes << endl
<< _("Message type: SMS-COMMAND") << endl
<< _("SC address: '") << _serviceCentreAddress._number << "'" << endl
<< _("Message reference: ") << (unsigned int)_messageReference << endl
<< _("Status report request: ") << _statusReportRequest << endl
<< _("Protocol identifier: 0x") << hex
<< (unsigned int)_protocolIdentifier << dec << endl
<< _("Command type: 0x") << hex << (unsigned int)_commandType
<< dec << endl
<< _("Message number: ") << (unsigned int)_messageNumber << endl
<< _("Destination address: '") << _destinationAddress._number
<< "'" << endl
<< _("Command data length: ") << (unsigned int)_commandDataLength << endl
<< _("Command data: '") << _commandData << "'" << endl
<< dashes << endl << endl
<< ends;
char *ss = os.str();
string result(ss);
delete[] ss;
return result;
}
Address SMSCommandMessage::address() const
{
return _destinationAddress;
}
Ref<SMSMessage> SMSCommandMessage::clone()
{
Ref<SMSMessage> result = new SMSCommandMessage(*this);
return result;
}
// SMSDeliverReportMessage members
void SMSDeliverReportMessage::init()
{
_messageTypeIndicator = SMS_DELIVER_REPORT;
_protocolIdentifierPresent = false;
_dataCodingSchemePresent = false;
_userDataLengthPresent = false;
}
SMSDeliverReportMessage::SMSDeliverReportMessage(string pdu)
throw(GsmException)
{
SMSDecoder d(pdu);
_serviceCentreAddress = d.getAddress(true);
_messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
assert(_messageTypeIndicator == SMS_DELIVER_REPORT);
d.alignOctet(); // skip to parameter indicator
_protocolIdentifierPresent = d.getBit(); // bit 0
_dataCodingSchemePresent = d.getBit(); // bit 1
_userDataLengthPresent = d.getBit(); // bit 2
if (_protocolIdentifierPresent)
_protocolIdentifier = d.getOctet();
if (_dataCodingSchemePresent)
_dataCodingScheme = d.getOctet();
if (_userDataLengthPresent)
{
unsigned char userDataLength = d.getOctet();
d.markSeptet();
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
{
_userData = d.getString(userDataLength);
_userData = gsmToLatin1(_userData);
}
else
{ // userDataLength is length in octets
unsigned char *s =
(unsigned char*)alloca(sizeof(unsigned char) * userDataLength);
d.getOctets(s, userDataLength);
_userData.assign((char*)s, userDataLength);
}
}
}
string SMSDeliverReportMessage::encode()
{
SMSEncoder e;
e.setAddress(_serviceCentreAddress, true);
e.set2Bits(_messageTypeIndicator); // bits 0..1
e.alignOctet(); // skip to parameter indicator
e.setBit(_protocolIdentifierPresent); // bit 0
e.setBit(_dataCodingSchemePresent); // bit 1
e.setBit(_userDataLengthPresent); // bit 2
if (_protocolIdentifierPresent)
e.setOctet(_protocolIdentifier);
if (_dataCodingSchemePresent)
e.setOctet(_dataCodingScheme);
if (_userDataLengthPresent)
{
unsigned char userDataLength = _userData.length();
e.setOctet(userDataLength);
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
e.setString(latin1ToGsm(_userData));
else
e.setOctets((unsigned char*)_userData.data(), userDataLength);
}
return e.getHexString();
}
string SMSDeliverReportMessage::toString() const
{
ostrstream os;
os << dashes << endl
<< _("Message type: SMS-DELIVER-REPORT") << endl
<< _("SC address: '") << _serviceCentreAddress._number << "'" << endl
<< _("Protocol identifier present: ") << _protocolIdentifierPresent
<< endl
<< _("Data coding scheme present: ") << _dataCodingSchemePresent << endl
<< _("User data length present: ") << _userDataLengthPresent << endl;
if (_protocolIdentifierPresent)
os << _("Protocol identifier: 0x") << hex
<< (unsigned int)_protocolIdentifier
<< dec << endl;
if (_dataCodingSchemePresent)
os << _("Data coding scheme: ") << _dataCodingScheme.toString() << endl;
if (_userDataLengthPresent)
os << _("User data length: ") << (int)userDataLength() << endl
<< _("User data: '") << _userData << "'" << endl;
os << dashes << endl << endl
<< ends;
char *ss = os.str();
string result(ss);
delete[] ss;
return result;
}
Address SMSDeliverReportMessage::address() const
{
assert(0); // not address, should not be in SMS store
return Address();
}
Ref<SMSMessage> SMSDeliverReportMessage::clone()
{
Ref<SMSMessage> result = new SMSDeliverReportMessage(*this);
return result;
}
// SMSSubmitReportMessage members
void SMSSubmitReportMessage::init()
{
_messageTypeIndicator = SMS_SUBMIT_REPORT;
_protocolIdentifierPresent = false;
_dataCodingSchemePresent = false;
_userDataLengthPresent = false;
}
SMSSubmitReportMessage::SMSSubmitReportMessage(string pdu) throw(GsmException)
{
SMSDecoder d(pdu);
_serviceCentreAddress = d.getAddress(true);
_messageTypeIndicator = (MessageType)d.get2Bits(); // bits 0..1
assert(_messageTypeIndicator == SMS_SUBMIT_REPORT);
_serviceCentreTimestamp = d.getTimestamp();
_protocolIdentifierPresent = d.getBit(); // bit 0
_dataCodingSchemePresent = d.getBit(); // bit 1
_userDataLengthPresent = d.getBit(); // bit 2
if (_protocolIdentifierPresent)
_protocolIdentifier = d.getOctet();
if (_dataCodingSchemePresent)
_dataCodingScheme = d.getOctet();
if (_userDataLengthPresent)
{
unsigned char userDataLength = d.getOctet();
d.markSeptet();
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
{
_userData = d.getString(userDataLength);
_userData = gsmToLatin1(_userData);
}
else
{ // _userDataLength is length in octets
unsigned char *s =
(unsigned char*)alloca(sizeof(unsigned char) * userDataLength);
d.getOctets(s, userDataLength);
_userData.assign((char*)s, userDataLength);
}
}
}
string SMSSubmitReportMessage::encode()
{
SMSEncoder e;
e.setAddress(_serviceCentreAddress, true);
e.set2Bits(_messageTypeIndicator); // bits 0..1
e.setTimestamp(_serviceCentreTimestamp);
e.setBit(_protocolIdentifierPresent); // bit 0
e.setBit(_dataCodingSchemePresent); // bit 1
e.setBit(_userDataLengthPresent); // bit 2
if (_protocolIdentifierPresent)
e.setOctet(_protocolIdentifier);
if (_dataCodingSchemePresent)
e.setOctet(_dataCodingScheme);
if (_userDataLengthPresent)
{
e.setOctet(userDataLength());
if (_dataCodingScheme.getAlphabet() == DCS_DEFAULT_ALPHABET)
e.setString(latin1ToGsm(_userData));
else
e.setOctets((unsigned char*)_userData.data(), _userData.length());
}
return e.getHexString();
}
string SMSSubmitReportMessage::toString() const
{
ostrstream os;
os << dashes << endl
<< _("Message type: SMS-SUBMIT-REPORT") << endl
<< _("SC address: '") << _serviceCentreAddress._number << "'" << endl
<< _("SC timestamp: ") << _serviceCentreTimestamp.toString() << endl
<< _("Protocol identifier present: ") << _protocolIdentifierPresent
<< endl
<< _("Data coding scheme present: ") << _dataCodingSchemePresent << endl
<< _("User data length present: ") << _userDataLengthPresent << endl;
if (_protocolIdentifierPresent)
os << _("Protocol identifier: 0x") << hex
<< (unsigned int)_protocolIdentifier
<< dec << endl;
if (_dataCodingSchemePresent)
os << _("Data coding scheme: ") << _dataCodingScheme.toString() << endl;
if (_userDataLengthPresent)
os << _("User data length: ") << (int)userDataLength() << endl
<< _("User data: '") << _userData << "'" << endl;
os << dashes << endl << endl
<< ends;
char *ss = os.str();
string result(ss);
delete[] ss;
return result;
}
Address SMSSubmitReportMessage::address() const
{
assert(0); // not address, should not be in SMS store
return Address();
}
Ref<SMSMessage> SMSSubmitReportMessage::clone()
{
Ref<SMSMessage> result = new SMSSubmitReportMessage(*this);
return result;
}

View File

@ -0,0 +1,480 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_sms.h
// *
// * Purpose: SMS functions
// * (ETSI GSM 07.05)
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 16.5.1999
// *************************************************************************
#ifndef GSM_SMS_H
#define GSM_SMS_H
#include <gsmlib/gsm_sms_codec.h>
#include <gsmlib/gsm_error.h>
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_at.h>
#include <string>
#include <vector>
using namespace std;
namespace gsmlib
{
// forward declarations
class SMSStore;
class SMSMessage;
// this class represents a single SMS message
class SMSMessage : public RefBase
{
private:
Ref<GsmAt> _at; // connection to the device
public:
// possible values for message type indicator
enum MessageType {SMS_DELIVER = 0, SMS_DELIVER_REPORT = 0,
SMS_STATUS_REPORT = 2, SMS_COMMAND = 2,
SMS_SUBMIT = 1, SMS_SUBMIT_REPORT = 1};
protected:
// fields of the different TPDUs
// all PDUs
string _userData;
UserDataHeader _userDataHeader;
Address _serviceCentreAddress;
MessageType _messageTypeIndicator;// 2 bits
DataCodingScheme _dataCodingScheme;
public:
// decode hexadecimal pdu string
// return SMSMessage of the appropriate type
// differentiate between SMS transfer directions SC to ME, ME to SC
// also give GsmAt object for send()
static Ref<SMSMessage> decode(string pdu,
bool SCtoMEdirection = true,
GsmAt *at = NULL)
throw(GsmException);
static Ref<SMSMessage> decode(istream& s) throw(GsmException);
// encode pdu, return hexadecimal pdu string
virtual string encode() = 0;
// send this PDU
// returns message reference and ACK-PDU (if requested)
// only applicate to SMS-SUBMIT and SMS-COMMAND
unsigned char send(Ref<SMSMessage> &ackPdu) throw(GsmException);
// same as above, but ACK-PDU is discarded
unsigned char send() throw(GsmException);
// create textual representation of SMS
virtual string toString() const = 0;
// return deep copy of this message
virtual Ref<SMSMessage> clone() = 0;
// return length of SC address when encoded
unsigned int getSCAddressLen();
// accessor functions
MessageType messageType() const {return _messageTypeIndicator;}
Address serviceCentreAddress() const {return _serviceCentreAddress;}
// provided for sorting messages by timestamp
virtual Timestamp serviceCentreTimestamp() const {return Timestamp();}
// return recipient, destination etc. address (for sorting by address)
virtual Address address() const = 0;
virtual void setUserData(string x) {_userData = x;}
virtual string userData() const {return _userData;}
// return the size of user data (including user data header)
unsigned char userDataLength() const;
// accessor functions
virtual void setUserDataHeader(UserDataHeader x) {_userDataHeader = x;}
virtual UserDataHeader userDataHeader() const {return _userDataHeader;}
virtual DataCodingScheme dataCodingScheme() const
{return _dataCodingScheme;}
virtual void setDataCodingScheme(DataCodingScheme x)
{_dataCodingScheme = x;}
void setServiceCentreAddress(Address &x) {_serviceCentreAddress = x;}
void setAt(Ref<GsmAt> at) {_at = at;}
virtual ~SMSMessage();
// print ASCII hex representation of message
ostream& operator<<(ostream& s);
// copy constructor and assignment
// SMSMessage(SMSMessage &m);
// SMSMessage &operator=(SMSMessage &m);
friend class SMSStore;
};
// SMS-DELIVER TPDU
class SMSDeliverMessage : public SMSMessage
{
private:
// SMS-DELIVER PDU members (see GSM 03.40 section 9.2.2.1)
bool _moreMessagesToSend;
bool _replyPath;
bool _statusReportIndication;
Address _originatingAddress;
unsigned char _protocolIdentifier; // octet
Timestamp _serviceCentreTimestamp;
// initialize members to sensible values
void init();
public:
// constructor, sets sensible default values
SMSDeliverMessage();
// constructor with given pdu
SMSDeliverMessage(string pdu) throw(GsmException);
// encode pdu, return hexadecimal pdu string
virtual string encode();
// create textual representation of SMS
virtual string toString() const;
// inherited from SMSMessage
Address address() const;
Ref<SMSMessage> clone();
// accessor functions
bool moreMessagesToSend() const {return _moreMessagesToSend;}
bool replyPath() const {return _replyPath;}
bool statusReportIndication() const {return _statusReportIndication;}
Address originatingAddress() const {return _originatingAddress;}
unsigned char protocolIdentifier() const {return _protocolIdentifier;}
Timestamp serviceCentreTimestamp() const {return _serviceCentreTimestamp;}
void setMoreMessagesToSend(bool x) {_moreMessagesToSend = x;}
void setReplyPath(bool x) {_replyPath = x;}
void setStatusReportIndication(bool x) {_statusReportIndication = x;}
void setOriginatingAddress(Address &x) {_originatingAddress = x;}
void setProtocolIdentifier(unsigned char x) {_protocolIdentifier = x;}
void setServiceCentreTimestamp(Timestamp &x) {_serviceCentreTimestamp = x;}
virtual ~SMSDeliverMessage() {}
};
// SMS-SUBMIT TPDU
class SMSSubmitMessage : public SMSMessage
{
private:
// SMS-SUBMIT PDU (see GSM 03.40 section 9.2.2.2)
bool _rejectDuplicates;
TimePeriod::Format _validityPeriodFormat; // 2 bits
bool _replyPath;
bool _statusReportRequest;
unsigned char _messageReference; // integer
Address _destinationAddress;
unsigned char _protocolIdentifier;
TimePeriod _validityPeriod;
// initialize members to sensible values
void init();
public:
// constructor, sets sensible default values
SMSSubmitMessage();
// constructor with given pdu
SMSSubmitMessage(string pdu) throw(GsmException);
// convenience constructor
// given the text and recipient telephone number
SMSSubmitMessage(string text, string number);
// encode pdu, return hexadecimal pdu string
virtual string encode();
// create textual representation of SMS
virtual string toString() const;
// inherited from SMSMessage
Address address() const;
Ref<SMSMessage> clone();
// accessor functions
bool rejectDuplicates() const {return _rejectDuplicates;}
TimePeriod::Format validityPeriodFormat() const
{return _validityPeriodFormat;}
bool replyPath() const {return _replyPath;}
bool statusReportRequest() const {return _statusReportRequest;}
unsigned char messageReference() const {return _messageReference;}
Address destinationAddress() const {return _destinationAddress;}
unsigned char protocolIdentifier() const {return _protocolIdentifier;}
TimePeriod validityPeriod() const {return _validityPeriod;}
void setRejectDuplicates(bool x) {_rejectDuplicates = x;}
void setValidityPeriodFormat(TimePeriod::Format &x)
{_validityPeriodFormat = x;}
void setReplyPath(bool x) {_replyPath = x;}
void setStatusReportRequest(bool x) {_statusReportRequest = x;}
void setMessageReference(unsigned char x) {_messageReference = x;}
void setDestinationAddress(Address &x) {_destinationAddress = x;}
void setProtocolIdentifier(unsigned char x) {_protocolIdentifier = x;}
void setValidityPeriod(TimePeriod &x) {_validityPeriod = x;}
virtual ~SMSSubmitMessage() {}
};
// SMS-STATUS-REPORT TPDU
class SMSStatusReportMessage : public SMSMessage
{
private:
// SMS-STATUS-REPORT PDU (see GSM 03.40 section 9.2.2.3)
bool _moreMessagesToSend;
bool _statusReportQualifier;
unsigned char _messageReference;
Address _recipientAddress;
Timestamp _serviceCentreTimestamp;
Timestamp _dischargeTime;
unsigned char _status; // octet
// initialize members to sensible values
void init();
public:
// constructor, sets sensible default values
SMSStatusReportMessage() {init();}
// constructor with given pdu
SMSStatusReportMessage(string pdu) throw(GsmException);
// encode pdu, return hexadecimal pdu string
virtual string encode();
// create textual representation of SMS
virtual string toString() const;
// inherited from SMSMessage
Address address() const;
Ref<SMSMessage> clone();
// accessor functions
bool moreMessagesToSend() const {return _moreMessagesToSend;}
bool statusReportQualifier() const {return _statusReportQualifier;}
unsigned char messageReference() const {return _messageReference;}
Address recipientAddress() const {return _recipientAddress;}
Timestamp serviceCentreTimestamp() const {return _serviceCentreTimestamp;}
Timestamp dischargeTime() const {return _dischargeTime;}
unsigned char status() const {return _status;}
void setMoreMessagesToSend(bool x) {_moreMessagesToSend = x;}
void setStatusReportQualifier(bool x) {_statusReportQualifier = x;}
void setMessageReference(unsigned char x) {_messageReference = x;}
void setRecipientAddress(Address x) {_recipientAddress = x;}
void setServiceCentreTimestamp(Timestamp x) {_serviceCentreTimestamp = x;}
void setDischargeTime(Timestamp x) {_serviceCentreTimestamp = x;}
void setStatus(unsigned char x) {_status = x;}
virtual ~SMSStatusReportMessage() {}
};
// SMS-COMMAND TPDU
class SMSCommandMessage : public SMSMessage
{
public:
// command types, other values are reserved or SC-specific
enum CommandType {EnquireSM = 0, CancelStatusReportRequest = 1,
DeleteSubmittedSM = 2, EnalbeStatusReportRequest = 3};
private:
// SMS-COMMAND PDU (see GSM 03.40 section 9.2.2.4)
unsigned char _messageReference;
bool _statusReportRequest;
unsigned char _protocolIdentifier;
unsigned char _commandType;
unsigned char _messageNumber;
Address _destinationAddress;
unsigned char _commandDataLength;
string _commandData;
// initialize members to sensible values
void init();
public:
// constructor, sets sensible default values
SMSCommandMessage() {init();}
// constructor with given pdu
SMSCommandMessage(string pdu) throw(GsmException);
// encode pdu, return hexadecimal pdu string
virtual string encode();
// create textual representation of SMS
virtual string toString() const;
// inherited from SMSMessage
Address address() const;
Ref<SMSMessage> clone();
// accessor functions
unsigned char messageReference() const {return _messageReference;}
bool statusReportRequest() const {return _statusReportRequest;}
unsigned char protocolIdentifier() const {return _protocolIdentifier;}
unsigned char commandType() const {return _commandType;}
unsigned char messageNumber() const {return _messageNumber;}
Address destinationAddress() const {return _destinationAddress;}
unsigned char commandDataLength() const {return _commandDataLength;}
string commandData() const {return _commandData;}
void setMessageReference(unsigned char x) {_messageReference = x;}
void setStatusReportRequest(bool x) {_statusReportRequest = x;}
void setProtocolIdentifier(unsigned char x) {_protocolIdentifier = x;}
void setCommandType(unsigned char x) {_commandType = x;}
void setMessageNumber(unsigned char x) {_messageNumber = x;}
void setDestinationAddress(Address &x) {_destinationAddress = x;}
void setCommandDataLength(unsigned char x) {_commandDataLength = x;}
void setCommandData(string x) {_commandData = x;}
virtual ~SMSCommandMessage() {}
};
// SMS-DELIVER-REPORT TPDU for RP-ACK
class SMSDeliverReportMessage : public SMSMessage
{
private:
// SMS-DELIVER-REPORT PDU (see GSM 03.40 section 9.2.2.1a (II))
bool _protocolIdentifierPresent; // parameter indicator
bool _dataCodingSchemePresent;
bool _userDataLengthPresent;
unsigned char _protocolIdentifier;
// initialize members to sensible values
void init();
public:
// constructor, sets sensible default values
SMSDeliverReportMessage() {init();}
// constructor with given pdu
SMSDeliverReportMessage(string pdu) throw(GsmException);
// encode pdu, return hexadecimal pdu string
virtual string encode();
// create textual representation of SMS
virtual string toString() const;
// inherited from SMSMessage
Address address() const;
Ref<SMSMessage> clone();
// accessor functions
bool protocolIdentifierPresent() const {return _protocolIdentifierPresent;}
bool dataCodingSchemePresent() const {return _dataCodingSchemePresent;}
bool userDataLengthPresent() const {return _userDataLengthPresent;}
unsigned char protocolIdentifier() const
{assert(_protocolIdentifierPresent); return _protocolIdentifier;}
DataCodingScheme dataCodingScheme() const
{assert(_dataCodingSchemePresent); return _dataCodingScheme;}
UserDataHeader userDataHeader() const
{assert(_userDataLengthPresent); return _userDataHeader;}
string userData() const
{assert(_userDataLengthPresent); return _userData;}
void setProtocolIdentifier(unsigned char x)
{_protocolIdentifierPresent = true; _protocolIdentifier = x;}
void setDataCodingScheme(DataCodingScheme x)
{_dataCodingSchemePresent = true; _dataCodingScheme = x;}
void setUserDataHeader(UserDataHeader x)
{
_userDataLengthPresent = true;
_userDataHeader = x;
}
void setUserData(string x)
{
_userDataLengthPresent = true;
_userData = x;
}
virtual ~SMSDeliverReportMessage() {}
};
// SMS-SUBMIT-REPORT TPDU for RP-ACK
class SMSSubmitReportMessage : public SMSMessage
{
private:
// SMS-SUBMIT-REPORT PDU (see GSM 03.40 section 9.2.2.2a (II))
Timestamp _serviceCentreTimestamp;
bool _protocolIdentifierPresent; // parameter indicator
bool _dataCodingSchemePresent;
bool _userDataLengthPresent;
unsigned char _protocolIdentifier;
DataCodingScheme _dataCodingScheme;
// initialize members to sensible values
void init();
public:
// constructor, sets sensible default values
SMSSubmitReportMessage() {init();}
// constructor with given pdu
SMSSubmitReportMessage(string pdu) throw(GsmException);
// encode pdu, return hexadecimal pdu string
virtual string encode();
// create textual representation of SMS
virtual string toString() const;
// inherited from SMSMessage
Address address() const;
Ref<SMSMessage> clone();
// accessor functions
Timestamp serviceCentreTimestamp() const {return _serviceCentreTimestamp;}
bool protocolIdentifierPresent() const {return _protocolIdentifierPresent;}
bool dataCodingSchemePresent() const {return _dataCodingSchemePresent;}
bool userDataLengthPresent() const {return _userDataLengthPresent;}
unsigned char protocolIdentifier() const
{assert(_protocolIdentifierPresent); return _protocolIdentifier;}
DataCodingScheme dataCodingScheme() const
{assert(_dataCodingSchemePresent); return _dataCodingScheme;}
UserDataHeader userDataHeader() const
{assert(_userDataLengthPresent); return _userDataHeader;}
string userData() const
{assert(_userDataLengthPresent); return _userData;}
void setServiceCentreTimestamp(Timestamp &x) {_serviceCentreTimestamp = x;}
void setProtocolIdentifier(unsigned char x)
{_protocolIdentifierPresent = true; _protocolIdentifier = x;}
void setDataCodingScheme(DataCodingScheme x)
{_dataCodingSchemePresent = true; _dataCodingScheme = x;}
void setUserDataHeader(UserDataHeader x)
{
_userDataLengthPresent = true;
_userDataHeader = x;
}
void setUserData(string x)
{
_userDataLengthPresent = true;
_userData = x;
}
virtual ~SMSSubmitReportMessage() {}
};
// some useful typdefs
typedef Ref<SMSMessage> SMSMessageRef;
};
#endif // GSM_SMS_H

View File

@ -0,0 +1,702 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_sms_codec.cc
// *
// * Purpose: Coder and Encoder for SMS TPDUs
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 17.5.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_nls.h>
#include <gsmlib/gsm_sysdep.h>
#include <gsmlib/gsm_sms_codec.h>
#include <gsmlib/gsm_util.h>
#include <time.h>
#include <strstream>
#include <iomanip>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <climits>
#include <string>
using namespace std;
using namespace gsmlib;
// Address members
Address::Address(string number) : _plan(ISDN_Telephone)
{
number = removeWhiteSpace(number);
if (number.length() > 0 && number[0] == '+')
{
_type = International;
_number = number.substr(1, number.length() - 1);
}
else
{
_type = Unknown;
_number = number;
}
}
string Address::toString() const
{
if (_type == International)
return "+" + _number;
else
return _number;
}
bool gsmlib::operator<(const Address &x, const Address &y)
{
// normalize numbers according to the following two rules:
// - prepend "+" if international number
// - append 0s to the shorter number so that both numbers have equal length
string xnumber = x._number;
string ynumber = y._number;
static string twenty0s = "00000000000000000000";
if (x._type == Address::International) xnumber = "+" + xnumber;
if (y._type == Address::International) ynumber = "+" + ynumber;
while (xnumber.length() != ynumber.length())
if (xnumber.length() < ynumber.length())
{
int diff = ynumber.length() - xnumber.length();
xnumber += twenty0s.substr(0, (diff > 20 ? 20 : diff));
}
else
{
int diff = xnumber.length() - ynumber.length();
ynumber += twenty0s.substr(0, (diff > 20 ? 20 : diff));
}
return xnumber < ynumber;
}
bool gsmlib::operator==(const Address &x, const Address &y)
{
return x._number == y._number && x._plan == y._plan;
}
// Timestamp members
bool Timestamp::empty() const
{
return _year == 0 && _month == 0 && _day == 0 && _hour == 0 &&
_minute == 0 && _seconds == 0 && _timeZoneMinutes == 0;
}
string Timestamp::toString(bool appendTimeZone) const
{
short timeZoneMinutes = _timeZoneMinutes;
short timeZoneHours = timeZoneMinutes / 60;
timeZoneMinutes %= 60;
// format date and time in a locale-specific way
struct tm t;
t.tm_sec = _seconds;
t.tm_min = _minute;
t.tm_hour = _hour;
t.tm_mon = _month - 1;
// year 2000 heuristics, SMSs cannot be older than start of GSM network
t.tm_year = _year < 80 ? _year + 100 : _year;
t.tm_mday = _day;
t.tm_isdst = -1;
t.tm_yday = 0;
t.tm_wday = 0;
#ifdef BROKEN_STRFTIME
char formattedTime[1024];
strftime(formattedTime, 1024, "%x %X", &t);
#else
int formattedTimeSize = strftime(NULL, INT_MAX, "%x %X", &t) + 1;
char *formattedTime = (char*)alloca(sizeof(char) * formattedTimeSize);
strftime(formattedTime, formattedTimeSize, "%x %X", &t);
#endif
if (! appendTimeZone)
return formattedTime;
ostrstream os;
os << formattedTime << " (" << (_negativeTimeZone ? '-' : '+')
<< setfill('0') << setw(2) << timeZoneHours
<< setw(2) << timeZoneMinutes << ')' << ends;
char *ss = os.str();
string result(ss);
delete[] ss;
return result;
}
bool gsmlib::operator<(const Timestamp &x, const Timestamp &y)
{
// we don't take time zone info into account because
// - it's more complicated to compute
// - it might confuse the user for whom it's also too complicated
if (x._year < y._year)
return true;
else if (x._year > y._year)
return false;
if (x._month < y._month)
return true;
else if (x._month > y._month)
return false;
if (x._day < y._day)
return true;
else if (x._day > y._day)
return false;
if (x._hour < y._hour)
return true;
else if (x._hour > y._hour)
return false;
if (x._minute < y._minute)
return true;
else if (x._minute > y._minute)
return false;
return x._seconds < y._seconds;
}
bool gsmlib::operator==(const Timestamp &x, const Timestamp &y)
{
// we don't take time zone info in order to be consistent with operator<
return x._year == y._year && x._month == y._month && x._day == y._day &&
x._hour == y._hour && x._minute == y._minute && x._seconds == y._seconds;
}
// TimePeriod members
string TimePeriod::toString() const
{
switch (_format)
{
case NotPresent:
return _("not present");
case Relative:
{
ostrstream os;
if (_relativeTime <= 143)
os << ((int)_relativeTime + 1) * 5 << _(" minutes");
else if (_relativeTime <= 167)
os << 12 * 60 + ((int)_relativeTime - 143) * 30 << _(" minutes");
else if (_relativeTime <= 196)
os << (int)_relativeTime - 166 << _(" days");
else if (_relativeTime <= 143)
os << (int)_relativeTime - 192 << _(" weeks");
os << ends;
char *ss = os.str();
string result(ss);
delete[] ss;
return result;
}
case Absolute:
return _absoluteTime.toString();
default:
return _("unknown");
}
}
// DataCodingScheme members
string DataCodingScheme::toString() const
{
string result;
if (compressed()) result += _("compressed ");
if (messageWaitingIndication())
switch (getMessageWaitingType())
{
case DCS_VOICEMAIL_MESSAGE_WAITING:
result += _("voicemail message waiting");
break;
case DCS_FAX_MESSAGE_WAITING:
result += _("fax message waiting");
break;
case DCS_ELECTRONIC_MAIL_MESSAGE_WAITING:
result += _("electronic mail message waiting");
break;
case DCS_OTHER_MESSAGE_WAITING:
result += _("other message waiting");
break;
}
else
switch (getAlphabet())
{
case DCS_DEFAULT_ALPHABET:
result += _("default alphabet");
break;
case DCS_EIGHT_BIT_ALPHABET:
result += _("8-bit alphabet");
break;
case DCS_SIXTEEN_BIT_ALPHABET:
result += _("16-bit alphabet");
break;
case DCS_RESERVED_ALPHABET:
result += _("reserved alphabet");
break;
}
return result;
}
// SMSDecoder members
SMSDecoder::SMSDecoder(string pdu) : _bi(0), _septetStart(NULL)
{
_p = new unsigned char[pdu.length() / 2];
_op = _p;
if (! hexToBuf(pdu, _p))
throw GsmException(_("bad hexadecimal PDU format"), SMSFormatError);
_maxop = _op + pdu.length() / 2;
}
void SMSDecoder::alignOctet()
{
if (_bi != 0)
{
_bi = 0;
++_op;
}
}
void SMSDecoder::alignSeptet()
{
assert(_septetStart != NULL);
while (((_op - _septetStart) * 8 + _bi) % 7 != 0) getBit();
}
unsigned char SMSDecoder::get2Bits()
{
unsigned char result = getBit();
return result | (getBit() << 1);
}
unsigned char SMSDecoder::getOctet()
{
alignOctet();
if (_op >= _maxop)
throw GsmException(_("premature end of PDU"), SMSFormatError);
return *_op++;
}
void SMSDecoder::getOctets(unsigned char* octets, unsigned short length)
{
alignOctet();
for (unsigned short i = 0; i < length; ++i)
{
if (_op >= _maxop)
throw GsmException(_("premature end of PDU"), SMSFormatError);
*octets++ = *_op++;
}
}
string SMSDecoder::getSemiOctets(unsigned short length)
{
string result;
result.reserve(length);
alignOctet();
for (unsigned short i = 0; i < length; ++i)
{
if (_bi == 0)
{
if (_op >= _maxop)
throw GsmException(_("premature end of PDU"), SMSFormatError);
// bits 0..3 are most significant
result += '0' + (*_op & 0xf);
_bi = 4;
}
else
{
if (_op >= _maxop)
throw GsmException(_("premature end of PDU"), SMSFormatError);
// bits 4..7 are least significant, skip 0xf digit
if ((*_op & 0xf0) != 0xf0)
result += '0' + (*_op >> 4);
_bi = 0;
++_op;
}
}
alignOctet();
return result;
}
unsigned long SMSDecoder::getSemiOctetsInteger(unsigned short length)
{
unsigned long result = 0;
alignOctet();
for (unsigned short i = 0; i < length; ++i)
{
if (_bi == 0)
{
if (_op >= _maxop)
throw GsmException(_("premature end of PDU"), SMSFormatError);
// bits 0..3 are most significant
result = result * 10 + (*_op & 0xf);
_bi = 4;
}
else
{
if (_op >= _maxop)
throw GsmException(_("premature end of PDU"), SMSFormatError);
// bits 4..7 are least significant, skip 0xf digit
if ((*_op & 0xf0) != 0xf0)
result = result * 10 + (*_op >> 4);
_bi = 0;
++_op;
}
}
alignOctet();
return result;
}
unsigned long SMSDecoder::getTimeZone(bool &negativeTimeZone)
{
unsigned long result = 0;
alignOctet();
for (unsigned short i = 0; i < 2; ++i)
{
if (_bi == 0)
{
if (_op >= _maxop)
throw GsmException(_("premature end of PDU"), SMSFormatError);
// bits 0..3 are most significant
if (i == 0)
{ // get sign
result = result * 10 + (*_op & 0x7);
negativeTimeZone = (*_op & 0x8 == 0);
}
else
result = result * 10 + (*_op & 0xf);
_bi = 4;
}
else
{
if (_op >= _maxop)
throw GsmException(_("premature end of PDU"), SMSFormatError);
// bits 4..7 are least significant
result = result * 10 + (*_op >> 4);
_bi = 0;
++_op;
}
}
alignOctet();
return result * 15; // compute minutes
}
unsigned long SMSDecoder::getInteger(unsigned short length)
{
unsigned long result = 0;
for (unsigned short i = 0; i < length; ++i)
result |= (getBit() << i);
return result;
}
string SMSDecoder::getString(unsigned short length)
{
string result;
alignSeptet();
for (unsigned short i = 0; i < length; ++i)
{
unsigned char c = 0;
for (unsigned short j = 0; j < 7; ++j)
c |= getBit() << j;
result += c;
}
return result;
}
Address SMSDecoder::getAddress(bool scAddressFormat)
{
Address result;
alignOctet();
unsigned char addressLength = getOctet();
if (addressLength == 0 && scAddressFormat)
return result; // special case for SUBMIT-PDUs
// parse Type-of-Address
result._plan = (Address::NumberingPlan)getInteger(4);
result._type = (Address::Type)getInteger(3);
// get address
if (result._type == Address::Alphanumeric)
{
markSeptet();
// addressLength is number of semi-octets
// (addressLength / 2) * 8 is number of available bits
// divided by 7 is number of 7-bit characters
result._number = gsmToLatin1(getString(addressLength * 4 / 7));
alignOctet();
}
else
result._number = getSemiOctets(scAddressFormat ?
(addressLength - 1) * 2 : addressLength);
return result;
}
Timestamp SMSDecoder::getTimestamp()
{
Timestamp result;
result._year = getSemiOctetsInteger(2);
result._month = getSemiOctetsInteger(2);
result._day = getSemiOctetsInteger(2);
result._hour = getSemiOctetsInteger(2);
result._minute = getSemiOctetsInteger(2);
result._seconds = getSemiOctetsInteger(2);
result._timeZoneMinutes = getTimeZone(result._negativeTimeZone);
return result;
}
TimePeriod SMSDecoder::getTimePeriod(TimePeriod::Format format)
{
TimePeriod result;
result._format = format;
switch (format)
{
case TimePeriod::NotPresent:
break;
case TimePeriod::Relative:
result._relativeTime = getOctet();
break;
case TimePeriod::Absolute:
result._absoluteTime = getTimestamp();
break;
default:
throw GsmException(_("unknown time period format"), SMSFormatError);
break;
}
return result;
}
SMSDecoder::~SMSDecoder()
{
delete _p;
}
// SMSEncoder members
SMSEncoder::SMSEncoder() : _bi(0), _op(_p)
{
memset((void*)_p, 0, sizeof(_p));
}
void SMSEncoder::alignOctet()
{
if (_bi != 0)
{
_bi = 0;
++_op;
}
}
void SMSEncoder::alignSeptet()
{
while (((_op - _septetStart) * 8 + _bi) % 7 != 0) setBit();
}
void SMSEncoder::set2Bits(unsigned char twoBits)
{
setBit(twoBits & 1);
setBit((twoBits & 2) == 2);
}
void SMSEncoder::setOctet(unsigned char octet)
{
alignOctet();
*_op++ = octet;
}
void SMSEncoder::setOctets(const unsigned char* octets, unsigned short length)
{
alignOctet();
for (unsigned short i = 0; i < length; ++i)
*_op++ = octets[i];
}
void SMSEncoder::setSemiOctets(string semiOctets)
{
alignOctet();
for (unsigned int i = 0; i < semiOctets.length(); ++i)
{
if (_bi == 0)
{
*_op = semiOctets[i] - '0';
_bi = 4;
}
else
{
*_op++ |= (semiOctets[i] - '0') << 4;
_bi = 0;
}
}
if (_bi == 4)
*_op++ |= 0xf0;
_bi = 0;
}
void SMSEncoder::setSemiOctetsInteger(unsigned long intValue,
unsigned short length)
{
ostrstream os;
os << intValue << ends;
char *ss = os.str();
string s(ss);
delete[] ss;
assert(s.length() <= length);
while (s.length() < length) s = '0' + s;
setSemiOctets(s);
}
void SMSEncoder::setTimeZone(bool negativeTimeZone, unsigned long timeZone)
{
setSemiOctetsInteger(timeZone / 15, 2);
if (!negativeTimeZone)
*(_op - 1) |= 8;
}
void SMSEncoder::setInteger(unsigned long intvalue, unsigned short length)
{
for (unsigned short i = 0; i < length; ++i)
setBit((intvalue & (1 << i)) != 0);
}
void SMSEncoder::setString(string stringValue)
{
alignSeptet();
for (unsigned int i = 0; i < stringValue.length(); ++i)
{
unsigned char c = stringValue[i];
for (unsigned short j = 0; j < 7; ++j)
setBit(((1 << j) & c) != 0);
}
}
void SMSEncoder::setAddress(Address &address, bool scAddressFormat)
{
alignOctet();
if (scAddressFormat)
{
unsigned int numberLen = address._number.length();
if (numberLen == 0)
{
setOctet(0); // special case: use default SC address
return; // (set by +CSCA=)
}
setOctet(numberLen / 2 + numberLen % 2 + 1);
// not supported for SCA format
assert(address._type != Address::Alphanumeric);
}
else
if (address._type == Address::Alphanumeric)
// address in GSM default encoding, see also comment in getAddress()
setOctet((address._number.length() * 7 + 6) / 8 * 2);
else
setOctet(address._number.length());
setInteger(address._plan, 4);
setInteger(address._type, 3);
setBit(1);
if (address._number.length() > 0)
if (address._type == Address::Alphanumeric)
{
markSeptet();
setString(latin1ToGsm(address._number));
}
else
setSemiOctets(address._number);
alignOctet();
}
void SMSEncoder::setTimestamp(Timestamp timestamp)
{
setSemiOctetsInteger(timestamp._year, 2);
setSemiOctetsInteger(timestamp._month, 2);
setSemiOctetsInteger(timestamp._day, 2);
setSemiOctetsInteger(timestamp._hour, 2);
setSemiOctetsInteger(timestamp._minute, 2);
setSemiOctetsInteger(timestamp._seconds, 2);
setTimeZone(timestamp._negativeTimeZone, timestamp._timeZoneMinutes);
}
void SMSEncoder::setTimePeriod(TimePeriod period)
{
switch (period._format)
{
case TimePeriod::NotPresent:
break;
case TimePeriod::Relative:
setOctet(period._relativeTime);
break;
case TimePeriod::Absolute:
setTimestamp(period._absoluteTime);
break;
default:
assert(0);
break;
}
}
string SMSEncoder::getHexString()
{
short bi = _bi;
unsigned char *op = _op;
alignOctet();
string result = bufToHex(_p, _op - _p);
_bi = bi;
_op = op;
return result;
}
unsigned int SMSEncoder::getLength()
{
short bi = _bi;
unsigned char *op = _op;
alignOctet();
unsigned int result = _op - _p;
_bi = bi;
_op = op;
return result;
}
// UserDataHeader members
void UserDataHeader::encode(SMSEncoder &e)
{
e.setOctet(_udh.length());
e.setOctets((unsigned char*)_udh.data(), _udh.length());
}
void UserDataHeader::decode(SMSDecoder &d)
{
unsigned char udhLen = d.getOctet();
unsigned char *s =
(unsigned char*)alloca(sizeof(unsigned char) * udhLen);
d.getOctets(s, udhLen);
string ss((char*)s, (unsigned int)udhLen);
_udh = ss;
}
string UserDataHeader::getIE(unsigned char id)
{
int udhl, pos = 0;
udhl = _udh.length();
while (pos < udhl)
{
unsigned char iei = _udh[pos++];
unsigned char ieidl = _udh[pos++];
if (iei == id) return _udh.substr(pos, ieidl);
pos += ieidl;
}
return "";
}

View File

@ -0,0 +1,329 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_sms_codec.h
// *
// * Purpose: Coder and Encoder for SMS TPDUs
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 16.5.1999
// *************************************************************************
#ifndef GSM_SMS_CODEC_H
#define GSM_SMS_CODEC_H
#include <string>
#include <assert.h>
using namespace std;
namespace gsmlib
{
// this struct represents a telephone number
// usually _type == Unknown or International
// and _number == ISDN_Telephone
struct Address
{
enum Type {Unknown = 0, International = 1, National = 2,
NetworkSpecific = 3, Subscriber = 4,
Alphanumeric = 5, Abbreviated = 6, Reserved = 7};
enum NumberingPlan {UnknownPlan = 0, ISDN_Telephone = 1,
Data = 3, Telex = 4, NationalPlan = 8,
PrivatePlan = 9, Ermes = 10, ReservedPlan = 15};
Type _type;
NumberingPlan _plan;
string _number;
Address() : _type(Unknown), _plan(UnknownPlan) {}
// the constructor sets _type and _plan to defaults
// _plan == ISDN_Telephone
// _type == International if number starts with "+"
// _type == unknown otherwise
// number must be of the form "+123456" or "123456"
Address(string number);
// return string representation
string toString() const;
friend bool operator<(const Address &x, const Address &y);
friend bool operator==(const Address &x, const Address &y);
};
// compare two addresses
extern bool operator<(const Address &x, const Address &y);
extern bool operator==(const Address &x, const Address &y);
// representation of a SMS timestamp
struct Timestamp
{
short _year, _month, _day, _hour, _minute, _seconds, _timeZoneMinutes;
bool _negativeTimeZone;
Timestamp() : _year(0), _month(0), _day(0), _hour(0),
_minute(0), _seconds(0), _timeZoneMinutes(0), _negativeTimeZone(false) {}
// return true if the time stamp is empty (ie. contains only zeroes)
bool empty() const;
// return string representation
string toString(bool appendTimeZone = true) const;
friend bool operator<(const Timestamp &x, const Timestamp &y);
friend bool operator==(const Timestamp &x, const Timestamp &y);
};
// compare two timestamps
extern bool operator<(const Timestamp &x, const Timestamp &y);
extern bool operator==(const Timestamp &x, const Timestamp &y);
// representation of time period
struct TimePeriod
{
// possible values for validity period format
enum Format {NotPresent = 0, Relative = 2, Absolute = 3};
Format _format;
Timestamp _absoluteTime;
unsigned char _relativeTime;
TimePeriod() : _format(NotPresent), _relativeTime(0) {}
// return string representation (already translated)
string toString() const;
};
// representation of DataCodingScheme
// the data coding scheme is described in detail in ETSI GSM 03.38, section 4
const unsigned char DCS_COMPRESSED = 0x20; // bit 5
const unsigned char DCS_DEFAULT_ALPHABET = 0 << 2; // bit 2..3 == 0
const unsigned char DCS_EIGHT_BIT_ALPHABET = 1 << 2; // bit 2..3 == 01
const unsigned char DCS_SIXTEEN_BIT_ALPHABET = 2 << 2; // bit 2..3 == 10
const unsigned char DCS_RESERVED_ALPHABET = 3 << 2; // bit 2..3 == 11
const unsigned char DCS_MESSAGE_WAITING_INDICATION = 0xc0; // bit 7..6 == 11
const unsigned char DCS_VOICEMAIL_MESSAGE_WAITING = 0;
const unsigned char DCS_FAX_MESSAGE_WAITING = 1;
const unsigned char DCS_ELECTRONIC_MAIL_MESSAGE_WAITING = 2;
const unsigned char DCS_OTHER_MESSAGE_WAITING = 3;
class DataCodingScheme
{
private:
unsigned char _dcs;
public:
// initialize with data coding scheme octet
DataCodingScheme(unsigned char dcs) : _dcs(dcs) {}
// set to default values (no message waiting, no message class indication,
// default 7-bit alphabet)
DataCodingScheme() : _dcs(DCS_DEFAULT_ALPHABET) {}
// return type of alphabet used (if messageWaitingIndication == false)
unsigned char getAlphabet() const {return _dcs & (3 << 2);}
// return true if message compressed
// (if messageWaitingIndication == false)
bool compressed() const {return _dcs & DCS_COMPRESSED == DCS_COMPRESSED;}
// return true if message waiting indication
bool messageWaitingIndication() const
{return _dcs & DCS_MESSAGE_WAITING_INDICATION ==
DCS_MESSAGE_WAITING_INDICATION;}
// return type of waiting message (if messageWaitingIndication == true)
unsigned char getMessageWaitingType() const {return _dcs & 3;}
// return string representation (already translated)
string toString() const;
operator unsigned char() const {return _dcs;}
};
// utility class facilitate SMS TPDU decoding
class SMSDecoder
{
private:
unsigned char *_p; // buffer to hold pdu
short _bi; // bit index (0..7)
unsigned char *_op; // current octet pointer
unsigned char *_septetStart; // start of septet string
unsigned char *_maxop; // pointer to last byte after _p
public:
// initialize with a hexadecimal octet string containing SMS TPDU
SMSDecoder(string pdu);
// align to octet border
void alignOctet();
// remember starting point of septets (important for alignSeptet())
void markSeptet() {alignOctet(); _septetStart = _op;}
// align to septet border
void alignSeptet();
// get single bit
bool getBit()
{
assert(_op < _maxop);
bool result = ((*_op >> _bi) & 1);
if (_bi == 7)
{
_bi = 0;
++_op;
}
else
++_bi;
return result;
}
// get two bits
unsigned char get2Bits();
// get one octet
unsigned char getOctet();
// get string of octets of specified length
void getOctets(unsigned char* octets, unsigned short length);
// get length semi-octets (bcd-coded number) as ASCII string of numbers
string getSemiOctets(unsigned short length);
// get length semi-octets (bcd-coded number) as integer
unsigned long getSemiOctetsInteger(unsigned short length);
// get time zone (in minutes) and time zone sign
unsigned long getTimeZone(bool &negativeTimeZone);
// get integer with length number of bits
unsigned long getInteger(unsigned short length);
// get length number of alphanumeric 7-bit characters
// markSeptet() must be called before this function
string getString(unsigned short length);
// get address/telephone number
// service centre address has special format
Address getAddress(bool scAddressFormat = false);
// get Timestamp
Timestamp getTimestamp();
// get TimePeriod of given format
TimePeriod getTimePeriod(TimePeriod::Format format);
// destructor
~SMSDecoder();
};
// utility class for SMS TPDU encoding
class SMSEncoder
{
private:
unsigned char _p[2000]; // buffer to hold pdu (2000 should be enough)
short _bi; // bit index (0..7)
unsigned char *_op; // current octet pointer
unsigned char *_septetStart; // start of septet string
public:
// constructor
SMSEncoder();
// align to octet border
void alignOctet();
// remember starting point of septets (important for alignSeptet())
void markSeptet() {alignOctet(); _septetStart = _op;}
// align to septet border
void alignSeptet();
// set single bit
void setBit(bool bit = false)
{
if (bit)
*_op |= (1 << _bi);
if (_bi == 7)
{
_bi = 0;
++_op;
}
else
++_bi;
}
// set two bits
void set2Bits(unsigned char twoBits);
// set one octet
void setOctet(unsigned char octet);
// set string of octets of specified length
void setOctets(const unsigned char* octets, unsigned short length);
// set semi-octets semiOctets (given as ASCII string of numbers)
void setSemiOctets(string semiOctets);
// set semi-octets (given as integer)
void setSemiOctetsInteger(unsigned long intValue, unsigned short length);
// set time zone (in minutes) and time zone sign
void setTimeZone(bool negativeTimeZone, unsigned long timeZone);
// set integer with length number of bits
void setInteger(unsigned long intvalue, unsigned short length);
// set alphanumeric 7-bit characters
void setString(string stringValue);
// set address/telephone number
// service centre address has special format
void setAddress(Address &address, bool scAddressFormat = false);
// set Timestamp
void setTimestamp(Timestamp timestamp);
// set TimePeriod
void setTimePeriod(TimePeriod period);
// return constructed TPDU as hex-encoded string
string getHexString();
// return current length of TPDU
unsigned int getLength();
};
// class to handle user data header
class UserDataHeader
{
private:
string _udh;
public:
// empty user data header
UserDataHeader() {}
// initialize with user data header
UserDataHeader (string udh) : _udh(udh) {}
// encode header
void encode(SMSEncoder &e);
// decode header
void decode(SMSDecoder &d);
// return a given information element, if present, or an empty string
string getIE(unsigned char id);
// return the size of the header
unsigned int length() const {return _udh.length();}
// return user data header as octet string
operator string() const {return _udh;}
};
};
#endif // GSM_SMS_CODEC_H

View File

@ -0,0 +1,489 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_sms_store.cc
// *
// * Purpose: SMS functions, SMS store
// * (ETSI GSM 07.05)
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 20.5.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_sms_store.h>
#include <gsmlib/gsm_parser.h>
#include <gsmlib/gsm_me_ta.h>
#include <iostream>
using namespace std;
using namespace gsmlib;
// SMSStoreEntry members
SMSStoreEntry::SMSStoreEntry() :
_status(Unknown), _cached(false), _mySMSStore(NULL), _index(0)
{
}
SMSMessageRef SMSStoreEntry::message() const throw(GsmException)
{
if (! cached())
{
assert(_mySMSStore != NULL);
// these operations are at least "logically const"
SMSStoreEntry *thisEntry = const_cast<SMSStoreEntry*>(this);
_mySMSStore->readEntry(_index, thisEntry->_message, thisEntry->_status);
thisEntry->_cached = true;
}
return _message;
}
CBMessageRef SMSStoreEntry::cbMessage() const throw(GsmException)
{
assert(_mySMSStore != NULL);
// these operations are at least "logically const"
SMSStoreEntry *thisEntry = const_cast<SMSStoreEntry*>(this);
// don't cache CB message for now
thisEntry->_cached = false;
CBMessageRef result;
_mySMSStore->readEntry(_index, result);
return result;
}
SMSStoreEntry::SMSMemoryStatus SMSStoreEntry::status() const
throw(GsmException)
{
if (! cached())
{
assert(_mySMSStore != NULL);
// these operations are at least "logically const"
SMSStoreEntry *thisEntry = const_cast<SMSStoreEntry*>(this);
_mySMSStore->readEntry(_index, thisEntry->_message, thisEntry->_status);
thisEntry->_cached = true;
}
return _status;
}
bool SMSStoreEntry::empty() const throw(GsmException)
{
return message().isnull();
}
unsigned char SMSStoreEntry::send(Ref<SMSMessage> &ackPdu)
throw(GsmException)
{
return _mySMSStore->send(_index, ackPdu);
}
unsigned char SMSStoreEntry::send() throw(GsmException)
{
SMSMessageRef mref;
return send(mref);
}
bool SMSStoreEntry::cached() const
{
if (_mySMSStore == NULL)
return _cached;
else
return _cached && _mySMSStore->_useCache;
}
Ref<SMSStoreEntry> SMSStoreEntry::clone()
{
Ref<SMSStoreEntry> result = new SMSStoreEntry(_message->clone());
result->_status = _status;
result->_index = _index;
return result;
}
bool SMSStoreEntry::operator==(const SMSStoreEntry &e) const
{
if (_message.isnull() || e._message.isnull())
return _message.isnull() && e._message.isnull();
else
return _message->encode() == e._message->encode();
}
SMSStoreEntry::SMSStoreEntry(const SMSStoreEntry &e)
{
_message = e._message;
_status = e._status;
_cached = e._cached;
_mySMSStore = e._mySMSStore;
_index = e._index;
}
SMSStoreEntry &SMSStoreEntry::operator=(const SMSStoreEntry &e)
{
_message = e._message;
_status = e._status;
_cached = e._cached;
_mySMSStore = e._mySMSStore;
_index = e._index;
return *this;
}
// iterator members
SMSStoreEntry &SMSStoreIterator::operator*()
{
return (*_store)[_index];
}
SMSStoreEntry *SMSStoreIterator::operator->()
{
return &(*_store)[_index];
}
SMSStoreIterator::operator SMSStoreEntry*()
{
return &(*_store)[_index];
}
SMSStoreIterator &SMSStoreIterator::operator=(const SMSStoreIterator &i)
{
_index = i._index;
_store = i._store;
return *this;
}
const SMSStoreEntry &SMSStoreConstIterator::operator*()
{
return (*_store)[_index];
}
const SMSStoreEntry *SMSStoreConstIterator::operator->()
{
return &(*_store)[_index];
}
// SMSStore members
void SMSStore::readEntry(int index, SMSMessageRef &message,
SMSStoreEntry::SMSMemoryStatus &status)
throw(GsmException)
{
// select SMS store
_meTa.setSMSStore(_storeName, 1);
#ifndef NDEBUG
if (debugLevel() >= 1)
cerr << "*** Reading SMS entry " << index << endl;
#endif // NDEBUG
string pdu;
Ref<Parser> p;
try
{
p = new Parser(_at->chat("+CMGR=" + intToStr(index + 1), "+CMGR:",
pdu, false, true, true));
}
catch (GsmException &ge)
{
if (ge.getErrorCode() != SMS_INVALID_MEMORY_INDEX)
throw ge;
else
{
message = SMSMessageRef();
status = SMSStoreEntry::Unknown;
return;
}
}
if (pdu.length() == 0)
{
message = SMSMessageRef();
status = SMSStoreEntry::Unknown;
}
else
{
// add missing service centre address if required by ME
if (! _at->getMeTa().getCapabilities()._hasSMSSCAprefix)
pdu = "00" + pdu;
status = (SMSStoreEntry::SMSMemoryStatus)p->parseInt();
// ignore the rest of the line
message = SMSMessageRef(
SMSMessage::decode(pdu,
!(status == SMSStoreEntry::StoredUnsent ||
status == SMSStoreEntry::StoredSent),
_at.getptr()));
}
}
void SMSStore::readEntry(int index, CBMessageRef &message)
throw(GsmException)
{
// select SMS store
_meTa.setSMSStore(_storeName, 1);
#ifndef NDEBUG
if (debugLevel() >= 1)
cerr << "*** Reading CB entry " << index << endl;
#endif // NDEBUG
string pdu;
Ref<Parser> p;
try
{
// this is just one row splitted in two part
// (msvc6 fail with internal compiler error)
string s = _at->chat("+CMGR=" + intToStr(index + 1), "+CMGR:",
pdu, false, true, true);
p = new Parser(s);
}
catch (GsmException &ge)
{
if (ge.getErrorCode() != SMS_INVALID_MEMORY_INDEX)
throw ge;
else
{
message = CBMessageRef();
return;
}
}
if (pdu.length() == 0)
message = CBMessageRef();
else
message = CBMessageRef(new CBMessage(pdu));
}
void SMSStore::writeEntry(int &index, SMSMessageRef message)
throw(GsmException)
{
// select SMS store
_meTa.setSMSStore(_storeName, 2);
#ifndef NDEBUG
if (debugLevel() >= 1)
cerr << "*** Writing SMS entry " << index << endl;
#endif
// compute length of pdu
string pdu = message->encode();
// set message status to "RECEIVED READ" for SMS_DELIVER, SMS_STATUS_REPORT
string statusString;
// Normally the ",1" sets the message status to "REC READ" (received read)
// which is appropriate for all non-submit messages
// Motorola Timeport 260 does not like this code, though
// DELIVER messages are magically recognized anyway
if (message->messageType() != SMSMessage::SMS_SUBMIT &&
! _at->getMeTa().getCapabilities()._wrongSMSStatusCode)
statusString = ",1";
Parser p(_at->sendPdu("+CMGW=" +
intToStr(pdu.length() / 2 -
message->getSCAddressLen()) + statusString,
"+CMGW:", pdu));
index = p.parseInt() - 1;
}
void SMSStore::eraseEntry(int index) throw(GsmException)
{
// Select SMS store
_meTa.setSMSStore(_storeName, 1);
#ifndef NDEBUG
if (debugLevel() >= 1)
cerr << "*** Erasing SMS entry " << index << endl;
#endif
_at->chat("+CMGD=" + intToStr(index + 1));
}
unsigned char SMSStore::send(int index, Ref<SMSMessage> &ackPdu)
throw(GsmException)
{
Parser p(_at->chat("+CMSS=" + intToStr(index + 1), "+CMSS:"));
unsigned char messageReference = p.parseInt();
if (p.parseComma(true))
{
string pdu = p.parseEol();
// add missing service centre address if required by ME
if (! _at->getMeTa().getCapabilities()._hasSMSSCAprefix)
pdu = "00" + pdu;
ackPdu = SMSMessage::decode(pdu);
}
else
ackPdu = SMSMessageRef();
return messageReference;
}
int SMSStore::doInsert(SMSMessageRef message)
throw(GsmException)
{
int index;
writeEntry(index, message);
// it is safer to force reading back the SMS from the ME
resizeStore(index + 1);
_store[index]->_cached = false;
return index;
}
SMSStore::SMSStore(string storeName, Ref<GsmAt> at, MeTa &meTa)
throw(GsmException) :
_storeName(storeName), _at(at), _meTa(meTa), _useCache(true)
{
// select SMS store
Parser p(_meTa.setSMSStore(_storeName, true, true));
p.parseInt(); // skip number of used mems
p.parseComma();
resizeStore(p.parseInt()); // ignore rest of line
}
void SMSStore::resizeStore(int newSize)
{
int oldSize = _store.size();
if (newSize > oldSize)
{
// cout << "*** Resizing from " << oldSize << " to " << newSize << endl;
_store.resize(newSize);
// initialize store entries
for (int i = oldSize; i < newSize; i++)
{
_store[i] = new SMSStoreEntry();
_store[i]->_index = i;
_store[i]->_cached = false;
_store[i]->_mySMSStore = this;
}
}
}
SMSStore::iterator SMSStore::begin()
{
return SMSStoreIterator(0, this);
}
SMSStore::const_iterator SMSStore::begin() const
{
return SMSStoreConstIterator(0, this);
}
SMSStore::iterator SMSStore::end()
{
return SMSStoreIterator(_store.size(), this);
}
SMSStore::const_iterator SMSStore::end() const
{
return SMSStoreConstIterator(_store.size(), this);
}
SMSStore::reference SMSStore::operator[](int n)
{
resizeStore(n + 1);
return *_store[n];
}
SMSStore::const_reference SMSStore::operator[](int n) const
{
const_cast<SMSStore*>(this)->resizeStore(n + 1);
return *_store[n];
}
SMSStore::reference SMSStore::front()
{
return *_store[0];
}
SMSStore::const_reference SMSStore::front() const
{
return *_store[0];
}
SMSStore::reference SMSStore::back()
{
return *_store.back();
}
SMSStore::const_reference SMSStore::back() const
{
return *_store.back();
}
int SMSStore::size() const throw(GsmException)
{
// select SMS store
Parser p(_meTa.setSMSStore(_storeName, 1, true));
return p.parseInt();
}
SMSStore::iterator SMSStore::insert(iterator position,
const SMSStoreEntry& x)
throw(GsmException)
{
int index = doInsert(x.message());
return SMSStoreIterator(index, this);
}
SMSStore::iterator SMSStore::insert(const SMSStoreEntry& x)
throw(GsmException)
{
int index = doInsert(x.message());
return SMSStoreIterator(index, this);
}
void SMSStore::insert (iterator pos, int n, const SMSStoreEntry& x)
throw(GsmException)
{
for (int i = 0; i < n; i++)
doInsert(x.message());
}
void SMSStore::insert (iterator pos, long n, const SMSStoreEntry& x)
throw(GsmException)
{
for (long i = 0; i < n; i++)
doInsert(x.message());
}
SMSStore::iterator SMSStore::erase(iterator position)
throw(GsmException)
{
eraseEntry(position->_index);
position->_cached = false;
return position + 1;
}
SMSStore::iterator SMSStore::erase(iterator first, iterator last)
throw(GsmException)
{
iterator i(0, this);
for (i = first; i != last; ++i)
erase(i);
return i;
}
void SMSStore::clear() throw(GsmException)
{
for (iterator i = begin(); i != end(); ++i)
erase(i);
}
SMSStore::~SMSStore()
{
for (vector<SMSStoreEntry*>::iterator i = _store.begin();
i != _store.end(); ++i)
delete *i;
}

View File

@ -0,0 +1,295 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_sms_store.h
// *
// * Purpose: SMS functions, SMS store
// * (ETSI GSM 07.05)
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 20.5.1999
// *************************************************************************
#ifndef GSM_SMS_STORE_H
#define GSM_SMS_STORE_H
#include <string>
#include <iterator>
#include <gsmlib/gsm_at.h>
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_sms.h>
#include <gsmlib/gsm_cb.h>
using namespace std;
namespace gsmlib
{
// forward declarations
class SMSStore;
class MeTa;
// a single entry in the SMS store
class SMSStoreEntry : public RefBase
{
public:
// status in ME memory
enum SMSMemoryStatus {ReceivedUnread = 0, ReceivedRead = 1,
StoredUnsent = 2, StoredSent = 3,
All = 4, Unknown = 5};
private:
SMSMessageRef _message;
SMSMemoryStatus _status;
bool _cached;
SMSStore *_mySMSStore;
int _index;
public:
// this constructor is only used by SMSStore
SMSStoreEntry();
// create new entry given a SMS message
SMSStoreEntry(SMSMessageRef message) :
_message(message), _status(Unknown), _cached(true), _mySMSStore(NULL),
_index(0) {}
// create new entry given a SMS message and an index
// only to be used for file-based stores (see gsm_sorted_sms_store)
SMSStoreEntry(SMSMessageRef message, int index) :
_message(message), _status(Unknown), _cached(true), _mySMSStore(NULL),
_index(index) {}
// clear cached flag
void clearCached() { _cached = false; }
// return SMS message stored in the entry
SMSMessageRef message() const throw(GsmException);
// return CB message stored in the entry
CBMessageRef cbMessage() const throw(GsmException);
// return message status in store
SMSMemoryStatus status() const throw(GsmException);
// return true if empty, ie. no SMS in this entry
bool empty() const throw(GsmException);
// send this PDU from store
// returns message reference and ACK-PDU (if requested)
// only applicate to SMS-SUBMIT and SMS-COMMAND
unsigned char send(Ref<SMSMessage> &ackPdu) throw(GsmException);
// same as above, but ACK-PDU is discarded
unsigned char send() throw(GsmException);
// return index (guaranteed to be unique,
// can be used for identification in store)
int index() const {return _index;}
// return true if entry is cached (and caching is enabled)
bool cached() const;
// return deep copy of this entry
Ref<SMSStoreEntry> clone();
// equality operator
bool operator==(const SMSStoreEntry &e) const;
// return store reference
SMSStore *getStore() {return _mySMSStore;}
// copy constructor and assignment
SMSStoreEntry(const SMSStoreEntry &e);
SMSStoreEntry &operator=(const SMSStoreEntry &e);
friend class SMSStore;
};
// iterator for the SMSStore class
#if __GNUC__ == 2 && __GNUC_MINOR__ == 95
class SMSStoreIterator : public random_access_iterator<SMSStoreEntry,
int>
#else
class SMSStoreIterator : public iterator<random_access_iterator_tag,
SMSStoreEntry, int>
#endif
{
int _index;
SMSStore *_store;
SMSStoreIterator(int index, SMSStore *store) :
_index(index), _store(store) {}
public:
SMSStoreIterator(SMSStoreEntry *entry) :
_index(entry->index()), _store(entry->getStore()) {}
SMSStoreEntry &operator*();
SMSStoreEntry *operator->();
SMSStoreIterator &operator+(int i)
{_index += i; return *this;}
operator SMSStoreEntry*();
SMSStoreIterator &operator=(const SMSStoreIterator &i);
SMSStoreIterator &operator++()
{++_index; return *this;}
SMSStoreIterator &operator--()
{--_index; return *this;}
SMSStoreIterator &operator++(int i)
{_index += i; return *this;}
SMSStoreIterator &operator--(int i)
{_index -= i; return *this;}
bool operator<(SMSStoreIterator &i)
{return _index < i._index;}
bool operator==(const SMSStoreIterator &i) const
{return _index == i._index;}
bool operator!=(const SMSStoreIterator &i) const
{return _index != i._index;}
friend class SMSStore;
};
#if __GNUC__ == 2 && __GNUC_MINOR__ == 95
class SMSStoreConstIterator : public random_access_iterator<SMSStoreEntry,
int>
#else
class SMSStoreConstIterator : public iterator<random_access_iterator_tag,
SMSStoreEntry, int>
#endif
{
int _index;
const SMSStore *_store;
SMSStoreConstIterator(int index, const SMSStore *store) :
_index(index), _store(store) {}
public:
const SMSStoreEntry &operator*();
const SMSStoreEntry *operator->();
SMSStoreConstIterator &operator++()
{++_index; return *this;}
SMSStoreConstIterator &operator--()
{--_index; return *this;}
SMSStoreConstIterator &operator++(int i)
{_index += i; return *this;}
SMSStoreConstIterator &operator--(int i)
{_index -= i; return *this;}
bool operator<(SMSStoreConstIterator &i)
{return _index < i._index;}
bool operator==(const SMSStoreConstIterator &i) const
{return _index == i._index;}
friend class SMSStore;
};
// this class corresponds to a SMS store in the ME
// all functions directly update storage in the ME
// if the ME is exchanged, the storage may become corrupted because
// of internal buffering in the SMSStore class
class SMSStore : public RefBase, public NoCopy
{
private:
vector<SMSStoreEntry*> _store; // vector of store entries
string _storeName; // name of the store, 2-byte like "SM"
Ref<GsmAt> _at; // my GsmAt class
MeTa &_meTa; // my MeTa class
bool _useCache; // true if entries should be cached
// internal access functions
// read/write entry from/to ME
void readEntry(int index, SMSMessageRef &message,
SMSStoreEntry::SMSMemoryStatus &status) throw(GsmException);
void readEntry(int index, CBMessageRef &message) throw(GsmException);
void writeEntry(int &index, SMSMessageRef message)
throw(GsmException);
// erase entry
void eraseEntry(int index) throw(GsmException);
// send PDU index from store
// returns message reference and ACK-PDU (if requested)
// only applicate to SMS-SUBMIT and SMS-COMMAND
unsigned char send(int index, Ref<SMSMessage> &ackPdu) throw(GsmException);
// do the actual insertion, return index of new element
int doInsert(SMSMessageRef message) throw(GsmException);
// used by class MeTa
SMSStore(string storeName, Ref<GsmAt> at, MeTa &meTa) throw(GsmException);
// resize store entry vector if necessary
void resizeStore(int newSize);
public:
// iterator defs
typedef SMSStoreIterator iterator;
typedef SMSStoreConstIterator const_iterator;
typedef SMSStoreEntry &reference;
typedef const SMSStoreEntry &const_reference;
// set cache mode on or off
void setCaching(bool useCache) {_useCache = useCache;}
// return name of this store (2-character string)
string name() const {return _storeName;}
// SMS store traversal commands
// these are suitable to use stdc++ lib algorithms and iterators
// ME have fixed storage space implemented as memory slots
// that may either be empty or used
// traversal commands
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reference front();
const_reference front() const;
reference back();
const_reference back() const;
reference operator[](int n);
const_reference operator[](int n) const;
// The size macros return the number of used entries
// Warning: indices may be _larger_ than size() because of this
// (perhaps this should be changed, because it is unexpected behavior)
int size() const throw(GsmException);
int max_size() const {return _store.size();}
int capacity() const {return _store.size();}
bool empty() const throw(GsmException) {return size() == 0;}
// insert iterators insert into the first empty cell regardless of position
// existing iterators may be invalidated after an insert operation
// return position
// insert only writes to available positions
// warning: insert fails silently if size() == max_size()
iterator insert(iterator position, const SMSStoreEntry& x)
throw(GsmException);
iterator insert(const SMSStoreEntry& x) throw(GsmException);
// insert n times, same procedure as above
void insert (iterator pos, int n, const SMSStoreEntry& x)
throw(GsmException);
void insert (iterator pos, long n, const SMSStoreEntry& x)
throw(GsmException);
// erase operators set used slots to "empty"
iterator erase(iterator position) throw(GsmException);
iterator erase(iterator first, iterator last) throw(GsmException);
void clear() throw(GsmException);
// destructor
~SMSStore();
friend class SMSStoreEntry;
friend class MeTa;
};
typedef Ref<SMSStore> SMSStoreRef;
};
#endif // GSM_SMS_STORE_H

View File

@ -0,0 +1,503 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_sorted_phonebook.cc
// *
// * Purpose: Alphabetically sorted phonebook
// * (residing in files or in the ME)
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 25.6.1999
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_sorted_phonebook.h>
#include <gsmlib/gsm_nls.h>
#include <iostream>
#include <fstream>
#include <limits.h>
#include <cstring>
const int MAX_LINE_SIZE = 1000;
using namespace std;
using namespace gsmlib;
string SortedPhonebook::escapeString(string s)
{
string result;
for (const char *pp = s.c_str(); *pp != 0; ++pp)
{
if (*pp == CR)
result += "\\r";
else if (*pp == LF)
result += "\\n";
else if (*pp == '\\')
result += "\\\\";
else if (*pp == '|')
result += "\\|";
else
result += *pp;
}
return result;
}
string SortedPhonebook::unescapeString(char *line, unsigned int &pos)
{
string result;
bool escaped = false;
while (! (line[pos] == '|' && ! escaped) && line[pos] != 0 &&
line[pos] != CR && line[pos] != LF)
{
if (escaped)
{
escaped = false;
if (line[pos] == 'r')
result += CR;
else if (line[pos] == 'n')
result += LF;
else if (line[pos] == '\\')
result += '\\';
else if (line[pos] == '|')
result += '|';
else
result += line[pos];
}
else
if (line[pos] == '\\')
escaped = true;
else
result += line[pos];
++pos;
}
return result;
}
void SortedPhonebook::readPhonebookFile(istream &pbs, string filename)
throw(GsmException)
{
// read entries
while (! pbs.eof())
{
char line[MAX_LINE_SIZE];
pbs.getline(line, MAX_LINE_SIZE);
if (strlen(line) == 0)
continue; // skip empty lines
if (pbs.bad())
throw GsmException(stringPrintf(_("error reading from file '%s"),
filename.c_str()),
OSError);
// convert line to newEntry (line format : [index] '|' text '|' number
string text, telephone;
unsigned int pos = 0;
// parse index
string indexS = unescapeString(line, pos);
int index = -1;
if (indexS.length() == 0)
{
if (_useIndices)
throw GsmException(stringPrintf(_("entry '%s' lacks index"), line),
ParserError);
}
else
{
index = checkNumber(indexS);
_useIndices = true;
}
if (line[pos++] != '|')
throw GsmException(stringPrintf(_("line '%s' has invalid format"), line),
ParserError);
// parse text
text = unescapeString(line, pos);
if (line[pos++] != '|')
throw GsmException(stringPrintf(_("line '%s' has invalid format"), line),
ParserError);
// parse telephone number
telephone = unescapeString(line, pos);
insert(PhonebookEntryBase(telephone, text, index));
}
}
void SortedPhonebook::sync(bool fromDestructor) throw(GsmException)
{
// if not in file it already is stored in ME/TA
if (! _fromFile) return;
// if writing to stdout and not called from destructor ignore
// (avoids writing to stdout multiple times)
if (_filename == "" && ! fromDestructor) return;
// find out if any of the entries have been updated
if (! _changed) // only look if we're not writing the file anyway
for (iterator i = begin(); i != end(); i++)
if (i->changed())
{
_changed = true;
break;
}
if (_changed)
{
checkReadonly();
// create backup file - but only once
if (! _madeBackupFile && _filename != "") // don't make backup of stdout
{
renameToBackupFile(_filename);
_madeBackupFile = true;
}
// open stream
ostream *pbs = NULL;
try
{
if (_filename == "")
pbs = &cout;
else
pbs = new ofstream(_filename.c_str());
if (pbs->bad())
throw GsmException(
stringPrintf(_("error opening file '%s' for writing"),
(_filename == "" ? _("<STDOUT>") :
_filename.c_str())),
OSError);
// and write the entries
for (PhonebookMap::iterator i = _sortedPhonebook.begin();
i != _sortedPhonebook.end(); ++i)
{
// convert entry to output line
string line =
(_useIndices ? intToStr(i->second->index()) : "") + "|" +
escapeString(i->second->text()) + "|" +
escapeString(i->second->telephone());
// write out the line
*pbs << line << endl;
if (pbs->bad())
throw GsmException(
stringPrintf(_("error writing to file '%s'"),
(_filename == "" ? _("<STDOUT>") :
_filename.c_str())),
OSError);
}
}
catch(GsmException &e)
{
if (pbs != &cout) delete pbs;
throw;
}
// close file
if (pbs != &cout) delete pbs;
// reset all changed states
_changed = false;
for (iterator j = begin(); j != end(); j++)
j->resetChanged();
}
}
void SortedPhonebook::checkReadonly() throw(GsmException)
{
if (_readonly) throw GsmException(
_("attempt to change phonebook read from <STDIN>"),
ParameterError);
}
SortedPhonebook::SortedPhonebook(string filename, bool useIndices)
throw(GsmException) :
_changed(false), _fromFile(true), _madeBackupFile(false),
_sortOrder(ByIndex), _useIndices(useIndices), _readonly(false),
_filename(filename)
{
// open the file
ifstream pbs(filename.c_str());
if (pbs.bad())
throw GsmException(stringPrintf(_("cannot open file '%s'"),
filename.c_str()),
OSError);
// and read the file
readPhonebookFile(pbs, filename);
}
SortedPhonebook::SortedPhonebook(bool fromStdin, bool useIndices)
throw(GsmException) :
_changed(false), _fromFile(true), _madeBackupFile(false),
_sortOrder(ByIndex), _useIndices(useIndices), _readonly(fromStdin)
// _filename is "" - this means stdout
{
// read from stdin
if (fromStdin)
readPhonebookFile(cin, (string)_("<STDIN>"));
}
SortedPhonebook::SortedPhonebook(PhonebookRef mePhonebook)
throw(GsmException) :
_changed(false), _fromFile(false), _madeBackupFile(false),
_sortOrder(ByIndex), _readonly(false), _mePhonebook(mePhonebook)
{
int entriesRead = 0;
reportProgress(0, _mePhonebook->end() - _mePhonebook->begin());
for (Phonebook::iterator i = _mePhonebook->begin();
i != _mePhonebook->end(); ++i)
{
if (! i->empty())
{
_sortedPhonebook.insert(
PhonebookMap::value_type(PhoneMapKey(*this, lowercase(i->text())), i));
++entriesRead;
if (entriesRead == _mePhonebook->size())
return; // ready
}
reportProgress(i - _mePhonebook->begin());
}
}
void SortedPhonebook::setSortOrder(SortOrder newOrder)
{
if (newOrder == _sortOrder) return; // nothing to do
PhonebookMap savedPhonebook = _sortedPhonebook; // save phonebook
_sortedPhonebook = PhonebookMap(); // empty old phonebook
_sortOrder = newOrder;
// re-insert entries
switch (newOrder)
{
case ByTelephone:
{
for (PhonebookMap::iterator i = savedPhonebook.begin();
i != savedPhonebook.end(); ++i)
_sortedPhonebook.
insert(PhonebookMap::value_type(
PhoneMapKey(*this, lowercase(i->second->telephone())), i->second));
break;
}
case ByText:
{
for (PhonebookMap::iterator i = savedPhonebook.begin();
i != savedPhonebook.end(); ++i)
_sortedPhonebook.
insert(PhonebookMap::value_type(
PhoneMapKey(*this, lowercase(i->second->text())), i->second));
break;
}
case ByIndex:
{
for (PhonebookMap::iterator i = savedPhonebook.begin();
i != savedPhonebook.end(); ++i)
_sortedPhonebook.
insert(PhonebookMap::value_type(
PhoneMapKey(*this, i->second->index()), i->second));
break;
}
default:
assert(0);
break;
}
}
unsigned int SortedPhonebook::getMaxTelephoneLen() const
{
if (_fromFile)
return UINT_MAX;
else
return _mePhonebook->getMaxTelephoneLen();
}
unsigned int SortedPhonebook::getMaxTextLen() const
{
if (_fromFile)
return UINT_MAX;
else
return _mePhonebook->getMaxTextLen();
}
int SortedPhonebook::max_size() const
{
if (_fromFile)
return _sortedPhonebook.max_size();
else
return _mePhonebook->max_size();
}
int SortedPhonebook::capacity() const
{
if (_fromFile)
return _sortedPhonebook.max_size();
else
return _mePhonebook->capacity();
}
SortedPhonebook::iterator
SortedPhonebook::insert(const PhonebookEntryBase& x) throw(GsmException)
{
checkReadonly();
_changed = true;
PhonebookEntryBase *newEntry;
if (_fromFile)
if (_useIndices)
{
if (x.index() != -1) // check that index is unique
{
for (PhonebookMap::iterator i = _sortedPhonebook.begin();
i != _sortedPhonebook.end(); ++i)
if (i->second->index() == x.index())
throw GsmException(_("indices must be unique in phonebook"),
ParameterError);
newEntry = new PhonebookEntryBase(x);
}
else // set index
{
SortOrder saveSortOrder = _sortOrder;
setSortOrder(ByIndex);
int index = 0;
for (PhonebookMap::iterator i = _sortedPhonebook.begin();
i != _sortedPhonebook.end(); ++i, ++index)
if (i->second->index() != index)
break;
setSortOrder(saveSortOrder);
newEntry = new PhonebookEntryBase();
newEntry->set(x.telephone(), x.text(), index, true);
}
}
else // index info in x is ignored
newEntry = new PhonebookEntryBase(x);
else
{
PhonebookEntry newMEEntry(x);
newEntry = _mePhonebook->insert((PhonebookEntry*)NULL, newMEEntry);
}
switch (_sortOrder)
{
case ByTelephone:
return
_sortedPhonebook.
insert(PhonebookMap::value_type(
PhoneMapKey(*this, lowercase(newEntry->telephone())), newEntry));
case ByText:
return
_sortedPhonebook.
insert(PhonebookMap::value_type(
PhoneMapKey(*this, lowercase(newEntry->text())), newEntry));
case ByIndex:
return
_sortedPhonebook.
insert(PhonebookMap::value_type(
PhoneMapKey(*this, newEntry->index()), newEntry));
default:
assert(0);
break;
}
return SortedPhonebook::iterator();
}
SortedPhonebook::iterator
SortedPhonebook::insert(iterator position, const PhonebookEntryBase& x)
throw(GsmException)
{
return insert(x);
}
SortedPhonebook::size_type SortedPhonebook::erase(string &key)
throw(GsmException)
{
// deallocate memory or remove from underlying ME phonebook
for (PhonebookMap::iterator i =
_sortedPhonebook.find(PhoneMapKey(*this, lowercase(key)));
i != _sortedPhonebook.end() &&
i->first == PhoneMapKey(*this, lowercase(key));
++i)
{
checkReadonly();
_changed = true;
if (_fromFile)
delete i->second;
else
_mePhonebook->erase((Phonebook::iterator)i->second);
}
return _sortedPhonebook.erase(PhoneMapKey(*this, lowercase(key)));
}
SortedPhonebook::size_type SortedPhonebook::erase(int key)
throw(GsmException)
{
// deallocate memory or remove from underlying ME phonebook
for (PhonebookMap::iterator i =
_sortedPhonebook.find(PhoneMapKey(*this, key));
i != _sortedPhonebook.end() && i->first == PhoneMapKey(*this, key);
++i)
{
checkReadonly();
_changed = true;
if (_fromFile)
delete i->second;
else
_mePhonebook->erase((Phonebook::iterator)i->second);
}
return _sortedPhonebook.erase(PhoneMapKey(*this, key));
}
void SortedPhonebook::erase(iterator position)
throw(GsmException)
{
checkReadonly();
_changed = true;
// deallocate memory or remove from underlying ME phonebook
if (_fromFile)
delete ((PhonebookMap::iterator)position)->second;
else
_mePhonebook->erase((Phonebook::iterator)
((PhonebookMap::iterator)position)->second);
_sortedPhonebook.erase(position);
}
void SortedPhonebook::erase(iterator first, iterator last)
throw(GsmException)
{
checkReadonly();
_changed = true;
for (PhonebookMap::iterator i = first; i != last; ++i)
if (_fromFile)
delete i->second;
else
_mePhonebook->erase((Phonebook::iterator)i->second);
_sortedPhonebook.erase(first, last);
}
void SortedPhonebook::clear() throw(GsmException)
{
checkReadonly();
_changed = true;
for (iterator i = begin(); i != end(); i++)
erase(i);
}
SortedPhonebook::~SortedPhonebook()
{
if (_fromFile)
{
sync(true);
for (PhonebookMap::iterator i = _sortedPhonebook.begin();
i != _sortedPhonebook.end(); ++i)
delete i->second;
}
}

View File

@ -0,0 +1,159 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_sorted_phonebook.h
// *
// * Purpose: Alphabetically sorted phonebook
// * (residing in files or in the ME)
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 25.6.1999
// *************************************************************************
#ifndef GSM_SORTED_PHONEBOOK_H
#define GSM_SORTED_PHONEBOOK_H
#include <gsmlib/gsm_sorted_phonebook_base.h>
#include <gsmlib/gsm_phonebook.h>
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_map_key.h>
#include <string>
#include <map>
#include <fstream>
using namespace std;
namespace gsmlib
{
// The class SortedPhonebook makes the phonebook more manageable:
// - empty slots in the ME phonebook are hidden by the API
// - the class transparently handles phonebooks that reside in files
class SortedPhonebook : public SortedPhonebookBase
{
private:
bool _changed; // true if file has changed after last save
bool _fromFile; // true if phonebook read from file
bool _madeBackupFile; // true if backup file was created
SortOrder _sortOrder; // sort order for the phonebook
bool _useIndices; // if phonebook from file: input file had
// indices; will write indices, too
bool _readonly; // =true if read from stdin
string _filename; // name of the file if phonebook from file
PhonebookMap _sortedPhonebook; // phonebook from file
PhonebookRef _mePhonebook; // phonebook if from ME
// convert CR and LF in string to "\r" and "\n" respectively
string escapeString(string s);
// convert "\r" and "\n" to CR and LF respectively
// start parsing with pos, stop when CR, LF, 0, or '|' is encountered
string unescapeString(char *line, unsigned int &pos);
// initial read of phonebook file
void readPhonebookFile(istream &pbs, string filename) throw(GsmException);
// synchronize SortedPhonebook with file (no action if in ME)
void sync(bool fromDestructor) throw(GsmException);
// throw an exception if _readonly is set
void checkReadonly() throw(GsmException);
public:
// iterator defs
typedef SortedPhonebookIterator iterator;
typedef PhonebookMap::size_type size_type;
// constructor for file-based phonebook
// expect indices in file if useIndices == true
// read from file
SortedPhonebook(string filename, bool useIndices)
throw(GsmException);
// read from stdin or start empty and write to stdout
SortedPhonebook(bool fromStdin, bool useIndices)
throw(GsmException);
// constructor for ME-based phonebook
SortedPhonebook(PhonebookRef mePhonebook) throw(GsmException);
// return maximum telephone number length
unsigned int getMaxTelephoneLen() const;
// return maximum entry description length
unsigned int getMaxTextLen() const;
// handle sorting
void setSortOrder(SortOrder newOrder);
SortOrder sortOrder() const {return _sortOrder;}
// phonebook traversal commands
// these are suitable to use stdc++ lib algorithms and iterators
// ME have fixed storage space implemented as memory slots
// that may either be empty or used
// traversal commands
iterator begin() {return _sortedPhonebook.begin();}
iterator end() {return _sortedPhonebook.end();}
// the size macros return the number of used entries
int size() const {return _sortedPhonebook.size();}
int max_size() const;
int capacity() const;
bool empty() const throw(GsmException) {return size() == 0;}
// existing iterators remain valid after an insert or erase operation
// note: inserting many entries in indexed mode is inefficient
// if the sort order is not set to indexed before
// return position
// insert only writes to available positions
// warning: insert fails silently if size() == max_size()
iterator insert(const PhonebookEntryBase& x) throw(GsmException);
iterator insert(iterator position, const PhonebookEntryBase& x)
throw(GsmException);
PhonebookMap::size_type count(string &key)
{return _sortedPhonebook.count(PhoneMapKey(*this, lowercase(key)));}
iterator find(string &key)
{return _sortedPhonebook.find(PhoneMapKey(*this, lowercase(key)));}
iterator lower_bound(string &key)
{return _sortedPhonebook.lower_bound(PhoneMapKey(*this,
lowercase(key)));}
iterator upper_bound(string &key)
{return _sortedPhonebook.upper_bound(PhoneMapKey(*this,
lowercase(key)));}
pair<iterator, iterator> equal_range(string &key)
{return _sortedPhonebook.equal_range(PhoneMapKey(*this,
lowercase(key)));}
PhonebookMap::size_type count(int key)
{return _sortedPhonebook.count(PhoneMapKey(*this, key));}
iterator find(int key)
{return _sortedPhonebook.find(PhoneMapKey(*this, key));}
iterator lower_bound(int key)
{return _sortedPhonebook.lower_bound(PhoneMapKey(*this, key));}
iterator upper_bound(int key)
{return _sortedPhonebook.upper_bound(PhoneMapKey(*this, key));}
pair<iterator, iterator> equal_range(int key)
{return _sortedPhonebook.equal_range(PhoneMapKey(*this, key));}
size_type erase(string &key) throw(GsmException);
size_type erase(int key) throw(GsmException);
void erase(iterator position) throw(GsmException);
void erase(iterator first, iterator last) throw(GsmException);
void clear() throw(GsmException);
// synchronize SortedPhonebook with file (no action if in ME)
void sync() throw(GsmException) {sync(false);}
// destructor
// writes back change to file if phonebook is in file
virtual ~SortedPhonebook();
};
// typedef Ref<SortedPhonebook> SortedPhonebookRef;
};
#endif // GSM_SORTED_PHONEBOOK_H

View File

@ -0,0 +1,115 @@
// *************************************************************************
// * GSM TA/ME library
// *
// * File: gsm_sorted_phonebook_base.cc
// *
// * Purpose: Virtual base class for alphabetically sorted phonebook
// * The infrastructure in this module allows custom backends for
// * storing phonebook entries to be integrated into gsmlib
// * (eg. LDAP- or RDBMS-based phonebook stores).
// *
// * Author: Peter Hofmann (software@pxh.de)
// *
// * Created: 5.6.2000
// *************************************************************************
#ifdef HAVE_CONFIG_H
#include <gsm_config.h>
#endif
#include <gsmlib/gsm_sorted_phonebook_base.h>
#include <gsmlib/gsm_error.h>
#include <gsmlib/gsm_util.h>
#include <gsmlib/gsm_nls.h>
#include <assert.h>
using namespace std;
using namespace gsmlib;
// PhonebookEntryBase members
void PhonebookEntryBase::set(string telephone, string text, int index,
bool useIndex)
throw(GsmException)
{
checkTextAndTelephone(text, telephone);
_changed = true;
_telephone = telephone;
_text = text;
_useIndex = useIndex;
if (index != -1)
_index = index;
}
bool PhonebookEntryBase::operator==(const PhonebookEntryBase &e) const
{
assert(! ((_useIndex || e._useIndex) &&
(_index == -1 || e._index == -1)));
return _telephone == e._telephone && _text == e._text &&
(! (_useIndex || e._useIndex) || _index == e._index);
}
string PhonebookEntryBase::text() const throw(GsmException)
{
return _text;
}
string PhonebookEntryBase::telephone() const throw(GsmException)
{
return _telephone;
}
bool PhonebookEntryBase::empty() const throw(GsmException)
{
return (text() == "") && (telephone() == "");
}
Ref<PhonebookEntryBase> PhonebookEntryBase::clone()
{
Ref<PhonebookEntryBase> result = new PhonebookEntryBase(*this);
return result;
}
PhonebookEntryBase::PhonebookEntryBase(const PhonebookEntryBase &e)
throw(GsmException)
{
set(e._telephone, e._text, e._index, e._useIndex);
}
PhonebookEntryBase &PhonebookEntryBase::operator=(const PhonebookEntryBase &e)
throw(GsmException)
{
set(e._telephone, e._text, e._index, e._useIndex);
return *this;
}
// CustomPhonebookRegistry members
map<string, CustomPhonebookFactory*>
*CustomPhonebookRegistry::_factoryList = NULL;
void CustomPhonebookRegistry::
registerCustomPhonebookFactory(string backendName,
CustomPhonebookFactory *factory)
throw(GsmException)
{
if (_factoryList == NULL)
_factoryList = new map<string, CustomPhonebookFactory*>;
backendName = lowercase(backendName);
if (_factoryList->find(backendName) != _factoryList->end())
throw GsmException(stringPrintf(_("backend '%s' already registered"),
backendName.c_str()), ParameterError);
}
SortedPhonebookRef CustomPhonebookRegistry::
createPhonebook(string backendName, string source) throw(GsmException)
{
if (_factoryList == NULL)
_factoryList = new map<string, CustomPhonebookFactory*>;
backendName = lowercase(backendName);
if (_factoryList->find(backendName) == _factoryList->end())
throw GsmException(stringPrintf(_("backend '%s' not registered"),
backendName.c_str()), ParameterError);
return (*_factoryList)[backendName]->createPhonebook(source);
}

Some files were not shown because too many files have changed in this diff Show More