Rserve/ 0000755 0001760 0000144 00000000000 14147657072 011565 5 ustar ripley users Rserve/NAMESPACE 0000644 0001760 0000144 00000000347 14147646005 013002 0 ustar ripley users export(Rserve, self.ctrlEval, self.ctrlSource, self.oobSend, self.oobMessage, run.Rserve, ocap,
Rserve.eval, Rserve.context, resolve.ocap, ulog)
if (.Platform$OS.type == "windows") {
importFrom("utils", "shortPathName")
}
Rserve/LICENSE 0000644 0001760 0000144 00000040726 14147646005 012575 0 ustar ripley users [Summary: GPL-2 with OpenSSL linking exception]
Rserve
Copyright (C) 2002-2013 Simon Urbanek
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
In addition, as a special exception, the copyright holders give
permission to link the code of portions of this program with the
OpenSSL project's "OpenSSL" library (or with modified versions of
it that use the same license as the "OpenSSL" library - see
http://www.openssl.org/), and distribute linked combinations
including the two.
You must obey the GNU General Public License in all respects
for all of the code used other than OpenSSL. If you modify
file(s) with this exception, you may extend this exception to your
version of the file(s), but you are not obligated to do so. If you
do not wish to do so, delete this exception statement from your
version. If you delete this exception statement from all source
files in the program, then also delete it here.
Full text of GPL-2 follows:
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Rserve/tools/ 0000755 0001760 0000144 00000000000 14147646005 012717 5 ustar ripley users Rserve/tools/config.sub 0000755 0001760 0000144 00000102644 14147646005 014711 0 ustar ripley users #! /bin/sh
# Configuration validation subroutine script.
# Copyright 1992-2020 Free Software Foundation, Inc.
timestamp='2020-11-07'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see .
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that
# program. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
# Please send patches to .
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
# Each package is responsible for reporting which valid configurations
# it does not support. The user should be able to distinguish
# a failure to support a valid configuration from a meaningless
# configuration.
# The goal of this file is to map all the various variations of a given
# machine specification into a single specification in the form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or in some cases, the newer four-part form:
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
me=$(echo "$0" | sed -e 's,.*/,,')
usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
Canonicalize a configuration name.
Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to ."
version="\
GNU config.sub ($timestamp)
Copyright 1992-2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
Try \`$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help" >&2
exit 1 ;;
*local*)
# First pass through any local machine types.
echo "$1"
exit ;;
* )
break ;;
esac
done
case $# in
0) echo "$me: missing argument$help" >&2
exit 1;;
1) ;;
*) echo "$me: too many arguments$help" >&2
exit 1;;
esac
# Split fields of configuration type
# shellcheck disable=SC2162
IFS="-" read field1 field2 field3 field4 <&2
exit 1
;;
*-*-*-*)
basic_machine=$field1-$field2
basic_os=$field3-$field4
;;
*-*-*)
# Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
# parts
maybe_os=$field2-$field3
case $maybe_os in
nto-qnx* | linux-* | uclinux-uclibc* \
| uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
| netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
| storm-chaos* | os2-emx* | rtmk-nova*)
basic_machine=$field1
basic_os=$maybe_os
;;
android-linux)
basic_machine=$field1-unknown
basic_os=linux-android
;;
*)
basic_machine=$field1-$field2
basic_os=$field3
;;
esac
;;
*-*)
# A lone config we happen to match not fitting any pattern
case $field1-$field2 in
decstation-3100)
basic_machine=mips-dec
basic_os=
;;
*-*)
# Second component is usually, but not always the OS
case $field2 in
# Prevent following clause from handling this valid os
sun*os*)
basic_machine=$field1
basic_os=$field2
;;
# Manufacturers
dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
| att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
| unicom* | ibm* | next | hp | isi* | apollo | altos* \
| convergent* | ncr* | news | 32* | 3600* | 3100* \
| hitachi* | c[123]* | convex* | sun | crds | omron* | dg \
| ultra | tti* | harris | dolphin | highlevel | gould \
| cbm | ns | masscomp | apple | axis | knuth | cray \
| microblaze* | sim | cisco \
| oki | wec | wrs | winbond)
basic_machine=$field1-$field2
basic_os=
;;
*)
basic_machine=$field1
basic_os=$field2
;;
esac
;;
esac
;;
*)
# Convert single-component short-hands not valid as part of
# multi-component configurations.
case $field1 in
386bsd)
basic_machine=i386-pc
basic_os=bsd
;;
a29khif)
basic_machine=a29k-amd
basic_os=udi
;;
adobe68k)
basic_machine=m68010-adobe
basic_os=scout
;;
alliant)
basic_machine=fx80-alliant
basic_os=
;;
altos | altos3068)
basic_machine=m68k-altos
basic_os=
;;
am29k)
basic_machine=a29k-none
basic_os=bsd
;;
amdahl)
basic_machine=580-amdahl
basic_os=sysv
;;
amiga)
basic_machine=m68k-unknown
basic_os=
;;
amigaos | amigados)
basic_machine=m68k-unknown
basic_os=amigaos
;;
amigaunix | amix)
basic_machine=m68k-unknown
basic_os=sysv4
;;
apollo68)
basic_machine=m68k-apollo
basic_os=sysv
;;
apollo68bsd)
basic_machine=m68k-apollo
basic_os=bsd
;;
aros)
basic_machine=i386-pc
basic_os=aros
;;
aux)
basic_machine=m68k-apple
basic_os=aux
;;
balance)
basic_machine=ns32k-sequent
basic_os=dynix
;;
blackfin)
basic_machine=bfin-unknown
basic_os=linux
;;
cegcc)
basic_machine=arm-unknown
basic_os=cegcc
;;
convex-c1)
basic_machine=c1-convex
basic_os=bsd
;;
convex-c2)
basic_machine=c2-convex
basic_os=bsd
;;
convex-c32)
basic_machine=c32-convex
basic_os=bsd
;;
convex-c34)
basic_machine=c34-convex
basic_os=bsd
;;
convex-c38)
basic_machine=c38-convex
basic_os=bsd
;;
cray)
basic_machine=j90-cray
basic_os=unicos
;;
crds | unos)
basic_machine=m68k-crds
basic_os=
;;
da30)
basic_machine=m68k-da30
basic_os=
;;
decstation | pmax | pmin | dec3100 | decstatn)
basic_machine=mips-dec
basic_os=
;;
delta88)
basic_machine=m88k-motorola
basic_os=sysv3
;;
dicos)
basic_machine=i686-pc
basic_os=dicos
;;
djgpp)
basic_machine=i586-pc
basic_os=msdosdjgpp
;;
ebmon29k)
basic_machine=a29k-amd
basic_os=ebmon
;;
es1800 | OSE68k | ose68k | ose | OSE)
basic_machine=m68k-ericsson
basic_os=ose
;;
gmicro)
basic_machine=tron-gmicro
basic_os=sysv
;;
go32)
basic_machine=i386-pc
basic_os=go32
;;
h8300hms)
basic_machine=h8300-hitachi
basic_os=hms
;;
h8300xray)
basic_machine=h8300-hitachi
basic_os=xray
;;
h8500hms)
basic_machine=h8500-hitachi
basic_os=hms
;;
harris)
basic_machine=m88k-harris
basic_os=sysv3
;;
hp300 | hp300hpux)
basic_machine=m68k-hp
basic_os=hpux
;;
hp300bsd)
basic_machine=m68k-hp
basic_os=bsd
;;
hppaosf)
basic_machine=hppa1.1-hp
basic_os=osf
;;
hppro)
basic_machine=hppa1.1-hp
basic_os=proelf
;;
i386mach)
basic_machine=i386-mach
basic_os=mach
;;
isi68 | isi)
basic_machine=m68k-isi
basic_os=sysv
;;
m68knommu)
basic_machine=m68k-unknown
basic_os=linux
;;
magnum | m3230)
basic_machine=mips-mips
basic_os=sysv
;;
merlin)
basic_machine=ns32k-utek
basic_os=sysv
;;
mingw64)
basic_machine=x86_64-pc
basic_os=mingw64
;;
mingw32)
basic_machine=i686-pc
basic_os=mingw32
;;
mingw32ce)
basic_machine=arm-unknown
basic_os=mingw32ce
;;
monitor)
basic_machine=m68k-rom68k
basic_os=coff
;;
morphos)
basic_machine=powerpc-unknown
basic_os=morphos
;;
moxiebox)
basic_machine=moxie-unknown
basic_os=moxiebox
;;
msdos)
basic_machine=i386-pc
basic_os=msdos
;;
msys)
basic_machine=i686-pc
basic_os=msys
;;
mvs)
basic_machine=i370-ibm
basic_os=mvs
;;
nacl)
basic_machine=le32-unknown
basic_os=nacl
;;
ncr3000)
basic_machine=i486-ncr
basic_os=sysv4
;;
netbsd386)
basic_machine=i386-pc
basic_os=netbsd
;;
netwinder)
basic_machine=armv4l-rebel
basic_os=linux
;;
news | news700 | news800 | news900)
basic_machine=m68k-sony
basic_os=newsos
;;
news1000)
basic_machine=m68030-sony
basic_os=newsos
;;
necv70)
basic_machine=v70-nec
basic_os=sysv
;;
nh3000)
basic_machine=m68k-harris
basic_os=cxux
;;
nh[45]000)
basic_machine=m88k-harris
basic_os=cxux
;;
nindy960)
basic_machine=i960-intel
basic_os=nindy
;;
mon960)
basic_machine=i960-intel
basic_os=mon960
;;
nonstopux)
basic_machine=mips-compaq
basic_os=nonstopux
;;
os400)
basic_machine=powerpc-ibm
basic_os=os400
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
basic_os=ose
;;
os68k)
basic_machine=m68k-none
basic_os=os68k
;;
paragon)
basic_machine=i860-intel
basic_os=osf
;;
parisc)
basic_machine=hppa-unknown
basic_os=linux
;;
psp)
basic_machine=mipsallegrexel-sony
basic_os=psp
;;
pw32)
basic_machine=i586-unknown
basic_os=pw32
;;
rdos | rdos64)
basic_machine=x86_64-pc
basic_os=rdos
;;
rdos32)
basic_machine=i386-pc
basic_os=rdos
;;
rom68k)
basic_machine=m68k-rom68k
basic_os=coff
;;
sa29200)
basic_machine=a29k-amd
basic_os=udi
;;
sei)
basic_machine=mips-sei
basic_os=seiux
;;
sequent)
basic_machine=i386-sequent
basic_os=
;;
sps7)
basic_machine=m68k-bull
basic_os=sysv2
;;
st2000)
basic_machine=m68k-tandem
basic_os=
;;
stratus)
basic_machine=i860-stratus
basic_os=sysv4
;;
sun2)
basic_machine=m68000-sun
basic_os=
;;
sun2os3)
basic_machine=m68000-sun
basic_os=sunos3
;;
sun2os4)
basic_machine=m68000-sun
basic_os=sunos4
;;
sun3)
basic_machine=m68k-sun
basic_os=
;;
sun3os3)
basic_machine=m68k-sun
basic_os=sunos3
;;
sun3os4)
basic_machine=m68k-sun
basic_os=sunos4
;;
sun4)
basic_machine=sparc-sun
basic_os=
;;
sun4os3)
basic_machine=sparc-sun
basic_os=sunos3
;;
sun4os4)
basic_machine=sparc-sun
basic_os=sunos4
;;
sun4sol2)
basic_machine=sparc-sun
basic_os=solaris2
;;
sun386 | sun386i | roadrunner)
basic_machine=i386-sun
basic_os=
;;
sv1)
basic_machine=sv1-cray
basic_os=unicos
;;
symmetry)
basic_machine=i386-sequent
basic_os=dynix
;;
t3e)
basic_machine=alphaev5-cray
basic_os=unicos
;;
t90)
basic_machine=t90-cray
basic_os=unicos
;;
toad1)
basic_machine=pdp10-xkl
basic_os=tops20
;;
tpf)
basic_machine=s390x-ibm
basic_os=tpf
;;
udi29k)
basic_machine=a29k-amd
basic_os=udi
;;
ultra3)
basic_machine=a29k-nyu
basic_os=sym1
;;
v810 | necv810)
basic_machine=v810-nec
basic_os=none
;;
vaxv)
basic_machine=vax-dec
basic_os=sysv
;;
vms)
basic_machine=vax-dec
basic_os=vms
;;
vsta)
basic_machine=i386-pc
basic_os=vsta
;;
vxworks960)
basic_machine=i960-wrs
basic_os=vxworks
;;
vxworks68)
basic_machine=m68k-wrs
basic_os=vxworks
;;
vxworks29k)
basic_machine=a29k-wrs
basic_os=vxworks
;;
xbox)
basic_machine=i686-pc
basic_os=mingw32
;;
ymp)
basic_machine=ymp-cray
basic_os=unicos
;;
*)
basic_machine=$1
basic_os=
;;
esac
;;
esac
# Decode 1-component or ad-hoc basic machines
case $basic_machine in
# Here we handle the default manufacturer of certain CPU types. It is in
# some cases the only manufacturer, in others, it is the most popular.
w89k)
cpu=hppa1.1
vendor=winbond
;;
op50n)
cpu=hppa1.1
vendor=oki
;;
op60c)
cpu=hppa1.1
vendor=oki
;;
ibm*)
cpu=i370
vendor=ibm
;;
orion105)
cpu=clipper
vendor=highlevel
;;
mac | mpw | mac-mpw)
cpu=m68k
vendor=apple
;;
pmac | pmac-mpw)
cpu=powerpc
vendor=apple
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
cpu=m68000
vendor=att
;;
3b*)
cpu=we32k
vendor=att
;;
bluegene*)
cpu=powerpc
vendor=ibm
basic_os=cnk
;;
decsystem10* | dec10*)
cpu=pdp10
vendor=dec
basic_os=tops10
;;
decsystem20* | dec20*)
cpu=pdp10
vendor=dec
basic_os=tops20
;;
delta | 3300 | motorola-3300 | motorola-delta \
| 3300-motorola | delta-motorola)
cpu=m68k
vendor=motorola
;;
dpx2*)
cpu=m68k
vendor=bull
basic_os=sysv3
;;
encore | umax | mmax)
cpu=ns32k
vendor=encore
;;
elxsi)
cpu=elxsi
vendor=elxsi
basic_os=${basic_os:-bsd}
;;
fx2800)
cpu=i860
vendor=alliant
;;
genix)
cpu=ns32k
vendor=ns
;;
h3050r* | hiux*)
cpu=hppa1.1
vendor=hitachi
basic_os=hiuxwe2
;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
cpu=hppa1.0
vendor=hp
;;
hp9k2[0-9][0-9] | hp9k31[0-9])
cpu=m68000
vendor=hp
;;
hp9k3[2-9][0-9])
cpu=m68k
vendor=hp
;;
hp9k6[0-9][0-9] | hp6[0-9][0-9])
cpu=hppa1.0
vendor=hp
;;
hp9k7[0-79][0-9] | hp7[0-79][0-9])
cpu=hppa1.1
vendor=hp
;;
hp9k78[0-9] | hp78[0-9])
# FIXME: really hppa2.0-hp
cpu=hppa1.1
vendor=hp
;;
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
# FIXME: really hppa2.0-hp
cpu=hppa1.1
vendor=hp
;;
hp9k8[0-9][13679] | hp8[0-9][13679])
cpu=hppa1.1
vendor=hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
cpu=hppa1.0
vendor=hp
;;
i*86v32)
cpu=$(echo "$1" | sed -e 's/86.*/86/')
vendor=pc
basic_os=sysv32
;;
i*86v4*)
cpu=$(echo "$1" | sed -e 's/86.*/86/')
vendor=pc
basic_os=sysv4
;;
i*86v)
cpu=$(echo "$1" | sed -e 's/86.*/86/')
vendor=pc
basic_os=sysv
;;
i*86sol2)
cpu=$(echo "$1" | sed -e 's/86.*/86/')
vendor=pc
basic_os=solaris2
;;
j90 | j90-cray)
cpu=j90
vendor=cray
basic_os=${basic_os:-unicos}
;;
iris | iris4d)
cpu=mips
vendor=sgi
case $basic_os in
irix*)
;;
*)
basic_os=irix4
;;
esac
;;
miniframe)
cpu=m68000
vendor=convergent
;;
*mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
cpu=m68k
vendor=atari
basic_os=mint
;;
news-3600 | risc-news)
cpu=mips
vendor=sony
basic_os=newsos
;;
next | m*-next)
cpu=m68k
vendor=next
case $basic_os in
openstep*)
;;
nextstep*)
;;
ns2*)
basic_os=nextstep2
;;
*)
basic_os=nextstep3
;;
esac
;;
np1)
cpu=np1
vendor=gould
;;
op50n-* | op60c-*)
cpu=hppa1.1
vendor=oki
basic_os=proelf
;;
pa-hitachi)
cpu=hppa1.1
vendor=hitachi
basic_os=hiuxwe2
;;
pbd)
cpu=sparc
vendor=tti
;;
pbb)
cpu=m68k
vendor=tti
;;
pc532)
cpu=ns32k
vendor=pc532
;;
pn)
cpu=pn
vendor=gould
;;
power)
cpu=power
vendor=ibm
;;
ps2)
cpu=i386
vendor=ibm
;;
rm[46]00)
cpu=mips
vendor=siemens
;;
rtpc | rtpc-*)
cpu=romp
vendor=ibm
;;
sde)
cpu=mipsisa32
vendor=sde
basic_os=${basic_os:-elf}
;;
simso-wrs)
cpu=sparclite
vendor=wrs
basic_os=vxworks
;;
tower | tower-32)
cpu=m68k
vendor=ncr
;;
vpp*|vx|vx-*)
cpu=f301
vendor=fujitsu
;;
w65)
cpu=w65
vendor=wdc
;;
w89k-*)
cpu=hppa1.1
vendor=winbond
basic_os=proelf
;;
none)
cpu=none
vendor=none
;;
leon|leon[3-9])
cpu=sparc
vendor=$basic_machine
;;
leon-*|leon[3-9]-*)
cpu=sparc
vendor=$(echo "$basic_machine" | sed 's/-.*//')
;;
*-*)
# shellcheck disable=SC2162
IFS="-" read cpu vendor <&2
exit 1
;;
esac
;;
esac
# Here we canonicalize certain aliases for manufacturers.
case $vendor in
digital*)
vendor=dec
;;
commodore*)
vendor=cbm
;;
*)
;;
esac
# Decode manufacturer-specific aliases for certain operating systems.
if test x$basic_os != x
then
# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just
# set os.
case $basic_os in
gnu/linux*)
kernel=linux
os=$(echo $basic_os | sed -e 's|gnu/linux|gnu|')
;;
os2-emx)
kernel=os2
os=$(echo $basic_os | sed -e 's|os2-emx|emx|')
;;
nto-qnx*)
kernel=nto
os=$(echo $basic_os | sed -e 's|nto-qnx|qnx|')
;;
*-*)
# shellcheck disable=SC2162
IFS="-" read kernel os <&2
exit 1
;;
esac
# As a final step for OS-related things, validate the OS-kernel combination
# (given a valid OS), if there is a kernel.
case $kernel-$os in
linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* )
;;
uclinux-uclibc* )
;;
-dietlibc* | -newlib* | -musl* | -uclibc* )
# These are just libc implementations, not actual OSes, and thus
# require a kernel.
echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
exit 1
;;
kfreebsd*-gnu* | kopensolaris*-gnu*)
;;
nto-qnx*)
;;
os2-emx)
;;
*-eabi* | *-gnueabi*)
;;
-*)
# Blank kernel with real OS is always fine.
;;
*-*)
echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
exit 1
;;
esac
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer. We pick the logical manufacturer.
case $vendor in
unknown)
case $cpu-$os in
*-riscix*)
vendor=acorn
;;
*-sunos*)
vendor=sun
;;
*-cnk* | *-aix*)
vendor=ibm
;;
*-beos*)
vendor=be
;;
*-hpux*)
vendor=hp
;;
*-mpeix*)
vendor=hp
;;
*-hiux*)
vendor=hitachi
;;
*-unos*)
vendor=crds
;;
*-dgux*)
vendor=dg
;;
*-luna*)
vendor=omron
;;
*-genix*)
vendor=ns
;;
*-clix*)
vendor=intergraph
;;
*-mvs* | *-opened*)
vendor=ibm
;;
*-os400*)
vendor=ibm
;;
s390-* | s390x-*)
vendor=ibm
;;
*-ptx*)
vendor=sequent
;;
*-tpf*)
vendor=ibm
;;
*-vxsim* | *-vxworks* | *-windiss*)
vendor=wrs
;;
*-aux*)
vendor=apple
;;
*-hms*)
vendor=hitachi
;;
*-mpw* | *-macos*)
vendor=apple
;;
*-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
vendor=atari
;;
*-vos*)
vendor=stratus
;;
esac
;;
esac
echo "$cpu-$vendor-${kernel:+$kernel-}$os"
exit
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
Rserve/tools/config.guess 0000755 0001760 0000144 00000137613 14147646005 015252 0 ustar ripley users #! /bin/sh
# Attempt to guess a canonical system name.
# Copyright 1992-2020 Free Software Foundation, Inc.
timestamp='2020-11-07'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see .
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that
# program. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
#
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
#
# Please send patches to .
me=$(echo "$0" | sed -e 's,.*/,,')
usage="\
Usage: $0 [OPTION]
Output the configuration name of the system \`$me' is run on.
Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to ."
version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
Copyright 1992-2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
Try \`$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help" >&2
exit 1 ;;
* )
break ;;
esac
done
if test $# != 0; then
echo "$me: too many arguments$help" >&2
exit 1
fi
# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
# compiler to aid in system detection is discouraged as it requires
# temporary files to be created and, as you can see below, it is a
# headache to deal with in a portable fashion.
# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
# use `HOST_CC' if defined, but it is deprecated.
# Portable tmp directory creation inspired by the Autoconf team.
tmp=
# shellcheck disable=SC2172
trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
set_cc_for_build() {
# prevent multiple calls if $tmp is already set
test "$tmp" && return 0
: "${TMPDIR=/tmp}"
# shellcheck disable=SC2039
{ tmp=$( (umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null) && test -n "$tmp" && test -d "$tmp" ; } ||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
dummy=$tmp/dummy
case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
,,) echo "int x;" > "$dummy.c"
for driver in cc gcc c89 c99 ; do
if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
CC_FOR_BUILD="$driver"
break
fi
done
if test x"$CC_FOR_BUILD" = x ; then
CC_FOR_BUILD=no_compiler_found
fi
;;
,,*) CC_FOR_BUILD=$CC ;;
,*,*) CC_FOR_BUILD=$HOST_CC ;;
esac
}
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
if test -f /.attbin/uname ; then
PATH=$PATH:/.attbin ; export PATH
fi
UNAME_MACHINE=$( (uname -m) 2>/dev/null) || UNAME_MACHINE=unknown
UNAME_RELEASE=$( (uname -r) 2>/dev/null) || UNAME_RELEASE=unknown
UNAME_SYSTEM=$( (uname -s) 2>/dev/null) || UNAME_SYSTEM=unknown
UNAME_VERSION=$( (uname -v) 2>/dev/null) || UNAME_VERSION=unknown
case "$UNAME_SYSTEM" in
Linux|GNU|GNU/*)
# If the system lacks a compiler, then just pick glibc.
# We could probably try harder.
LIBC=gnu
set_cc_for_build
cat <<-EOF > "$dummy.c"
#include
#if defined(__UCLIBC__)
LIBC=uclibc
#elif defined(__dietlibc__)
LIBC=dietlibc
#else
#include
#ifdef __DEFINED_va_list
LIBC=musl
#else
LIBC=gnu
#endif
#endif
EOF
eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g')"
;;
esac
# Note: order is significant - the case branches are not exclusive.
case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
# compatibility and a consistent mechanism for selecting the
# object file format.
#
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
sysctl="sysctl -n hw.machine_arch"
UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \
"/sbin/$sysctl" 2>/dev/null || \
"/usr/sbin/$sysctl" 2>/dev/null || \
echo unknown))
case "$UNAME_MACHINE_ARCH" in
aarch64eb) machine=aarch64_be-unknown ;;
armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
earmv*)
arch=$(echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,')
endian=$(echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p')
machine="${arch}${endian}"-unknown
;;
*) machine="$UNAME_MACHINE_ARCH"-unknown ;;
esac
# The Operating System including object format, if it has switched
# to ELF recently (or will in the future) and ABI.
case "$UNAME_MACHINE_ARCH" in
earm*)
os=netbsdelf
;;
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ELF__
then
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
# Return netbsd for either. FIX?
os=netbsd
else
os=netbsdelf
fi
;;
*)
os=netbsd
;;
esac
# Determine ABI tags.
case "$UNAME_MACHINE_ARCH" in
earm*)
expr='s/^earmv[0-9]/-eabi/;s/eb$//'
abi=$(echo "$UNAME_MACHINE_ARCH" | sed -e "$expr")
;;
esac
# The OS release
# Debian GNU/NetBSD machines have a different userland, and
# thus, need a distinct triplet. However, they do not need
# kernel version information, so it can be replaced with a
# suitable tag, in the style of linux-gnu.
case "$UNAME_VERSION" in
Debian*)
release='-gnu'
;;
*)
release=$(echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2)
;;
esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
echo "$machine-${os}${release}${abi-}"
exit ;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//')
echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
exit ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//')
echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
exit ;;
*:LibertyBSD:*:*)
UNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\.//')
echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
exit ;;
*:MidnightBSD:*:*)
echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
exit ;;
*:ekkoBSD:*:*)
echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
exit ;;
*:SolidBSD:*:*)
echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
exit ;;
*:OS108:*:*)
echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE"
exit ;;
macppc:MirBSD:*:*)
echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
exit ;;
*:MirBSD:*:*)
echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
exit ;;
*:Sortix:*:*)
echo "$UNAME_MACHINE"-unknown-sortix
exit ;;
*:Twizzler:*:*)
echo "$UNAME_MACHINE"-unknown-twizzler
exit ;;
*:Redox:*:*)
echo "$UNAME_MACHINE"-unknown-redox
exit ;;
mips:OSF1:*.*)
echo mips-dec-osf1
exit ;;
alpha:OSF1:*:*)
case $UNAME_RELEASE in
*4.0)
UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $3}')
;;
*5.*)
UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $4}')
;;
esac
# According to Compaq, /usr/sbin/psrinfo has been available on
# OSF/1 and Tru64 systems produced since 1995. I hope that
# covers most systems running today. This code pipes the CPU
# types through head -n 1, so we only detect the type of CPU 0.
ALPHA_CPU_TYPE=$(/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1)
case "$ALPHA_CPU_TYPE" in
"EV4 (21064)")
UNAME_MACHINE=alpha ;;
"EV4.5 (21064)")
UNAME_MACHINE=alpha ;;
"LCA4 (21066/21068)")
UNAME_MACHINE=alpha ;;
"EV5 (21164)")
UNAME_MACHINE=alphaev5 ;;
"EV5.6 (21164A)")
UNAME_MACHINE=alphaev56 ;;
"EV5.6 (21164PC)")
UNAME_MACHINE=alphapca56 ;;
"EV5.7 (21164PC)")
UNAME_MACHINE=alphapca57 ;;
"EV6 (21264)")
UNAME_MACHINE=alphaev6 ;;
"EV6.7 (21264A)")
UNAME_MACHINE=alphaev67 ;;
"EV6.8CB (21264C)")
UNAME_MACHINE=alphaev68 ;;
"EV6.8AL (21264B)")
UNAME_MACHINE=alphaev68 ;;
"EV6.8CX (21264D)")
UNAME_MACHINE=alphaev68 ;;
"EV6.9A (21264/EV69A)")
UNAME_MACHINE=alphaev69 ;;
"EV7 (21364)")
UNAME_MACHINE=alphaev7 ;;
"EV7.9 (21364A)")
UNAME_MACHINE=alphaev79 ;;
esac
# A Pn.n version is a patched version.
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
echo "$UNAME_MACHINE"-dec-osf"$(echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)"
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
exitcode=$?
trap '' 0
exit $exitcode ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-unknown-sysv4
exit ;;
*:[Aa]miga[Oo][Ss]:*:*)
echo "$UNAME_MACHINE"-unknown-amigaos
exit ;;
*:[Mm]orph[Oo][Ss]:*:*)
echo "$UNAME_MACHINE"-unknown-morphos
exit ;;
*:OS/390:*:*)
echo i370-ibm-openedition
exit ;;
*:z/VM:*:*)
echo s390-ibm-zvmoe
exit ;;
*:OS400:*:*)
echo powerpc-ibm-os400
exit ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix"$UNAME_RELEASE"
exit ;;
arm*:riscos:*:*|arm*:RISCOS:*:*)
echo arm-unknown-riscos
exit ;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
echo hppa1.1-hitachi-hiuxmpp
exit ;;
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
if test "$( (/bin/universe) 2>/dev/null)" = att ; then
echo pyramid-pyramid-sysv3
else
echo pyramid-pyramid-bsd
fi
exit ;;
NILE*:*:*:dcosx)
echo pyramid-pyramid-svr4
exit ;;
DRS?6000:unix:4.0:6*)
echo sparc-icl-nx6
exit ;;
DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
case $(/usr/bin/uname -p) in
sparc) echo sparc-icl-nx7; exit ;;
esac ;;
s390x:SunOS:*:*)
echo "$UNAME_MACHINE"-ibm-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')"
exit ;;
sun4H:SunOS:5.*:*)
echo sparc-hal-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
exit ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')"
exit ;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
echo i386-pc-auroraux"$UNAME_RELEASE"
exit ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
set_cc_for_build
SUN_ARCH=i386
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
# This test works for both compilers.
if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
SUN_ARCH=x86_64
fi
fi
echo "$SUN_ARCH"-pc-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
exit ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
echo sparc-sun-solaris3"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
exit ;;
sun4*:SunOS:*:*)
case "$(/usr/bin/arch -k)" in
Series*|S4*)
UNAME_RELEASE=$(uname -v)
;;
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
echo sparc-sun-sunos"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/')"
exit ;;
sun3*:SunOS:*:*)
echo m68k-sun-sunos"$UNAME_RELEASE"
exit ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=$( (sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null)
test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
case "$(/bin/arch)" in
sun3)
echo m68k-sun-sunos"$UNAME_RELEASE"
;;
sun4)
echo sparc-sun-sunos"$UNAME_RELEASE"
;;
esac
exit ;;
aushp:SunOS:*:*)
echo sparc-auspex-sunos"$UNAME_RELEASE"
exit ;;
# The situation for MiNT is a little confusing. The machine name
# can be virtually everything (everything which is not
# "atarist" or "atariste" at least should have a processor
# > m68000). The system name ranges from "MiNT" over "FreeMiNT"
# to the lowercase version "mint" (or "freemint"). Finally
# the system name "TOS" denotes a system which is actually not
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint"$UNAME_RELEASE"
exit ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint"$UNAME_RELEASE"
exit ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
echo m68k-atari-mint"$UNAME_RELEASE"
exit ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
echo m68k-milan-mint"$UNAME_RELEASE"
exit ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
echo m68k-hades-mint"$UNAME_RELEASE"
exit ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
echo m68k-unknown-mint"$UNAME_RELEASE"
exit ;;
m68k:machten:*:*)
echo m68k-apple-machten"$UNAME_RELEASE"
exit ;;
powerpc:machten:*:*)
echo powerpc-apple-machten"$UNAME_RELEASE"
exit ;;
RISC*:Mach:*:*)
echo mips-dec-mach_bsd4.3
exit ;;
RISC*:ULTRIX:*:*)
echo mips-dec-ultrix"$UNAME_RELEASE"
exit ;;
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix"$UNAME_RELEASE"
exit ;;
2020:CLIX:*:* | 2430:CLIX:*:*)
echo clipper-intergraph-clix"$UNAME_RELEASE"
exit ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
set_cc_for_build
sed 's/^ //' << EOF > "$dummy.c"
#ifdef __cplusplus
#include /* for printf() prototype */
int main (int argc, char *argv[]) {
#else
int main (argc, argv) int argc; char *argv[]; {
#endif
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
}
EOF
$CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
dummyarg=$(echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p') &&
SYSTEM_NAME=$("$dummy" "$dummyarg") &&
{ echo "$SYSTEM_NAME"; exit; }
echo mips-mips-riscos"$UNAME_RELEASE"
exit ;;
Motorola:PowerMAX_OS:*:*)
echo powerpc-motorola-powermax
exit ;;
Motorola:*:4.3:PL8-*)
echo powerpc-harris-powermax
exit ;;
Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
echo powerpc-harris-powermax
exit ;;
Night_Hawk:Power_UNIX:*:*)
echo powerpc-harris-powerunix
exit ;;
m88k:CX/UX:7*:*)
echo m88k-harris-cxux7
exit ;;
m88k:*:4*:R4*)
echo m88k-motorola-sysv4
exit ;;
m88k:*:3*:R3*)
echo m88k-motorola-sysv3
exit ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=$(/usr/bin/uname -p)
if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
then
if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
test "$TARGET_BINARY_INTERFACE"x = x
then
echo m88k-dg-dgux"$UNAME_RELEASE"
else
echo m88k-dg-dguxbcs"$UNAME_RELEASE"
fi
else
echo i586-dg-dgux"$UNAME_RELEASE"
fi
exit ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
echo m88k-motorola-sysv3
exit ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
echo m88k-tektronix-sysv3
exit ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
echo m68k-tektronix-bsd
exit ;;
*:IRIX*:*:*)
echo mips-sgi-irix"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/g')"
exit ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
exit ;; # Note that: echo "'$(uname -s)'" gives 'AIX '
i*86:AIX:*:*)
echo i386-ibm-aix
exit ;;
ia64:AIX:*:*)
if test -x /usr/bin/oslevel ; then
IBM_REV=$(/usr/bin/oslevel)
else
IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
fi
echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV"
exit ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
set_cc_for_build
sed 's/^ //' << EOF > "$dummy.c"
#include
main()
{
if (!__power_pc())
exit(1);
puts("powerpc-ibm-aix3.2.5");
exit(0);
}
EOF
if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy")
then
echo "$SYSTEM_NAME"
else
echo rs6000-ibm-aix3.2.5
fi
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
echo rs6000-ibm-aix3.2.4
else
echo rs6000-ibm-aix3.2
fi
exit ;;
*:AIX:*:[4567])
IBM_CPU_ID=$(/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }')
if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
if test -x /usr/bin/lslpp ; then
IBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc |
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/)
else
IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
fi
echo "$IBM_ARCH"-ibm-aix"$IBM_REV"
exit ;;
*:AIX:*:*)
echo rs6000-ibm-aix
exit ;;
ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
echo romp-ibm-bsd4.4
exit ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to
exit ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
exit ;;
DPX/2?00:B.O.S.:*:*)
echo m68k-bull-sysv3
exit ;;
9000/[34]??:4.3bsd:1.*:*)
echo m68k-hp-bsd
exit ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
exit ;;
9000/[34678]??:HP-UX:*:*)
HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//')
case "$UNAME_MACHINE" in
9000/31?) HP_ARCH=m68000 ;;
9000/[34]??) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
if test -x /usr/bin/getconf; then
sc_cpu_version=$(/usr/bin/getconf SC_CPU_VERSION 2>/dev/null)
sc_kernel_bits=$(/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null)
case "$sc_cpu_version" in
523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case "$sc_kernel_bits" in
32) HP_ARCH=hppa2.0n ;;
64) HP_ARCH=hppa2.0w ;;
'') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
esac ;;
esac
fi
if test "$HP_ARCH" = ""; then
set_cc_for_build
sed 's/^ //' << EOF > "$dummy.c"
#define _HPUX_SOURCE
#include
#include
int main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
#endif
long cpu = sysconf (_SC_CPU_VERSION);
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
case CPU_PA_RISC2_0:
#if defined(_SC_KERNEL_BITS)
switch (bits)
{
case 64: puts ("hppa2.0w"); break;
case 32: puts ("hppa2.0n"); break;
default: puts ("hppa2.0"); break;
} break;
#else /* !defined(_SC_KERNEL_BITS) */
puts ("hppa2.0"); break;
#endif
default: puts ("hppa1.0"); break;
}
exit (0);
}
EOF
(CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=$("$dummy")
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
if test "$HP_ARCH" = hppa2.0w
then
set_cc_for_build
# hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
# 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
# generating 64-bit code. GNU and HP use different nomenclature:
#
# $ CC_FOR_BUILD=cc ./config.guess
# => hppa2.0w-hp-hpux11.23
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
# => hppa64-hp-hpux11.23
if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
grep -q __LP64__
then
HP_ARCH=hppa2.0w
else
HP_ARCH=hppa64
fi
fi
echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
exit ;;
ia64:HP-UX:*:*)
HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//')
echo ia64-hp-hpux"$HPUX_REV"
exit ;;
3050*:HI-UX:*:*)
set_cc_for_build
sed 's/^ //' << EOF > "$dummy.c"
#include
int
main ()
{
long cpu = sysconf (_SC_CPU_VERSION);
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
results, however. */
if (CPU_IS_PA_RISC (cpu))
{
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
default: puts ("hppa-hitachi-hiuxwe2"); break;
}
}
else if (CPU_IS_HP_MC68K (cpu))
puts ("m68k-hitachi-hiuxwe2");
else puts ("unknown-hitachi-hiuxwe2");
exit (0);
}
EOF
$CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") &&
{ echo "$SYSTEM_NAME"; exit; }
echo unknown-hitachi-hiuxwe2
exit ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
echo hppa1.1-hp-bsd
exit ;;
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
exit ;;
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
echo hppa1.0-hp-mpeix
exit ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
echo hppa1.1-hp-osf
exit ;;
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
exit ;;
i*86:OSF1:*:*)
if test -x /usr/sbin/sysversion ; then
echo "$UNAME_MACHINE"-unknown-osf1mk
else
echo "$UNAME_MACHINE"-unknown-osf1
fi
exit ;;
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
exit ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
exit ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
exit ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*[A-Z]90:*:*:*)
echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
exit ;;
CRAY*TS:*:*:*)
echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*T3E:*:*:*)
echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*SV1:*:*:*)
echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
*:UNICOS/mp:*:*)
echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=$(uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)
FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///')
FUJITSU_REL=$(echo "$UNAME_RELEASE" | sed -e 's/ /_/')
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
5000:UNIX_System_V:4.*:*)
FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///')
FUJITSU_REL=$(echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/')
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE"
exit ;;
sparc*:BSD/OS:*:*)
echo sparc-unknown-bsdi"$UNAME_RELEASE"
exit ;;
*:BSD/OS:*:*)
echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
exit ;;
arm:FreeBSD:*:*)
UNAME_PROCESSOR=$(uname -p)
set_cc_for_build
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabi
else
echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabihf
fi
exit ;;
*:FreeBSD:*:*)
UNAME_PROCESSOR=$(/usr/bin/uname -p)
case "$UNAME_PROCESSOR" in
amd64)
UNAME_PROCESSOR=x86_64 ;;
i386)
UNAME_PROCESSOR=i586 ;;
esac
echo "$UNAME_PROCESSOR"-unknown-freebsd"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')"
exit ;;
i*:CYGWIN*:*)
echo "$UNAME_MACHINE"-pc-cygwin
exit ;;
*:MINGW64*:*)
echo "$UNAME_MACHINE"-pc-mingw64
exit ;;
*:MINGW*:*)
echo "$UNAME_MACHINE"-pc-mingw32
exit ;;
*:MSYS*:*)
echo "$UNAME_MACHINE"-pc-msys
exit ;;
i*:PW*:*)
echo "$UNAME_MACHINE"-pc-pw32
exit ;;
*:Interix*:*)
case "$UNAME_MACHINE" in
x86)
echo i586-pc-interix"$UNAME_RELEASE"
exit ;;
authenticamd | genuineintel | EM64T)
echo x86_64-unknown-interix"$UNAME_RELEASE"
exit ;;
IA64)
echo ia64-unknown-interix"$UNAME_RELEASE"
exit ;;
esac ;;
i*:UWIN*:*)
echo "$UNAME_MACHINE"-pc-uwin
exit ;;
amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
echo x86_64-pc-cygwin
exit ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
exit ;;
*:GNU:*:*)
# the GNU system
echo "$(echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,')-unknown-$LIBC$(echo "$UNAME_RELEASE"|sed -e 's,/.*$,,')"
exit ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
echo "$UNAME_MACHINE-unknown-$(echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]")$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')-$LIBC"
exit ;;
*:Minix:*:*)
echo "$UNAME_MACHINE"-unknown-minix
exit ;;
aarch64:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
alpha:Linux:*:*)
case $(sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null) in
EV5) UNAME_MACHINE=alphaev5 ;;
EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;;
PCA57) UNAME_MACHINE=alphapca56 ;;
EV6) UNAME_MACHINE=alphaev6 ;;
EV67) UNAME_MACHINE=alphaev67 ;;
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
arc:Linux:*:* | arceb:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
arm*:Linux:*:*)
set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
else
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
fi
fi
exit ;;
avr32*:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
cris:Linux:*:*)
echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
exit ;;
crisv32:Linux:*:*)
echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
exit ;;
e2k:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
frv:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
hexagon:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
i*86:Linux:*:*)
echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
exit ;;
ia64:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
k1om:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
m32r*:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
m68*:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
mips:Linux:*:* | mips64:Linux:*:*)
set_cc_for_build
IS_GLIBC=0
test x"${LIBC}" = xgnu && IS_GLIBC=1
sed 's/^ //' << EOF > "$dummy.c"
#undef CPU
#undef mips
#undef mipsel
#undef mips64
#undef mips64el
#if ${IS_GLIBC} && defined(_ABI64)
LIBCABI=gnuabi64
#else
#if ${IS_GLIBC} && defined(_ABIN32)
LIBCABI=gnuabin32
#else
LIBCABI=${LIBC}
#endif
#endif
#if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
CPU=mipsisa64r6
#else
#if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
CPU=mipsisa32r6
#else
#if defined(__mips64)
CPU=mips64
#else
CPU=mips
#endif
#endif
#endif
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
MIPS_ENDIAN=el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
MIPS_ENDIAN=
#else
MIPS_ENDIAN=
#endif
#endif
EOF
eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI')"
test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
;;
mips64el:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
openrisc*:Linux:*:*)
echo or1k-unknown-linux-"$LIBC"
exit ;;
or32:Linux:*:* | or1k*:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
padre:Linux:*:*)
echo sparc-unknown-linux-"$LIBC"
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-"$LIBC"
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case $(grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2) in
PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
*) echo hppa-unknown-linux-"$LIBC" ;;
esac
exit ;;
ppc64:Linux:*:*)
echo powerpc64-unknown-linux-"$LIBC"
exit ;;
ppc:Linux:*:*)
echo powerpc-unknown-linux-"$LIBC"
exit ;;
ppc64le:Linux:*:*)
echo powerpc64le-unknown-linux-"$LIBC"
exit ;;
ppcle:Linux:*:*)
echo powerpcle-unknown-linux-"$LIBC"
exit ;;
riscv32:Linux:*:* | riscv64:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
exit ;;
sh64*:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
sh*:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
tile*:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
vax:Linux:*:*)
echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
exit ;;
x86_64:Linux:*:*)
set_cc_for_build
LIBCABI=$LIBC
if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_X32 >/dev/null
then
LIBCABI="$LIBC"x32
fi
fi
echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI"
exit ;;
xtensa*:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
# sysname and nodename.
echo i386-sequent-sysv4
exit ;;
i*86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION"
exit ;;
i*86:OS/2:*:*)
# If we were able to find `uname', then EMX Unix compatibility
# is probably installed.
echo "$UNAME_MACHINE"-pc-os2-emx
exit ;;
i*86:XTS-300:*:STOP)
echo "$UNAME_MACHINE"-unknown-stop
exit ;;
i*86:atheos:*:*)
echo "$UNAME_MACHINE"-unknown-atheos
exit ;;
i*86:syllable:*:*)
echo "$UNAME_MACHINE"-pc-syllable
exit ;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
echo i386-unknown-lynxos"$UNAME_RELEASE"
exit ;;
i*86:*DOS:*:*)
echo "$UNAME_MACHINE"-pc-msdosdjgpp
exit ;;
i*86:*:4.*:*)
UNAME_REL=$(echo "$UNAME_RELEASE" | sed 's/\/MP$//')
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
else
echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL"
fi
exit ;;
i*86:*:5:[678]*)
# UnixWare 7.x, OpenUNIX and OpenServer 6.
case $(/bin/uname -X | grep "^Machine") in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
esac
echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}"
exit ;;
i*86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=$(sed -n 's/.*Version //p' /dev/null >/dev/null ; then
UNAME_REL=$( (/bin/uname -X|grep Release|sed -e 's/.*= //'))
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
&& UNAME_MACHINE=i686
(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
&& UNAME_MACHINE=i686
echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL"
else
echo "$UNAME_MACHINE"-pc-sysv32
fi
exit ;;
pc:*:*:*)
# Left here for compatibility:
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
# prints for the "djgpp" host, or else GDB configure will decide that
# this is a cross-build.
echo i586-pc-msdosdjgpp
exit ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
exit ;;
paragon:*:*:*)
echo i860-intel-osf1
exit ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4
fi
exit ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
echo m68010-convergent-sysv
exit ;;
mc68k:UNIX:SYSTEM5:3.51m)
echo m68k-convergent-sysv
exit ;;
M680?0:D-NIX:5.3:*)
echo m68k-diab-dnix
exit ;;
M68*:*:R3V[5678]*:*)
test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
OS_REL='.3'
test -r /etc/.relid \
&& OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
&& { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
echo m68k-unknown-lynxos"$UNAME_RELEASE"
exit ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit ;;
TSUNAMI:LynxOS:2.*:*)
echo sparc-unknown-lynxos"$UNAME_RELEASE"
exit ;;
rs6000:LynxOS:2.*:*)
echo rs6000-unknown-lynxos"$UNAME_RELEASE"
exit ;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
echo powerpc-unknown-lynxos"$UNAME_RELEASE"
exit ;;
SM[BE]S:UNIX_SV:*:*)
echo mips-dde-sysv"$UNAME_RELEASE"
exit ;;
RM*:ReliantUNIX-*:*:*)
echo mips-sni-sysv4
exit ;;
RM*:SINIX-*:*:*)
echo mips-sni-sysv4
exit ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=$( (uname -p) 2>/dev/null)
echo "$UNAME_MACHINE"-sni-sysv4
else
echo ns32k-sni-sysv
fi
exit ;;
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says
echo i586-unisys-sysv4
exit ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes .
# How about differentiating between stratus architectures? -djm
echo hppa1.1-stratus-sysv4
exit ;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
echo i860-stratus-sysv4
exit ;;
i*86:VOS:*:*)
# From Paul.Green@stratus.com.
echo "$UNAME_MACHINE"-stratus-vos
exit ;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
echo hppa1.1-stratus-vos
exit ;;
mc68*:A/UX:*:*)
echo m68k-apple-aux"$UNAME_RELEASE"
exit ;;
news*:NEWS-OS:6*:*)
echo mips-sony-newsos6
exit ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if test -d /usr/nec; then
echo mips-nec-sysv"$UNAME_RELEASE"
else
echo mips-unknown-sysv"$UNAME_RELEASE"
fi
exit ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
echo powerpc-be-beos
exit ;;
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
echo powerpc-apple-beos
exit ;;
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
echo i586-pc-beos
exit ;;
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
echo i586-pc-haiku
exit ;;
x86_64:Haiku:*:*)
echo x86_64-unknown-haiku
exit ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux"$UNAME_RELEASE"
exit ;;
SX-5:SUPER-UX:*:*)
echo sx5-nec-superux"$UNAME_RELEASE"
exit ;;
SX-6:SUPER-UX:*:*)
echo sx6-nec-superux"$UNAME_RELEASE"
exit ;;
SX-7:SUPER-UX:*:*)
echo sx7-nec-superux"$UNAME_RELEASE"
exit ;;
SX-8:SUPER-UX:*:*)
echo sx8-nec-superux"$UNAME_RELEASE"
exit ;;
SX-8R:SUPER-UX:*:*)
echo sx8r-nec-superux"$UNAME_RELEASE"
exit ;;
SX-ACE:SUPER-UX:*:*)
echo sxace-nec-superux"$UNAME_RELEASE"
exit ;;
Power*:Rhapsody:*:*)
echo powerpc-apple-rhapsody"$UNAME_RELEASE"
exit ;;
*:Rhapsody:*:*)
echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
exit ;;
arm64:Darwin:*:*)
echo aarch64-apple-darwin"$UNAME_RELEASE"
exit ;;
*:Darwin:*:*)
UNAME_PROCESSOR=$(uname -p)
case $UNAME_PROCESSOR in
unknown) UNAME_PROCESSOR=powerpc ;;
esac
if command -v xcode-select > /dev/null 2> /dev/null && \
! xcode-select --print-path > /dev/null 2> /dev/null ; then
# Avoid executing cc if there is no toolchain installed as
# cc will be a stub that puts up a graphical alert
# prompting the user to install developer tools.
CC_FOR_BUILD=no_compiler_found
else
set_cc_for_build
fi
if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
case $UNAME_PROCESSOR in
i386) UNAME_PROCESSOR=x86_64 ;;
powerpc) UNAME_PROCESSOR=powerpc64 ;;
esac
fi
# On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_PPC >/dev/null
then
UNAME_PROCESSOR=powerpc
fi
elif test "$UNAME_PROCESSOR" = i386 ; then
# uname -m returns i386 or x86_64
UNAME_PROCESSOR=$UNAME_MACHINE
fi
echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=$(uname -p)
if test "$UNAME_PROCESSOR" = x86; then
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
fi
echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE"
exit ;;
*:QNX:*:4*)
echo i386-pc-qnx
exit ;;
NEO-*:NONSTOP_KERNEL:*:*)
echo neo-tandem-nsk"$UNAME_RELEASE"
exit ;;
NSE-*:NONSTOP_KERNEL:*:*)
echo nse-tandem-nsk"$UNAME_RELEASE"
exit ;;
NSR-*:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk"$UNAME_RELEASE"
exit ;;
NSV-*:NONSTOP_KERNEL:*:*)
echo nsv-tandem-nsk"$UNAME_RELEASE"
exit ;;
NSX-*:NONSTOP_KERNEL:*:*)
echo nsx-tandem-nsk"$UNAME_RELEASE"
exit ;;
*:NonStop-UX:*:*)
echo mips-compaq-nonstopux
exit ;;
BS2000:POSIX*:*:*)
echo bs2000-siemens-sysv
exit ;;
DS/*:UNIX_System_V:*:*)
echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE"
exit ;;
*:Plan9:*:*)
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
# operating systems.
# shellcheck disable=SC2154
if test "$cputype" = 386; then
UNAME_MACHINE=i386
else
UNAME_MACHINE="$cputype"
fi
echo "$UNAME_MACHINE"-unknown-plan9
exit ;;
*:TOPS-10:*:*)
echo pdp10-unknown-tops10
exit ;;
*:TENEX:*:*)
echo pdp10-unknown-tenex
exit ;;
KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
echo pdp10-dec-tops20
exit ;;
XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
echo pdp10-xkl-tops20
exit ;;
*:TOPS-20:*:*)
echo pdp10-unknown-tops20
exit ;;
*:ITS:*:*)
echo pdp10-unknown-its
exit ;;
SEI:*:*:SEIUX)
echo mips-sei-seiux"$UNAME_RELEASE"
exit ;;
*:DragonFly:*:*)
echo "$UNAME_MACHINE"-unknown-dragonfly"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')"
exit ;;
*:*VMS:*:*)
UNAME_MACHINE=$( (uname -p) 2>/dev/null)
case "$UNAME_MACHINE" in
A*) echo alpha-dec-vms ; exit ;;
I*) echo ia64-dec-vms ; exit ;;
V*) echo vax-dec-vms ; exit ;;
esac ;;
*:XENIX:*:SysV)
echo i386-pc-xenix
exit ;;
i*86:skyos:*:*)
echo "$UNAME_MACHINE"-pc-skyos"$(echo "$UNAME_RELEASE" | sed -e 's/ .*$//')"
exit ;;
i*86:rdos:*:*)
echo "$UNAME_MACHINE"-pc-rdos
exit ;;
i*86:AROS:*:*)
echo "$UNAME_MACHINE"-pc-aros
exit ;;
x86_64:VMkernel:*:*)
echo "$UNAME_MACHINE"-unknown-esx
exit ;;
amd64:Isilon\ OneFS:*:*)
echo x86_64-unknown-onefs
exit ;;
*:Unleashed:*:*)
echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE"
exit ;;
esac
# No uname command or uname output not recognized.
set_cc_for_build
cat > "$dummy.c" <
#include
#endif
#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
#include
#if defined(_SIZE_T_) || defined(SIGLOST)
#include
#endif
#endif
#endif
main ()
{
#if defined (sony)
#if defined (MIPSEB)
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
I don't know.... */
printf ("mips-sony-bsd\n"); exit (0);
#else
#include
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
"4"
#else
""
#endif
); exit (0);
#endif
#endif
#if defined (NeXT)
#if !defined (__ARCHITECTURE__)
#define __ARCHITECTURE__ "m68k"
#endif
int version;
version=$( (hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null);
if (version < 4)
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
else
printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
exit (0);
#endif
#if defined (MULTIMAX) || defined (n16)
#if defined (UMAXV)
printf ("ns32k-encore-sysv\n"); exit (0);
#else
#if defined (CMU)
printf ("ns32k-encore-mach\n"); exit (0);
#else
printf ("ns32k-encore-bsd\n"); exit (0);
#endif
#endif
#endif
#if defined (__386BSD__)
printf ("i386-pc-bsd\n"); exit (0);
#endif
#if defined (sequent)
#if defined (i386)
printf ("i386-sequent-dynix\n"); exit (0);
#endif
#if defined (ns32000)
printf ("ns32k-sequent-dynix\n"); exit (0);
#endif
#endif
#if defined (_SEQUENT_)
struct utsname un;
uname(&un);
if (strncmp(un.version, "V2", 2) == 0) {
printf ("i386-sequent-ptx2\n"); exit (0);
}
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
printf ("i386-sequent-ptx1\n"); exit (0);
}
printf ("i386-sequent-ptx\n"); exit (0);
#endif
#if defined (vax)
#if !defined (ultrix)
#include
#if defined (BSD)
#if BSD == 43
printf ("vax-dec-bsd4.3\n"); exit (0);
#else
#if BSD == 199006
printf ("vax-dec-bsd4.3reno\n"); exit (0);
#else
printf ("vax-dec-bsd\n"); exit (0);
#endif
#endif
#else
printf ("vax-dec-bsd\n"); exit (0);
#endif
#else
#if defined(_SIZE_T_) || defined(SIGLOST)
struct utsname un;
uname (&un);
printf ("vax-dec-ultrix%s\n", un.release); exit (0);
#else
printf ("vax-dec-ultrix\n"); exit (0);
#endif
#endif
#endif
#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
#if defined(_SIZE_T_) || defined(SIGLOST)
struct utsname *un;
uname (&un);
printf ("mips-dec-ultrix%s\n", un.release); exit (0);
#else
printf ("mips-dec-ultrix\n"); exit (0);
#endif
#endif
#endif
#if defined (alliant) && defined (i860)
printf ("i860-alliant-bsd\n"); exit (0);
#endif
exit (1);
}
EOF
$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=$($dummy) &&
{ echo "$SYSTEM_NAME"; exit; }
# Apollos put the system type in the environment.
test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
echo "$0: unable to guess system type" >&2
case "$UNAME_MACHINE:$UNAME_SYSTEM" in
mips:Linux | mips64:Linux)
# If we got here on MIPS GNU/Linux, output extra information.
cat >&2 <&2 <&2 </dev/null || echo unknown)
uname -r = $( (uname -r) 2>/dev/null || echo unknown)
uname -s = $( (uname -s) 2>/dev/null || echo unknown)
uname -v = $( (uname -v) 2>/dev/null || echo unknown)
/usr/bin/uname -p = $( (/usr/bin/uname -p) 2>/dev/null)
/bin/uname -X = $( (/bin/uname -X) 2>/dev/null)
hostinfo = $( (hostinfo) 2>/dev/null)
/bin/universe = $( (/bin/universe) 2>/dev/null)
/usr/bin/arch -k = $( (/usr/bin/arch -k) 2>/dev/null)
/bin/arch = $( (/bin/arch) 2>/dev/null)
/usr/bin/oslevel = $( (/usr/bin/oslevel) 2>/dev/null)
/usr/convex/getsysinfo = $( (/usr/convex/getsysinfo) 2>/dev/null)
UNAME_MACHINE = "$UNAME_MACHINE"
UNAME_RELEASE = "$UNAME_RELEASE"
UNAME_SYSTEM = "$UNAME_SYSTEM"
UNAME_VERSION = "$UNAME_VERSION"
EOF
fi
exit 1
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
Rserve/tools/m4/ 0000755 0001760 0000144 00000000000 14147646005 013237 5 ustar ripley users Rserve/tools/m4/ax_pthread.m4 0000644 0001760 0000144 00000033603 14147646005 015625 0 ustar ripley users # ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
#
# DESCRIPTION
#
# This macro figures out how to build C programs using POSIX threads. It
# sets the PTHREAD_LIBS output variable to the threads library and linker
# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
# flags that are needed. (The user can also force certain compiler
# flags/libs to be tested by setting these environment variables.)
#
# Also sets PTHREAD_CC to any special C compiler that is needed for
# multi-threaded programs (defaults to the value of CC otherwise). (This
# is necessary on AIX to use the special cc_r compiler alias.)
#
# NOTE: You are assumed to not only compile your program with these flags,
# but also link it with them as well. e.g. you should link with
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
#
# If you are only building threads programs, you may wish to use these
# variables in your default LIBS, CFLAGS, and CC:
#
# LIBS="$PTHREAD_LIBS $LIBS"
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# CC="$PTHREAD_CC"
#
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
#
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
# PTHREAD_CFLAGS.
#
# ACTION-IF-FOUND is a list of shell commands to run if a threads library
# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
# is not found. If ACTION-IF-FOUND is not specified, the default action
# will define HAVE_PTHREAD.
#
# Please let the authors know if this macro fails on any platform, or if
# you have any other suggestions or comments. This macro was based on work
# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
# Alejandro Forero Cuervo to the autoconf macro repository. We are also
# grateful for the helpful feedback of numerous users.
#
# Updated for Autoconf 2.68 by Daniel Richard G.
# Updated to work around issues in RedHat by Simon Urbanek
#
# LICENSE
#
# Copyright (c) 2008 Steven G. Johnson
# Copyright (c) 2011 Daniel Richard G.
# Copyright (c) 2015 Simon Urbanek
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see .
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 21
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
AC_DEFUN([AX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
AC_LANG_PUSH([C])
ax_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on True64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes])
AC_MSG_RESULT([$ax_pthread_ok])
if test x"$ax_pthread_ok" = xno; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
fi
# We must check for the threads library under a number of different
# names; the ordering is very important because some systems
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items starting with a "-" are
# C compiler flags, and other items are library names, except for "none"
# which indicates that we try without any flags at all, and "pthread-config"
# which is a program returning the flags for the Pth emulation library.
ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
# pthreads: AIX (must check this before -lpthread)
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
# -pthreads: Solaris/gcc
# -mthreads: Mingw32/gcc, Lynx/gcc
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads too;
# also defines -D_REENTRANT)
# ... -mt is also the pthreads flag for HP/aCC
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)
case ${host_os} in
solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
# a function called by this macro, so we could check for that, but
# who knows whether they'll stub that too in a future libc.) So,
# we'll just look for -pthreads and -lpthread first:
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
;;
darwin*)
ax_pthread_flags="-pthread $ax_pthread_flags"
;;
esac
# Clang doesn't consider unrecognized options an error unless we specify
# -Werror. We throw in some extra Clang-specific options to ensure that
# this doesn't happen for GCC, which also accepts -Werror.
AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags])
save_CFLAGS="$CFLAGS"
ax_pthread_extra_flags="-Werror"
CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])],
[AC_MSG_RESULT([yes])],
[ax_pthread_extra_flags=
AC_MSG_RESULT([no])])
CFLAGS="$save_CFLAGS"
if test x"$ax_pthread_ok" = xno; then
for flag in $ax_pthread_flags; do
case $flag in
none)
AC_MSG_CHECKING([whether pthreads work without any flags])
;;
-*)
AC_MSG_CHECKING([whether pthreads work with $flag])
PTHREAD_CFLAGS="$flag"
;;
pthread-config)
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
if test x"$ax_pthread_config" = xno; then continue; fi
PTHREAD_CFLAGS="`pthread-config --cflags`"
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
;;
*)
AC_MSG_CHECKING([for the pthreads library -l$flag])
PTHREAD_LIBS="-l$flag"
;;
esac
save_LIBS="$LIBS"
save_CFLAGS="$CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
# need a special flag -Kthread to make this header compile.)
# We check for pthread_join because it is in -lpthread on IRIX
# while pthread_create is in libc. We check for pthread_attr_init
# due to DEC craziness with -lpthreads. We check for
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
# NOTE: RedHat is broken and requires an explicit
# inclusion of pthread_atfork in the test otherwise it
# will appear to work without -pthread even though it doesn't.
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include
static void routine(void *a) { a = 0; }
static void atfork_null() { }
static void *start_routine(void *a) { return a; }],
[pthread_t th; pthread_attr_t attr;
pthread_atfork(atfork_null, atfork_null, atfork_null);
pthread_create(&th, 0, start_routine, 0);
pthread_join(th, 0);
pthread_attr_init(&attr);
pthread_cleanup_push(routine, 0);
pthread_cleanup_pop(0) /* ; */])],
[ax_pthread_ok=yes],
[])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
AC_MSG_RESULT([$ax_pthread_ok])
if test "x$ax_pthread_ok" = xyes; then
break;
fi
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
done
fi
# Various other checks:
if test "x$ax_pthread_ok" = xyes; then
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
AC_MSG_CHECKING([for joinable pthread attribute])
attr_name=unknown
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ],
[int attr = $attr; return attr /* ; */])],
[attr_name=$attr; break],
[])
done
AC_MSG_RESULT([$attr_name])
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name],
[Define to necessary symbol if this constant
uses a non-standard name on your system.])
fi
AC_MSG_CHECKING([if more special flags are required for pthreads])
flag=no
case ${host_os} in
aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
osf* | hpux*) flag="-D_REENTRANT";;
solaris*)
if test "$GCC" = "yes"; then
flag="-D_REENTRANT"
else
# TODO: What about Clang on Solaris?
flag="-mt -D_REENTRANT"
fi
;;
esac
AC_MSG_RESULT([$flag])
if test "x$flag" != xno; then
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
fi
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
[ax_cv_PTHREAD_PRIO_INHERIT], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]],
[[int i = PTHREAD_PRIO_INHERIT;]])],
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
[ax_cv_PTHREAD_PRIO_INHERIT=no])
])
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
# More AIX lossage: compile with *_r variant
if test "x$GCC" != xyes; then
case $host_os in
aix*)
AS_CASE(["x/$CC"],
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
[#handle absolute path differently from PATH based program lookup
AS_CASE(["x$CC"],
[x/*],
[AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
[AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
;;
esac
fi
fi
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
AC_SUBST([PTHREAD_LIBS])
AC_SUBST([PTHREAD_CFLAGS])
AC_SUBST([PTHREAD_CC])
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test x"$ax_pthread_ok" = xyes; then
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
:
else
ax_pthread_ok=no
$2
fi
AC_LANG_POP
])dnl AX_PTHREAD
Rserve/man/ 0000755 0001760 0000144 00000000000 14147646005 012332 5 ustar ripley users Rserve/man/Rserv.Rd 0000644 0001760 0000144 00000005243 14147646005 013726 0 ustar ripley users \name{Rserve}
\title{Server providing R functionality to applications via TCP/IP or local unix sockets}
\alias{Rserve}
\usage{
# R CMD Rserve []
Rserve(debug = FALSE, port, args = NULL, quote=(length(args) > 1), wait, ...)
}
\description{
Starts Rserve in daemon mode (unix only). Any additional parameters
not related to Rserve will be passed straight to the underlying R. For
configuration, usage and command line parameters please consult the
online documentation at http://www.rforge.net/Rserve.
Use \code{R CMD Rserve --help} for a brief help.
The \code{Rserve} function is provided for convenience only.
On Windows the \code{Rserve()} function sets up the \code{PATH} to
include the current R.DLL so that Rserve can be run.
}
\arguments{
\item{debug}{determines whether regular Rserve or debug version of
Rserve (\code{Rserve.dbg}) should be started.}
\item{port}{port used by Rserve to listen for connections. If not
specified, it will be taken from the configuration file (if present)
or default to 6311}
\item{args}{further arguments passed to Rserve (as a string that will be
passed to the \code{system} command - see \code{quote} below).}
\item{quote}{logical, if \code{TRUE} then arguments are quoted,
otherwise they are just joined with spaces}
\item{wait}{wait argument for the \code{\link{system}} call. It defaults
to \code{FALSE} on Windows and \code{TRUE} elsewhere.}
\item{\dots}{other arguments to be passes to \code{\link{system}}.}
}
\details{
Rserve is not just a package, but an application. It is provided as a
R package for convenience only. For details see
http://www.rforge.net/Rserve
}
\note{
\code{R CMD Rserve} will only work on unix when installed from
\emph{sources} and with sufficient permissions to have write-rights in
\code{$R_HOME/bin}. Binary installations have no way to write in
\code{$R_HOME/bin} and thus \code{Rserve()} function described above
is the only reliable way to start \code{Rserve} in that case.
Java developers may want to see the \code{StartRserve} class in
\code{java/Rserve/test} examples for easy way to start \code{Rserve}
from Java.
Rserve can be compiled with TLS/SSL support based on
OpenSSL. Therefore the following statements may be true if Rserve
binaries are shipped together with OpenSSL: This product includes
software developed by the OpenSSL Project for use in the OpenSSL
Toolkit (http://www.openssl.org/). This product includes cryptographic
software written by Eric Young (eay@cryptsoft.com). This product
includes software written by Tim Hudson (tjh@cryptsoft.com). They are
not true otherwise.
}
\seealso{\code{\link{run.Rserve}}}
\author{Simon Urbanek}
\keyword{interface}
Rserve/man/ulog.Rd 0000644 0001760 0000144 00000002100 14147646005 013560 0 ustar ripley users \name{ulog}
\title{Micro Logging}
\alias{ulog}
\usage{
ulog(...)
}
\description{
\code{ulog} logs the supplied message using the \code{ulog}
facility which typically corresponsed to syslog. See \code{ulog}
Rserve configuration for the various endpoints supported by ulog
(local, UDP/TCP remote, ...).
This function is guaranteed to be silent regardless of the ulog
setting and is intended to have minimal performance impact.
Note: if Rserve is compiled with \code{-DULOG_STDERR} (also
implied in the debug build) then ulog messages are also emitted
on \code{stderr} with \code{"ULOG: "} prefix.
Please note that this \code{ulog} function is governed by the Rserve
settings, and NOT the \code{ulog} package settings. The latter is a
general port of the \code{ulog} logging facility to R, while
\code{Rserve::ulog} is specific to to the Rserve process.
}
\arguments{
\item{...}{message to log}
}
\value{
The logged string constructed from the message, invisibly
}
\examples{
ulog("INFO: My application started")
}
\author{Simon Urbanek}
\keyword{interface}
Rserve/man/self.Rd 0000644 0001760 0000144 00000004540 14147646005 013555 0 ustar ripley users \name{self}
\title{Functions usable for R code run inside Rserve}
\alias{self.ctrlEval}
\alias{self.ctrlSource}
\alias{self.oobSend}
\alias{self.oobMessage}
\usage{
self.ctrlEval(expr)
self.ctrlSource(file)
self.oobSend(what, code = 0L)
self.oobMessage(what, code = 0L)
}
\description{
The following functions can only be used inside Rserve, they cannot be
used in stand-alone R. They interact with special features of Rserve.
All commands below will succeed only if Rserve has been started with
\code{r-control enable} configuration setting for security reasons.
\code{self.ctrlEval} issues a control command to the Rserve parent
instance that evaluates the given expression in the server. The
expression is only queued for evaluation which will happen
asynchronously in the server (see \code{RSserverEval} in
\code{RSclient} package for details). Note that the current session is
unaffected by the command.
\code{self.ctrlSource} issues a control command to the Rserve parent
instance to source the given file in the server, see
\code{RSserverSource} in the \code{RSclient} package for details.
\code{self.oobSend} sends a out-of-band (OOB) message with the encoded
content of \code{what} to the client connected to this session. The
OOB facility must be enabled in the Rserve configuration (using
\code{oob enable}) and the client must support OOB messages for this
to be meaningful. This facility is not used by Rserve itself, it is
offered to specialized applications (e.g. \code{Cairo} supports
asynchronous notification of web clients using WebSockets-QAP1 tunnel
to dynamically update graphics on the web during evaluation).
\code{self.oobMessage} is like \code{self.oobSend} except that it
waits for a response and returns the response.
}
\arguments{
\item{expr}{R expression to evaluate remotely}
\item{file}{path to a file that will be sourced into the main
instance}
\item{what}{object to include as the payload fo the message}
\item{code}{user-defined message code that will be ORed with the
\code{OOB_SEND}/\code{OOB_MSG} message code}
}
\value{
\code{oobMessage} returns data contained in the response message.
All other functions return \code{TRUE} (invisibly).
}
\examples{
\dontrun{
self.ctrlEval("a <- rnorm(10)")
self.oobSend(list("url","http://foo/bar"))
}
}
\author{Simon Urbanek}
\keyword{interface}
Rserve/man/Rserve.eval.Rd 0000644 0001760 0000144 00000005303 14147646005 015016 0 ustar ripley users \name{Rserve.eval}
\alias{Rserve.eval}
\title{Evaluate expressions in a REPL-like fashion}
\description{
\code{Rserve.eval} evaluates a given expression in a way that is very
close to the behavior on the console Read/Evaluate/Print Loop (REPL).
Among other things this means printing the result of each expression
if visible. The function is guaranteed to not raise an error and in
case of an error it returns an object of class
\code{Rserve-eval-error} with details including the error and the
stack trace.
}
\usage{
Rserve.eval(what, where = .GlobalEnv, last.value = FALSE, exp.value = FALSE,
context = NULL)
}
%- maybe also 'usage' for other objects documented here.
\arguments{
\item{what}{expressions to evaluate}
\item{where}{environment to evaluate in}
\item{last.value}{logical, if \code{FALSE} then the result of teh
evaluation is returned, otherwise the evaluation is only performed
for its side-efects and returns \code{TRUE} instead.}
\item{exp.value}{logical, it \code{TRUE} then an error object will
include the actual expression that triggered the error, otherwise
it will only store the index of the expression in \code{what}.}
\item{context}{optional object that will be used as the context
for the duration of the evaluation.}
}
\details{
If \code{what} contains one or more expressions, they are evaluated
one by one while printing the result of each if visible. Upon error
subsequent expressions are not evaluated. If \code{what} is not an
expression then the only a single evaluation of \code{what} is
performed and the result is not printed.
The main purpose of this function is to implement console front-ends
where the front-end uses \code{parse()} + \code{Rserve.eval()} to
simulate the action of a GUI. Because the function returns in all
circumstances it allows clients to rely on a well-define messaging
behavior.
}
\value{
If the evaluation triggered an error, the result is an object of class
\code{Rserve-eval-error} with components
\item{error}{character, error message}
\item{traceback}{list of contexts in the traceback}
\item{expression}{if \code{what} contains multiple expressions then
this will be either an index to the expression that caused the error
(\code{exp.value=FALSE}) or the actual expression (otherwise).}
If the evaluation finished without an error then the result is either
\code{TRUE} if \code{last.value=FALSE} or the value of the last
expression otherwise.
}
%\references{
%}
\author{
Simon Urbanek
}
\examples{
g <- function() stop("foo")
f <- function() g()
(Rserve.eval(expression(f())))
(Rserve.eval(parse(text="1:5\n1+1")))
(Rserve.eval(quote(1+1), last.value=TRUE))
}
\keyword{manip}
Rserve/man/run.Rserve.Rd 0000644 0001760 0000144 00000002732 14147646005 014676 0 ustar ripley users \name{run.Rserve}
\alias{run.Rserve}
\title{
Start Rserve within the current R process.
}
\description{
\code{run.Rserve} makes the current R process into an Rserve
instance. Rserve takes over until it is shut down or receives a user
interrupt signal. The main difference between \code{\link{Rserve}} and
\code{run.Rserve} is that \code{Rserve} starts a new process, whereas
\code{run.Rserve} turns the current R session into Rserve. This is only
possible if there are no UI elements or other parts that could
interfere with the prepation of \code{Rserve}.
}
\usage{
run.Rserve(..., config.file = "/etc/Rserve.conf")
}
%- maybe also 'usage' for other objects documented here.
\arguments{
\item{\dots}{
all named arguments are treated as entries that would be otherwise
present in the configuration file. So argument \code{foo="bar"}
has the same meaning as \code{foo bar} in the configuration
file. The only exception is that logical values can be used instead
of \code{enable}/\code{disable}. Some settings such as \code{uid} are
not relevant and thus ignored.
}
\item{config.file}{
path of the configuration file to load in the Rserve. It will be
loaded before the above settings and is optional, i.e. if the
file is not present or readable it will be ignored.
}
}
%\details{
%}
\value{
Returns \code{TRUE} after the Rserve was shut down.
}
%\references{
%}
\author{Simon Urbanek}
\seealso{
\code{\link{Rserve}}
}
\keyword{interface}
Rserve/man/ocap.Rd 0000644 0001760 0000144 00000003026 14147646005 013544 0 ustar ripley users \name{ocap}
\title{Object Capability (OCAP) Functions}
\alias{ocap}
\alias{resolve.ocap}
\alias{Rserve.context}
\usage{
ocap(fun, name = deparse(substitute(fun)))
resolve.ocap(ocap)
Rserve.context(what)
}
\description{
The following functions are only meaningful when used by code that
is run inside Rserve in object-capability (OCAP) mode.
See \url{https://github.com/s-u/Rserve/wiki/OCAP-mode}{Rserve Wiki}
for details.
\code{ocap} registers a function as a capability and returns the
reference.
\code{resolve.ocap} takes a capability reference and returns the
function representing the capability.
\code{Rserve.context} retrieves or sets the current context for
out-of-band (OOB) messages (see also \code{\link{Rserve.eval}} for
specifying contexts during evaluation).
}
\arguments{
\item{fun}{function to register}
\item{name}{description of the function, only for informational and
logging purposes}
\item{ocap}{reference previously obtained by a call to \code{ocap}}
\item{what}{if present, sets the context to the supplied value. If
missing, the function returns the current context}
}
\value{
\code{ocap} returns the new capability reference, it will be an
object of the class \code{"OCref"}.
\code{resolve.ocap} returns the function corresponding to the
reference or \code{NULL} if the reference does not exist. It will
raise an error if \code{ocap} is not a valid \code{"OCref"} object.
\code{Rserve.context} returns the current context
}
%\examples{
%}
\author{Simon Urbanek}
\keyword{interface}
Rserve/DESCRIPTION 0000644 0001760 0000144 00000001716 14147657072 013300 0 ustar ripley users Package: Rserve
Version: 1.8-10
Title: Binary R server
Author: Simon Urbanek
Maintainer: Simon Urbanek
Depends: R (>= 1.5.0)
Suggests: RSclient
SystemRequirements: libR, GNU make
Description: Rserve acts as a socket server (TCP/IP or local sockets)
which allows binary requests to be sent to R. Every
connection has a separate workspace and working
directory. Client-side implementations are available
for popular languages such as C/C++ and Java, allowing
any application to use facilities of R without the need of
linking to R code. Rserve supports remote connection,
user authentication and file transfer. A simple R client
is included in this package as well.
License: GPL-2 | file LICENSE
URL: http://www.rforge.net/Rserve/
Biarch: true
NeedsCompilation: yes
Packaged: 2021-11-25 08:40:40 UTC; rforge
Repository: CRAN
Date/Publication: 2021-11-25 09:58:18 UTC
Rserve/configure.ac 0000644 0001760 0000144 00000020250 14147646005 014044 0 ustar ripley users # Process this file with autoconf to produce a configure script.
AC_INIT([Rserve],[1.8],[Simon.Urbanek@r-project.org])
AC_CONFIG_SRCDIR([src/Rserv.c])
AC_CONFIG_HEADERS([src/config.h])
AC_CONFIG_AUX_DIR([tools])
AC_CONFIG_MACRO_DIRS([tools/m4])
# find R home and set CC/CFLAGS
: ${R_HOME=`R RHOME`}
if test -z "${R_HOME}"; then
echo "could not determine R_HOME"
exit 1
fi
AC_ARG_WITH([server],
AS_HELP_STRING(--with-server,[compile Rserve server (default is @<:@yes@:>@). Given that this is the main functionality of Rserve, the only reason to disable the server is to configure R or C++ client separately.]),
[with_server=$withval], [with_server=yes])
AC_ARG_WITH([client],
AS_HELP_STRING(--with-client,[compile additional C/C++ Rserve client (default is @<:@no@:>@). The client can be always compiled manually regardless of this setting.]),
[with_client=$withval], [with_client=no])
AC_ARG_WITH([proxy],
AS_HELP_STRING(--with-proxy,[compile WebSockets/QAP proxy (default is @<:@yes@:>@).]),
[with_proxy=$withval], [with_proxy=yes])
AC_ARG_ENABLE([ipv6],
[AS_HELP_STRING([--enable-ipv6],[enable the use of IPv6 protocol. @<:@no@:>@])],
[want_ipv6="${enableval}"],
[want_ipv6=no])
RLD=`${R_HOME}/bin/R CMD config --ldflags 2>/dev/null`
has_R_shlib=no
if test -n "$RLD"; then
has_R_shlib=yes
fi
AC_ARG_ENABLE([threads],
[AS_HELP_STRING([--enable-threads],[enable the use of threads in code than may benefit from it.
Currently, it is only used in stdout/err forwarding, it does not
enable the threaded server.
@<:@auto@:>@])],
[want_threads="${enableval}"],
[want_threads=auto])
AC_MSG_CHECKING([whether to compile the server])
if test "${with_server}" = yes; then
AC_MSG_RESULT(yes)
if test "${has_R_shlib}" = no; then
AC_MSG_ERROR([R was configured without --enable-R-shlib or --enable-R-static-lib
*** Rserve requires R (shared or static) library. ***
*** Please install R library or compile R with either --enable-R-shlib ***
*** or --enable-R-static-lib support ***
Alternatively use --without-server if you wish to build only Rserve client.
])
fi
else
AC_MSG_RESULT(no)
fi
AC_MSG_CHECKING([whether to compile the client])
if test "${with_client}" = yes; then
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
AM_CONDITIONAL(WITH_SERVER, [test "x${with_server}" = xyes])
AM_CONDITIONAL(WITH_CLIENT, [test "x${with_client}" = xyes])
AM_CONDITIONAL(WITH_PROXY, [test "x${with_proxy}" = xyes])
CC=`${R_HOME}/bin/R CMD config CC`;
CXX=`${R_HOME}/bin/R CMD config CXX`;
R_CPPFLAGS=`${R_HOME}/bin/R CMD config CPPFLAGS`;
LDFLAGS=`${R_HOME}/bin/R CMD config LDFLAGS`;
CPPFLAGS="${CPPFLAGS} ${PKG_CPPFLAGS} ${R_CPPFLAGS}"
CFLAGS=`${R_HOME}/bin/R CMD config CFLAGS`
CXXFLAGS=`${R_HOME}/bin/R CMD config CXXFLAGS`
RINC=`${R_HOME}/bin/R CMD config --cppflags`
LIBS="${LIBS} ${PKG_LIBS}"
AC_SUBST(R_HOME)
AC_SUBST(RINC)
AC_SUBST(RLD)
AC_ARG_VAR([OPENSSL_INCLUDES],[optional path to the include directory for OpenSSL headers])
AC_ARG_VAR([PKG_CPPFLAGS],[additional pre-processor flags])
AC_ARG_VAR([PKG_LIBS],[additional linker library flags])
if test "x${OPENSSL_INCLUDES}" != x; then
CPPFLAGS="${CPPFLAGS} -I${OPENSSL_INCLUDES}"
fi
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([limits.h string.h memory.h sys/time.h unistd.h])
AC_CHECK_HEADERS([sys/stat.h sys/types.h sys/socket.h sys/un.h netinet/in.h netinet/tcp.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_BIGENDIAN(AC_DEFINE(BS_BIG_ENDIAN, 1, [Defined if the platform is big-endian]),
AC_DEFINE(BS_LITTLE_ENDIAN, 1, [Defined if the platform is little-endian]),
[
AC_MSG_RESULT(endianness unknown - will rely solely on compiler macros)
AC_MSG_CHECKING([whether compiler sets endianness macros])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#if defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN_ || defined __BIG_ENDIAN__ || defined _BIG_ENDIAN_
#define BS_OK 1
#else
cannot determine compiler's endianness
#endif
])],[AC_MSG_RESULT(yes)],[
AC_MSG_RESULT(no)
AC_MSG_ERROR([Cannot determine endianness neither from the compiler nor using a test.
Try adding -D_BIG_ENDIAN_ or -D_LITTLE_ENDIAN_ to PKG_CPPFLAGS.
])])
])
AC_CHECK_SIZEOF(size_t)
# Checks for library functions.
AC_FUNC_FORK
# NOTE: autoconf claims this must be void and thus is not needed
AC_CACHE_CHECK([return type of signal handlers],[ac_cv_type_signal],[AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([#include
#include
],
[return *(signal (0, 0)) (0) == 1;])],
[ac_cv_type_signal=int],
[ac_cv_type_signal=void])])
AC_DEFINE_UNQUOTED([RETSIGTYPE],[$ac_cv_type_signal],[Define as the return type of signal handlers
(`int' or `void').])
AC_CHECK_FUNCS([memset mkdir rmdir select socket srandomdev])
# Check whether we can use crypt (and if we do if it's in the crypt library)
AC_SEARCH_LIBS(crypt, crypt,
[AC_DEFINE(HAS_CRYPT, 1, [If defined Rserve supports unix crypt password encryption.])])
AC_CHECK_HEADERS([crypt.h])
# socket related stuff - indroduced first due to Solaris
# socklen_t - note that we don't try to find an equivalent!
# we'll use BSD-style int in case this one isn't defined.
# that should be fine for all major platforms.
AC_CHECK_TYPE(socklen_t,,
AC_DEFINE(socklen_t, int, [Define to `int' if neither nor define.]),
[
#include
#include
])
# connect may need -lsocket and/or -lnsl (e.g. on Solaris)
AC_CHECK_FUNCS(connect)
if test x"$ac_cv_func_connect" = x"no"; then
case "$LIBS" in
*-lnsl*) ;;
*) AC_CHECK_LIB(nsl_s, printf) ;;
esac
case "$LIBS" in
*-lnsl*) ;;
*) AC_CHECK_LIB(nsl, printf) ;;
esac
case "$LIBS" in
*-lsocket*) ;;
*) AC_CHECK_LIB(socket, connect) ;;
esac
case "$LIBS" in
*-linet*) ;;
*) AC_CHECK_LIB(inet, connect) ;;
esac
dnl We can't just call AC_CHECK_FUNCS(connect) here, because the value
dnl has been cached.
if test x"$ac_cv_lib_socket_connect" = x"yes" ||
test x"$ac_cv_lib_inet_connect" = x"yes"; then
# ac_cv_func_connect=yes
# don't! it would cause AC_CHECK_FUNC to succeed next time configure is run
AC_DEFINE(HAVE_CONNECT, 1, [ ])
fi
fi
# IPv6
have_ipv6=no
AC_MSG_CHECKING([whether to enable IPv6])
if test "$want_ipv6" = yes; then
AC_MSG_RESULT([yes])
AC_MSG_CHECKING([for working IPv6 sockets])
AC_LINK_IFELSE([AC_LANG_SOURCE([
#include
#include
int main(void) {
struct sockaddr_in6 sin;
int i = socket(PF_INET6, SOCK_STREAM, 0);
sin.sin6_family = AF_INET6;
sin.sin6_addr = in6addr_any;
return 0;
}
])],[AC_MSG_RESULT(yes)
have_ipv6=yes],[AC_MSG_RESULT(no)])
else
AC_MSG_RESULT([no])
fi
if test "$have_ipv6" = yes; then
AC_DEFINE(HAVE_IPV6, 1, [IPv6 support present and enabled])
fi
# on some platforms libR expects dl code in the binary
AC_CHECK_LIB(dl, dlopen)
# check RSA/crypto
AC_CHECK_HEADER([openssl/rsa.h],
[AC_SEARCH_LIBS(RSA_generate_key, [crypto ssl openssl], [AC_DEFINE(HAVE_RSA, 1, [RSA crypto support])])])
# check SSL support
AC_CHECK_HEADER([openssl/ssl.h],
[AC_SEARCH_LIBS(SSL_CTX_load_verify_locations, [ssl openssl], [AC_DEFINE(HAVE_TLS, 1, [TLS/SSL support])])])
# check threads
AC_MSG_CHECKING([whether threads are desired])
if test "$want_threads" != no; then
AC_MSG_RESULT([yes])
AX_PTHREAD([
LIBS="$PTHREAD_LIBS $LIBS"
## we don't want to mess with CFLAGS so we (ab)use CPPFLAGS
CPPFLAGS="$CPPFLAGS $PTHREAD_CFLAGS"
## and we ignore PTHREAD_CC since we have to use R's settings
with_threads=yes
AC_MSG_CHECKING([for working threads support])
AC_MSG_RESULT([yes])
], [
AC_MSG_CHECKING([for working threads support])
AC_MSG_RESULT([no])
if test "$want_threads" = yes; then
AC_MSG_ERROR([Threads were requested, but no working threads support was found])
fi
with_threads=no
])
else
AC_MSG_RESULT([no])
with_threads=no
fi
AC_SUBST(PTHREAD_CFLAGS)
if test x"$with_threads" = xyes; then
AC_DEFINE(WITH_THREADS, 1, [set if threads can be used])
fi
AC_CONFIG_FILES([src/Makevars])
AC_CONFIG_FILES([src/client/cxx/Makefile])
AC_OUTPUT
Rserve/src/ 0000755 0001760 0000144 00000000000 14147646005 012346 5 ustar ripley users Rserve/src/tls.h 0000644 0001760 0000144 00000001316 14147646005 013322 0 ustar ripley users #ifndef TLS_H__
#define TLS_H__
#include "RSserver.h"
typedef struct tls tls_t;
/* for set_tls_verify() */
#define TLS_NONE 0 /* default */
#define TLS_REQUIRE 1
/* in case shared tls is not set, it will be set to new_tls
(which can be NULL) */
tls_t *shared_tls(tls_t *new_tls);
tls_t *new_tls();
int set_tls_pk(tls_t *tls, const char *fn);
int set_tls_cert(tls_t *tls, const char *fn);
int set_tls_ca(tls_t *tls, const char *fn_ca, const char *path_ca);
int set_tls_verify(tls_t *tls, int verify);
void free_tls(tls_t *tls);
int add_tls(args_t *c, tls_t *tls, int server);
void copy_tls(args_t *src, args_t *dst);
void close_tls(args_t *c);
int verify_peer_tls(args_t *c, char *cn, int len);
#endif
Rserve/src/install.libs.R 0000644 0001760 0000144 00000001465 14147646005 015075 0 ustar ripley users libarch <- if (nzchar(R_ARCH)) paste("libs", R_ARCH, sep='') else "libs"
dest <- file.path(R_PACKAGE_DIR, libarch)
## the last two on unix are for compatibility only
files <- if (WINDOWS) c("Rserve.exe", "Rserve_d.exe", "forward.exe") else c("Rserve","Rserve.dbg","forward")
files <- c(files, paste("Rserve",SHLIB_EXT,sep=''))
## all files are optional in case the package is built without the server
files <- files[file.exists(files)]
if (length(files)) {
dir.create(dest, recursive = TRUE, showWarnings = FALSE)
file.copy(files, dest, overwrite = TRUE)
if (length(grep("^darwin", R.version$os))) {
message('generating debug symbols (dSYM)')
dylib <- Sys.glob(paste(dest, "/*", SHLIB_EXT, sep=''))
if (length(dylib)) for (file in dylib) try(system(paste("dsymutil ", file, sep='')), silent=TRUE)
}
}
Rserve/src/websockets.h 0000644 0001760 0000144 00000002103 14147646005 014664 0 ustar ripley users #ifndef WEBSOCKETS_H__
#define WEBSOCKETS_H__
#include "RSserver.h"
#define WS_PROT_QAP 0x01
#define WS_PROT_TEXT 0x02
/* NOTE: this is not the same as SRV_TLS! It is annoying, but WS needs to
chain TLS futher down, if SRC_TLS is set then QAP will be tunneled
through TLS but we need to wrap WS around it first */
#define WS_TLS 0x08
/* WARNING: HTTP uses 0x10 and 0x20 */
#define WS_PROT_ALL (WS_PROT_QAP | WS_PROT_TEXT)
server_t *create_WS_server(int port, int protocols);
/* upgrade HTTP connection to WS - assumes that the HTTP server has parsed the request already
only WS 13+ handshake is supported by this function */
void WS13_upgrade(args_t *arg, const char *key, const char *protocol, const char *version);
/* flags used in args_t.flags */
#define F_INFRAME 0x010
#define F_MASK 0x020
#define F_IN_BIN 0x040
#define F_OUT_BIN 0x080
#define SET_F_FT(X, FT) X = (((X) & 0xfff) | (((FT) & 15) << 12))
#define GET_F_FT(X) (((X) >> 12) & 15)
#define GET_MASK_ID(X) ((X) & 3)
#define SET_F_MASK(X, M) X = (((X) & 0xfffc) | F_MASK | ((M) & 3))
#endif
Rserve/src/RSserver.h 0000644 0001760 0000144 00000005541 14147646005 014277 0 ustar ripley users #ifndef RS_SERVER_H__
#define RS_SERVER_H__
#include "Rsrv.h"
/* this is a voluntary standart flag to request TLS support */
#define SRV_TLS 0x0800
/* these flags are global and respected by the default socket server */
#define SRV_IPV6 0x1000 /* use IPv6 */
#define SRV_LOCAL 0x4000 /* bind to local loopback interface only */
#define SRV_KEEPALIVE 0x8000 /* enable keep-alive - note that this is really
a client option sice inheritance is not
guaranteed */
typedef struct args args_t;
typedef void (*work_fn_t)(void *par);
typedef int (*send_fn_t)(args_t *arg, int rsp, rlen_t len, const void *buf);
typedef int (*buf_fn_t) (args_t *arg, void *buf, rlen_t len);
typedef int (*cbuf_fn_t) (args_t *arg, const void *buf, rlen_t len);
typedef int (*fork_fn_t) (args_t *arg);
/* definition of a server */
typedef struct server {
int ss; /* server socket */
int unix_socket; /* 0 = TCP/IP, 1 = unix socket */
int flags; /* optional server-specific flags */
work_fn_t connected; /* function called for each new connection */
work_fn_t fin; /* optional finalization function */
send_fn_t send_resp; /* send response */
cbuf_fn_t send; /* direct send */
buf_fn_t recv; /* direct receive */
fork_fn_t fork; /* fork */
struct server *parent;/* parent server - used only by multi-layer servers */
} server_t;
/* this flag can be passed to create_server for an IP socket to modify the behavior */
#define LSM_IP_LOCAL 1 /* bind to loopback address only */
#define LSM_IPV6 2 /* use IPv6 (if available) */
server_t *create_server(int port, const char *localSocketName, int localSocketMode, int flags);
void accepted_server(server_t *srv, int cs); /* performs additional tasks on client socket (eg SO_KEEPALIVE) */
int add_server(server_t *srv);
int rm_server(server_t *srv);
/* server stacks */
typedef struct server_stack server_stack_t;
server_stack_t* create_server_stack();
void push_server(server_stack_t *s, server_t *srv);
int server_stack_size(server_stack_t *s);
void release_server_stack(server_stack_t *s);
/* some generic implementations */
void server_fin(void *x);
int server_recv(args_t *arg, void *buf, rlen_t len);
int server_send(args_t *arg, const void *buf, rlen_t len);
void stop_server_loop();
void serverLoop();
/* helper function that prepares the process just like Rserve
internal impleemntation - forking when desired, establishing
pipes, setting see, uid/gid, cwd etc.
returns 0 for the child */
int Rserve_prepare_child(args_t *arg);
/* this one is called by the former to close all server sockets in the child */
void close_all_srv_sockets();
#endif
/*--- The following makes the indenting behavior of emacs compatible
with Xcode's 4/4 setting ---*/
/* Local Variables: */
/* indent-tabs-mode: t */
/* tab-width: 4 */
/* c-basic-offset: 4 */
/* End: */
Rserve/src/base64.c 0000644 0001760 0000144 00000003240 14147646005 013575 0 ustar ripley users void base64encode(const unsigned char *src, int len, char *dst);
int base64decode(const char *src, void *dst, int max_len);
static const char *b64tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/* dst must be at least (len + 2) / 3 * 4 + 1 bytes long and will be NUL terminated when done */
void base64encode(const unsigned char *src, int len, char *dst) {
while (len > 0) {
*(dst++) = b64tab[src[0] >> 2];
*(dst++) = b64tab[((src[0] & 0x03) << 4) | ((src[1] & 0xf0) >> 4)];
*(dst++) = (len > 1) ? b64tab[((src[1] & 0x0f) << 2) | ((src[2] & 0xc0) >> 6)] : '=';
*(dst++) = (len > 2) ? b64tab[src[2] & 0x3f] : '=';
src += 3;
len -= 3;
}
*dst = 0;
}
static unsigned int val(const char **src) {
while (1) {
char c = **src;
if (c) src[0]++; else return 0x10000;
if (c >= 'A' && c <= 'Z') return c - 'A';
if (c >= 'a' && c <= 'z') return c - 'a' + 26;
if (c >= '0' && c <= '9') return c - '0' + 52;
if (c == '+') return 62;
if (c == '/') return 63;
if (c == '=')
return 0x10000;
/* we loop as to skip any blanks, newlines etc. */
}
}
/* returns the decoded length or -1 if max_len was not enough */
int base64decode(const char *src, void *dst, int max_len) {
unsigned char *t = (unsigned char*) dst, *end = t + max_len;
while (*src && t < end) {
unsigned int v = val(&src);
if (v > 64) break;
*t = v << 2;
v = val(&src);
*t |= v >> 4;
if (v < 64) {
if (++t == end) return -1;
*t = v << 4;
v = val(&src);
*t |= v >> 2;
if (v < 64) {
if (++t == end) return -1;
*t = v << 6;
v = val(&src);
*t |= v & 0x3f;
if (v < 64) t++;
}
}
}
return (int) (t - (unsigned char*) dst);
}
Rserve/src/md5.c 0000644 0001760 0000144 00000021101 14147646005 013172 0 ustar ripley users /*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/
/* Brutally hacked by John Walker back from ANSI C to K&R (no
prototypes) to maintain the tradition that Netfone will compile
with Sun's original "cc".
Modified to work better with autoconf and added md5hash
convenience function (Simon Urbanek, 2005/09/30)
$Id$
*/
#ifndef NO_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_MEMORY_H
#include /* for memcpy() */
#else
#include
#endif
#include "md5.h"
#ifdef SWAPEND
#define HIGHFIRST
#endif
#ifndef HIGHFIRST
#define byteReverse(buf, len) /* Nothing */
#else
/*
* Note: this code is harmless on little-endian machines.
*/
void byteReverse(buf, longs)
unsigned char *buf; unsigned longs;
{
uint32 t;
do {
t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
((unsigned) buf[1] << 8 | buf[0]);
*(uint32 *) buf = t;
buf += 4;
} while (--longs);
}
#endif
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void MD5Init(ctx)
struct MD5Context *ctx;
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void MD5Update(ctx, buf, len)
struct MD5Context *ctx; const unsigned char *buf; unsigned len;
{
uint32 t;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t) {
unsigned char *p = (unsigned char *) ctx->in + t;
t = 64 - t;
if (len < t) {
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *) ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *) ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void MD5Final(digest, ctx)
unsigned char digest[16]; struct MD5Context *ctx;
{
unsigned count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *) ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
byteReverse(ctx->in, 14);
/* Append length in bits and transform */
((uint32 *) ctx->in)[14] = ctx->bits[0];
((uint32 *) ctx->in)[15] = ctx->bits[1];
MD5Transform(ctx->buf, (uint32 *) ctx->in);
byteReverse((unsigned char *) ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<>(32-s), w += x )
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
void MD5Transform(buf, in)
uint32 buf[4]; uint32 in[16];
{
register uint32 a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
static unsigned char m5hash[16];
/* the hash must hold 16 bytes */
unsigned char *md5hash(const void *buf, int len, unsigned char hash[16]) {
struct MD5Context ctx;
if (!hash) hash=m5hash;
MD5Init(&ctx);
MD5Update(&ctx, buf, len);
MD5Final(hash, &ctx);
return hash;
}
Rserve/src/sha1.h 0000644 0001760 0000144 00000000154 14147646005 013353 0 ustar ripley users #ifndef SHA1_H__
#define SHA1_H__
void sha1hash(const char *buf, int len, unsigned char hash[20]);
#endif
Rserve/src/Rsrv.h 0000644 0001760 0000144 00000046250 14147646005 013462 0 ustar ripley users /*
* Rsrv.h : constants and macros for Rserve client/server architecture
* Copyright (C) 2002-21 Simon Urbanek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 of the License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Note: This header file is licensed under LGPL to allow other
* programs to use it under LGPL. Rserve itself is licensed under GPL.
*
* $Id$
*/
/* external defines:
MAIN - should be defined in just one file that will contain the fn definitions and variables
*/
#ifndef __RSRV_H__
#define __RSRV_H__
#ifndef NO_CONFIG_H
#include "config.h"
#endif
#define RSRV_VER 0x01080a /* Rserve v1.8-10 */
#define default_Rsrv_port 6311
/* Rserve communication is done over any reliable connection-oriented
protocol (usually TCP/IP or local sockets). After the connection is
established, the server sends 32 bytes of ID-string defining the
capabilities of the server. Each attribute of the ID-string is 4 bytes
long and is meant to be user-readable (i.e. don't use special characters),
and it's a good idea to make "\r\n\r\n" the last attribute
the ID string must be of the form:
[0] "Rsrv" - R-server ID signature
[4] "0100" - version of the R server
[8] "QAP1" - protocol used for communication (here Quad Attributes Packets v1)
[12] any additional attributes follow. \r\n and '-' are ignored.
optional attributes
(in any order; it is legitimate to put dummy attributes, like "----" or
" " between attributes):
"R151" - version of R (here 1.5.1)
"ARpt" - authorization required (here "pt"=plain text, "uc"=unix crypt,
"m5"=MD5)
connection will be closed if the first packet is not CMD_login.
if more AR.. methods are specified, then client is free to
use the one he supports (usually the most secure)
"K***" - key if encoded authentification is challenged (*** is the key)
for unix crypt the first two letters of the key are the salt
required by the server */
/* QAP1 transport protocol header structure
all int and double entries throughout the transfer are in
Intel-endianess format: int=0x12345678 -> char[4]=(0x78,0x56,x34,0x12)
functions/macros for converting from native to protocol format
are available below
Please note also that all values muse be quad-aligned, i.e. the length
must be divisible by 4. This is automatically assured for int/double etc.,
but care must be taken when using strings and byte streams.
*/
struct phdr { /* always 16 bytes */
int cmd; /* command */
int len; /* length of the packet minus header (ergo -16) */
int msg_id; /* message id (since 1.8) [WAS:data offset behind header (ergo usually 0)] */
int res; /* high 32-bit of the packet length (since 0103
and supported on 64-bit platforms only)
aka "lenhi", but the name was not changed to
maintain compatibility */
};
/* each entry in the data section (aka parameter list) is preceded by 4 bytes:
1 byte : parameter type
3 bytes: length
parameter list may be terminated by 0/0/0/0 but doesn't have to since "len"
field specifies the packet length sufficiently (hint: best method for parsing is
to allocate len+4 bytes, set the last 4 bytes to 0 and trverse list of parameters
until (int)0 occurs
since 0102:
if the 7-th bit (0x40) in parameter type is set then the length is encoded
in 7 bytes enlarging the header by 4 bytes.
*/
/* macros for handling the first int - split/combine (24-bit version only!) */
#define PAR_TYPE(X) ((X) & 255)
#define PAR_LEN(X) (((unsigned int)(X)) >> 8)
#define PAR_LENGTH PAR_LEN
#define SET_PAR(TY,LEN) ((((unsigned int) (LEN) & 0xffffff) << 8) | ((TY) & 255))
#define CMD_STAT(X) (((X) >> 24)&127) /* returns the stat code of the response */
#define SET_STAT(X,s) ((X) | (((s) & 127) << 24)) /* sets the stat code */
#define CMD_RESP 0x10000 /* all responses have this flag set */
#define RESP_OK (CMD_RESP|0x0001) /* command succeeded; returned parameters depend
on the command issued */
#define RESP_ERR (CMD_RESP|0x0002) /* command failed, check stats code
attached string may describe the error */
#define CMD_OOB 0x20000 /* out-of-band data - i.e. unsolicited messages */
#define OOB_SEND (CMD_OOB | 0x1000) /* OOB send - unsolicited SEXP sent from the R instance to the client. 12 LSB are reserved for application-specific code */
#define OOB_MSG (CMD_OOB | 0x2000) /* OOB message - unsolicited message sent from the R instance to the client requiring a response. 12 LSB are reserved for application-specific code */
#define IS_OOB_SEND(X) (((X) & 0x0ffff000) == OOB_SEND)
#define IS_OOB_MSG(X) (((X) & 0x0ffff000) == OOB_MSG)
#define OOB_USR_CODE(X) ((X) & 0xfff)
/* flag for create_server: Use QAP object-cap mode */
#define SRV_QAP_OC 0x40
/* mask of all flags that are relevant to QAP (so they can be passed through) */
#define SRV_QAP_FLAGS (SRV_QAP_OC)
/* stat codes; 0-0x3f are reserved for program specific codes - e.g. for R
connection they correspond to the stat of Parse command.
the following codes are returned by the Rserv itself
codes <0 denote Rerror as provided by R_tryEval
*/
#define ERR_auth_failed 0x41 /* auth.failed or auth.requested but no
login came. in case of authentification
failure due to name/pwd mismatch,
server may send CMD_accessDenied instead
*/
#define ERR_conn_broken 0x42 /* connection closed or broken packet killed it */
#define ERR_inv_cmd 0x43 /* unsupported/invalid command */
#define ERR_inv_par 0x44 /* some parameters are invalid */
#define ERR_Rerror 0x45 /* R-error occured, usually followed by
connection shutdown */
#define ERR_IOerror 0x46 /* I/O error */
#define ERR_notOpen 0x47 /* attempt to perform fileRead/Write
on closed file */
#define ERR_accessDenied 0x48 /* this answer is also valid on
CMD_login; otherwise it's sent
if the server deosn;t allow the user
to issue the specified command.
(e.g. some server admins may block
file I/O operations for some users) */
#define ERR_unsupportedCmd 0x49 /* unsupported command */
#define ERR_unknownCmd 0x4a /* unknown command - the difference
between unsupported and unknown is that
unsupported commands are known to the
server but for some reasons (e.g.
platform dependent) it's not supported.
unknown commands are simply not recognized
by the server at all. */
/* The following ERR_.. exist since 1.23/0.1-6 */
#define ERR_data_overflow 0x4b /* incoming packet is too big.
currently there is a limit as of the
size of an incoming packet. */
#define ERR_object_too_big 0x4c /* the requested object is too big
to be transported in that way.
If received after CMD_eval then
the evaluation itself was successful.
optional parameter is the size of the object
*/
/* since 1.29/0.1-9 */
#define ERR_out_of_mem 0x4d /* out of memory. the connection is usually
closed after this error was sent */
/* since 0.6-0 */
#define ERR_ctrl_closed 0x4e /* control pipe to the master process is closed or broken */
/* since 0.4-0 */
#define ERR_session_busy 0x50 /* session is still busy */
#define ERR_detach_failed 0x51 /* unable to detach seesion (cannot determine
peer IP or problems creating a listening
socket for resume) */
/* since 1.7 */
#define ERR_disabled 0x61 /* feature is disabled */
#define ERR_unavailable 0x62 /* feature is not present in this build */
#define ERR_cryptError 0x63 /* crypto-system error */
#define ERR_securityClose 0x64 /* server-initiated close due to security
violation (too many attempts, excessive
timeout etc.) */
/* availiable commands */
#define CMD_login 0x001 /* "name\npwd" : - */
#define CMD_voidEval 0x002 /* string : - */
#define CMD_eval 0x003 /* string | encoded SEXP : encoded SEXP */
#define CMD_shutdown 0x004 /* [admin-pwd] : - */
/* security/encryption - all since 1.7-0 */
#define CMD_switch 0x005 /* string (protocol) : - */
#define CMD_keyReq 0x006 /* string (request) : bytestream (key) */
#define CMD_secLogin 0x007 /* bytestream (encrypted auth) : - */
#define CMD_OCcall 0x00f /* SEXP : SEXP -- it is the only command
supported in object-capability mode
and it requires that the SEXP is a
language construct with OC reference
in the first position */
#define CMD_OCinit 0x434f7352 /* SEXP -- 'RsOC' - command sent from
the server in OC mode with the packet
of initial capabilities. */
/* file I/O routines. server may answe */
#define CMD_openFile 0x010 /* fn : - */
#define CMD_createFile 0x011 /* fn : - */
#define CMD_closeFile 0x012 /* - : - */
#define CMD_readFile 0x013 /* [int size] : data... ; if size not present,
server is free to choose any value - usually
it uses the size of its static buffer */
#define CMD_writeFile 0x014 /* data : - */
#define CMD_removeFile 0x015 /* fn : - */
/* object manipulation */
#define CMD_setSEXP 0x020 /* string(name), REXP : - */
#define CMD_assignSEXP 0x021 /* string(name), REXP : - ; same as setSEXP
except that the name is parsed */
/* session management (since 0.4-0) */
#define CMD_detachSession 0x030 /* : session key */
#define CMD_detachedVoidEval 0x031 /* string : session key; doesn't */
#define CMD_attachSession 0x032 /* session key : - */
/* control commands (since 0.6-0) - passed on to the master process */
/* Note: currently all control commands are asychronous, i.e. RESP_OK
indicates that the command was enqueued in the master pipe, but there
is no guarantee that it will be processed. Moreover non-forked
connections (e.g. the default debug setup) don't process any
control commands until the current client connection is closed so
the connection issuing the control command will never see its
result.
*/
#define CMD_ctrl 0x40 /* -- not a command - just a constant -- */
#define CMD_ctrlEval 0x42 /* string : - */
#define CMD_ctrlSource 0x45 /* string : - */
#define CMD_ctrlShutdown 0x44 /* - : - */
/* 'internal' commands (since 0.1-9) */
#define CMD_setBufferSize 0x081 /* [int sendBufSize]
this commad allow clients to request
bigger buffer sizes if large data is to be
transported from Rserve to the client.
(incoming buffer is resized automatically)
*/
#define CMD_setEncoding 0x082 /* string (one of "native","latin1","utf8") : -; since 0.5-3 */
/* special commands - the payload of packages with this mask does not contain defined parameters */
#define CMD_SPECIAL_MASK 0xf0
#define CMD_serEval 0xf5 /* serialized eval - the packets are raw serialized data without data header */
#define CMD_serAssign 0xf6 /* serialized assign - serialized list with [[1]]=name, [[2]]=value */
#define CMD_serEEval 0xf7 /* serialized expression eval - like serEval with one additional evaluation round */
/* data types for the transport protocol (QAP1)
do NOT confuse with XT_.. values. */
#define DT_INT 1 /* int */
#define DT_CHAR 2 /* char */
#define DT_DOUBLE 3 /* double */
#define DT_STRING 4 /* 0 terminted string */
#define DT_BYTESTREAM 5 /* stream of bytes (unlike DT_STRING may contain 0) */
#define DT_SEXP 10 /* encoded SEXP */
#define DT_ARRAY 11 /* array of objects (i.e. first 4 bytes specify how many
subsequent objects are part of the array; 0 is legitimate) */
#define DT_CUSTOM 32 /* custom types not defined in the protocol but used
by applications */
#define DT_LARGE 64 /* new in 0102: if this flag is set then the length of the object
is coded as 56-bit integer enlarging the header by 4 bytes */
/* XpressionTypes
REXP - R expressions are packed in the same way as command parameters
transport format of the encoded Xpressions:
[0] int type/len (1 byte type, 3 bytes len - same as SET_PAR)
[4] REXP attr (if bit 8 in type is set)
[4/8] data .. */
#define XT_NULL 0 /* P data: [0] */
#define XT_INT 1 /* - data: [4]int */
#define XT_DOUBLE 2 /* - data: [8]double */
#define XT_STR 3 /* P data: [n]char null-term. strg. */
#define XT_LANG 4 /* - data: same as XT_LIST */
#define XT_SYM 5 /* - data: [n]char symbol name */
#define XT_BOOL 6 /* - data: [1]byte boolean
(1=TRUE, 0=FALSE, 2=NA) */
#define XT_S4 7 /* P data: [0] */
#define XT_VECTOR 16 /* P data: [?]REXP,REXP,.. */
#define XT_LIST 17 /* - X head, X vals, X tag (since 0.1-5) */
#define XT_CLOS 18 /* P X formals, X body (closure; since 0.1-5) */
#define XT_SYMNAME 19 /* s same as XT_STR (since 0.5) */
#define XT_LIST_NOTAG 20 /* s same as XT_VECTOR (since 0.5) */
#define XT_LIST_TAG 21 /* P X tag, X val, Y tag, Y val, ... (since 0.5) */
#define XT_LANG_NOTAG 22 /* s same as XT_LIST_NOTAG (since 0.5) */
#define XT_LANG_TAG 23 /* s same as XT_LIST_TAG (since 0.5) */
#define XT_VECTOR_EXP 26 /* s same as XT_VECTOR (since 0.5) */
#define XT_VECTOR_STR 27 /* - same as XT_VECTOR (since 0.5 but unused, use XT_ARRAY_STR instead) */
#define XT_ARRAY_INT 32 /* P data: [n*4]int,int,.. */
#define XT_ARRAY_DOUBLE 33 /* P data: [n*8]double,double,.. */
#define XT_ARRAY_STR 34 /* P data: string,string,.. (string=byte,byte,...,0) padded with '\01' */
#define XT_ARRAY_BOOL_UA 35 /* - data: [n]byte,byte,.. (unaligned! NOT supported anymore) */
#define XT_ARRAY_BOOL 36 /* P data: int(n),byte,byte,... */
#define XT_RAW 37 /* P data: int(n),byte,byte,... */
#define XT_ARRAY_CPLX 38 /* P data: [n*16]double,double,... (Re,Im,Re,Im,...) */
#define XT_UNKNOWN 48 /* P data: [4]int - SEXP type (as from TYPEOF(x)) */
/* |
+--- interesting flags for client implementations:
P = primary type
s = secondary type - its decoding is identical to
a primary type and thus the client doesn't need to
decode it separately.
- = deprecated/removed. if a client doesn't need to
support old Rserve versions, those can be safely
skipped.
Total primary: 4 trivial types (NULL, STR, S4, UNKNOWN) + 6 array types + 3 recursive types
*/
#define XT_LARGE 64 /* new in 0102: if this flag is set then the length of the object
is coded as 56-bit integer enlarging the header by 4 bytes */
#define XT_HAS_ATTR 128 /* flag; if set, the following REXP is the
attribute */
/* the use of attributes and vectors results in recursive storage of REXPs */
#define BOOL_TRUE 1
#define BOOL_FALSE 0
#define BOOL_NA 2
#define GET_XT(X) ((X)&63)
#define GET_DT(X) ((X)&63)
#define HAS_ATTR(X) (((X)&XT_HAS_ATTR)>0)
#define IS_LARGE(X) (((X)&XT_LARGE)>0)
#if defined sun && ! defined ALIGN_DOUBLES
#define ALIGN_DOUBLES
#endif
#ifndef SIZEOF_SIZE_T
#include /* defines SIZEOF_SIZE_T in case we missed it */
#endif
/* long vectors - we don't want to mandate Rinternals.h here
so we use the minimal definition */
#if ( SIZEOF_SIZE_T > 4 )
#include /* for ptrdiff_t, which is required by C99 */
typedef ptrdiff_t rlen_t;
/* this is used for alignment/masking */
#define rlen_max ((rlen_t) 0x7fffffffffffffff)
#else /* old legacy definition using unsigned long */
/* this is the type used to calculate pointer distances */
/* note: we may want to use size_t or something more compatible */
typedef unsigned long rlen_t;
#ifdef ULONG_MAX
#define rlen_max ULONG_MAX
#else
#ifdef __LP64__
#define rlen_max 0xffffffffffffffffL
#else
#define rlen_max 0xffffffffL
#endif /* __LP64__ */
#endif /* ULONG_MAX */
#endif /* long vector fallback */
/* functions/macros to convert native endianess of int/double for transport
currently ony PPC style and Intel style are supported */
/* Since 0.4-5 we no longer use configure-time endianness tests to allow cross-compilation.
Either BS_xx_ENDIAN constant is defined by configure and thus should be relied upon only if
the compiler contants don't work */
#if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN_
#define SWAPEND 1
#elif defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN_ || defined BS_LITTLE_ENDIAN
/* #undef SWAPEND */
#elif defined BS_BIG_ENDIAN
#define SWAPEND 1
#elif __ia64__ || __i386__ || __x86_64__ /* take a guess based on the architecture (Intel-like) */
#define __LITTLE_ENDIAN__ 1
#elif __ppc__ || __ppc64__ /* any ppc */
#define __BIG_ENDIAN__ 1
#define SWAPEND 1
#elif ! defined Win32 /* Windows is little-endian is most cases, anywhere else we're stuck */
#error "Cannot determine endianness. Make sure config.h is included or __{BIG|LITTLE}_ENDIAN__ is defined ."
#endif
/* FIXME: all the mess below needs more efficient implementation - the current one is so messy to work around alignment problems on some platforms like Sun and HP 9000 */
#ifdef SWAPEND /* swap endianness - for PPC and co. */
#ifdef MAIN
unsigned int itop(unsigned int i) { char b[4]; b[0]=((char*)&i)[3]; b[3]=((char*)&i)[0]; b[1]=((char*)&i)[2]; b[2]=((char*)&i)[1]; return *((unsigned int*)b); }
double dtop(double i) { char b[8]; b[0]=((char*)&i)[7]; b[1]=((char*)&i)[6]; b[2]=((char*)&i)[5]; b[3]=((char*)&i)[4]; b[7]=((char*)&i)[0]; b[6]=((char*)&i)[1]; b[5]=((char*)&i)[2]; b[4]=((char*)&i)[3]; return *((double*)b); }
void fixdcpy(void *t,void *s) { int i=0; while (i<8) { ((char*)t)[7-i]=((char*)s)[i]; i++; } }
#else
extern unsigned int itop(unsigned int i);
extern double dtop(double i);
extern void fixdcpy(void *t,void *s);
#endif
#define ptoi(X) itop(X) /* itop*itop=id */
#define ptod(X) dtop(X)
#else
#define itop(X) (X)
#define ptoi(X) (X)
#define dtop(X) (X)
#define ptod(X) (X)
#define fixdcpy(T,S) ((double*)(T))[0]=((double*)(S))[0];
#define NATIVE_COPY 1
#endif
#ifndef HAVE_CONFIG_H
/* this tiny function can be used to make sure that the endianess
is correct (it is not included if the package was configured with
autoconf since then it should be fine anyway) */
#ifdef MAIN
int isByteSexOk() {
int i;
i=itop(0x12345678);
return (*((char*)&i)==0x78);
}
#else
extern int isByteSexOk();
#endif
#else
#define isByteSexOk 1
#endif
/* STANDALONE_RSERVE takes precedence over RSERVE_PKG */
#if defined STANDALONE_RSERVE && defined RSERVE_PKG
#undef RSERVE_PKG
#endif
#endif
/*--- The following makes the indenting behavior of emacs compatible
with Xcode's 4/4 setting ---*/
/* Local Variables: */
/* indent-tabs-mode: t */
/* tab-width: 4 */
/* c-basic-offset: 4 */
/* End: */
Rserve/src/tls.c 0000644 0001760 0000144 00000007106 14147646005 013320 0 ustar ripley users #ifndef NO_CONFIG_H
#include "config.h"
#endif
#include "tls.h"
#ifdef HAVE_TLS
#include
#ifdef RSERV_DEBUG
#include
#endif
struct tls {
SSL_CTX *ctx;
const SSL_METHOD *method;
};
static int first_tls = 1;
static tls_t *tls;
tls_t *shared_tls(tls_t *new_tls) {
if (!tls)
tls = new_tls;
return tls;
}
tls_t *new_tls() {
tls_t *t = (tls_t*) calloc(1, sizeof(tls_t));
if (first_tls) {
SSL_library_init();
#ifdef RSERV_DEBUG
SSL_load_error_strings();
#endif
first_tls = 0;
tls = t;
}
t->method = SSLv23_server_method();
t->ctx = SSL_CTX_new(t->method);
return t;
}
int set_tls_pk(tls_t *tls, const char *fn) {
return SSL_CTX_use_PrivateKey_file(tls->ctx, fn, SSL_FILETYPE_PEM);
}
int set_tls_cert(tls_t *tls, const char *fn) {
return SSL_CTX_use_certificate_file(tls->ctx, fn, SSL_FILETYPE_PEM);
}
int set_tls_ca(tls_t *tls, const char *fn_ca, const char *path_ca) {
return SSL_CTX_load_verify_locations(tls->ctx, fn_ca, path_ca);
}
int set_tls_verify(tls_t *tls, int verify) {
SSL_CTX_set_verify(tls->ctx, verify ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, 0);
return 1;
}
struct args {
server_t *srv; /* server that instantiated this connection */
int s;
int ss;
int msg_id;
SSL *ssl;
void *res2;
};
static int tls_recv(args_t *c, void *buf, rlen_t len) {
return SSL_read(c->ssl, buf, len);
}
static int tls_send(args_t *c, const void *buf, rlen_t len) {
return SSL_write(c->ssl, buf, len);
}
int add_tls(args_t *c, tls_t *tls, int server) {
c->ssl = SSL_new(tls->ctx);
c->srv->send = tls_send;
c->srv->recv = tls_recv;
SSL_set_fd(c->ssl, c->s);
if (server)
return SSL_accept(c->ssl);
else
return SSL_connect(c->ssl);
}
void copy_tls(args_t *src, args_t *dst) {
dst->ssl = src->ssl;
dst->s = src->s;
dst->srv->send = src->srv->send;
dst->srv->recv = src->srv->recv;
}
void close_tls(args_t *c) {
if (c->ssl) {
SSL_shutdown(c->ssl);
SSL_free(c->ssl);
c->ssl = 0;
}
}
void free_tls(tls_t *tls) {
}
/* if cn is present, len > 0 and there is a cert then the common name
is copied to cn and terminated. It may be truncated if len is too short.
Return values:
0 = present but verification failed
1 = present and verification successful
-1 = absent */
int verify_peer_tls(args_t *c, char *cn, int len) {
X509 *peer;
if ((peer = SSL_get_peer_certificate(c->ssl))) {
if (cn && len > 0) {
X509_NAME *sn = X509_get_subject_name(peer);
X509_NAME_get_text_by_NID(sn, NID_commonName, cn, len);
fprintf(stderr, "INFO: peer cert common name: \"%s\"\n", cn);
}
X509_free(peer);
if (SSL_get_verify_result(c->ssl) == X509_V_OK) {
fprintf(stderr, "INFO: peer cert present and OK\n");
return 1;
} else {
fprintf(stderr, "INFO: peer cert present, but verification FAILED\n");
return 0;
}
}
fprintf(stderr, "INFO: peer nas NO cert\n");
return -1;
}
#else /* no SSL/TLS support, ignore everything, fail on everything */
tls_t *shared_tls(tls_t *new_tls) { return 0; }
tls_t *new_tls() { return 0; }
int set_tls_pk(tls_t *tls, const char *fn) { return -1; }
int set_tls_cert(tls_t *tls, const char *fn) { return -1; }
int set_tls_ca(tls_t *tls, const char *fn_ca, const char *path_ca) { return -1; }
int set_tls_verify(tls_t *tls, int verify) { return -1; }
void free_tls(tls_t *tls) { }
int add_tls(args_t *c, tls_t *tls, int server) { return -1; }
void copy_tls(args_t *src, args_t *dst) { }
void close_tls(args_t *c) { }
int verify_peer_tls(args_t *c, char *cn, int len) { return -1; }
#endif
Rserve/src/ulog.c 0000644 0001760 0000144 00000012447 14147646005 013470 0 ustar ripley users /* UDP logger
(C)Copyright 2002-2013 Simon Urbanek
This logger can be used either via simple
ulog(...)
call in the printf format, or the message can be constructed
incerementally via
ulog_begin()
ulog_add(...); [ulog_add(...); ...]
ulog_end()
calls. ulog_end() commences the transfer.
Internal state, sockets etc. may be cached after the first use.
*/
#define DEFAULT_ULOG_PORT 514
#ifndef NO_CONFIG_H
#include "config.h"
#endif
#include "ulog.h"
/* FIXME: now that we support UDP/TCP we could make this work on Windows ... */
#ifndef WIN32
#include
#include
#include
#include
#include
#include
#include
#include
#if HAVE_SYS_TIME_H
# include
#endif
#include
#include
#include
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#endif
static int ulog_sock = -1;
static char *ulog_path;
static int ulog_dcol, ulog_port = 0;
static char hn[512];
static char buf[4096];
static char ts[64];
static unsigned int buf_pos;
#ifdef ULOG_MICROTIME
static double time0, timeN;
#endif
static char *app_name = "unknown";
static char *sstrdup(const char *s, const char *dflt) {
char *c;
if (!s) return 0;
c = strdup(s);
return (char*) (c ? c : dflt);
}
void ulog_set_app_name(const char *name) {
app_name = sstrdup(name, "out-of-memory");
}
void ulog_set_path(const char *path) {
ulog_path = sstrdup(path, 0);
}
int ulog_enabled() {
return (ulog_path) ? 1 : 0;
}
void ulog_begin() {
if (!ulog_path) return;
if (ulog_sock == -1) { /* first-time user */
int u_family = AF_LOCAL;
int u_sock = SOCK_DGRAM;
gethostname(hn, sizeof(hn));
if (!strncmp(ulog_path, "udp://", 6) || !strncmp(ulog_path, "tcp://", 6)) {
const char *c;
u_family = AF_INET;
if (ulog_path[0] == 't') u_sock = SOCK_STREAM;
c = strchr(ulog_path + 6, ':');
ulog_port = DEFAULT_ULOG_PORT;
if (c) {
ulog_dcol = (int) (c - ulog_path);
ulog_port = atoi(c + 1);
if (ulog_port < 1)
ulog_port = DEFAULT_ULOG_PORT;
}
/* FIXME: we don't resolve host names - only IPs are supported for now */
}
#ifdef RSERV_DEBUG
fprintf(stderr, "ULOG: begin %s %s port=%d\n", (u_family == AF_INET) ? "INET" : "UNIX", (u_sock == SOCK_DGRAM) ? "DGRAM" : "STREAM", ulog_port);
#endif
ulog_sock = socket(u_family, u_sock, 0);
if (ulog_sock == -1) return;
#if defined O_NONBLOCK && defined F_SETFL
{ /* try to use non-blocking socket where available */
int flags = fcntl(ulog_sock, F_GETFL, 0);
if (flags != -1)
fcntl(ulog_sock, F_SETFL, flags | O_NONBLOCK);
}
#endif
}
{
struct tm *stm;
time_t now = time(0);
stm = gmtime(&now);
strftime (ts, sizeof(ts), "%Y-%m-%dT%H:%M:%SZ", stm);
#ifdef ULOG_MICROTIME
{ /* this is useful for profiling but breaks the syslog standard */
struct timeval tv;
double t;
gettimeofday(&tv, 0);
t = ((double) tv.tv_sec) + (((double) tv.tv_usec) / 1000000.0);
if (time0 < 1.0) timeN = time0 = t;
snprintf(ts + strlen(ts), sizeof(ts), "[%.4f/%.4f]", t - time0, t - timeN);
timeN = t;
}
#endif
}
/* FIXME: we could cache user/group/pid and show the former
in textual form ... */
/* This format is compatible with the syslog format (RFC5424)
with hard-coded facility (3) and severity (6) */
snprintf(buf, sizeof(buf), "<30>1 %s %s %s %ld %d/%d - ", ts,
hn, app_name, (long) getpid(), (int) getuid(), (int) getgid());
buf_pos = strlen(buf);
}
void ulog_add(const char *format, ...) {
va_list(ap);
va_start(ap, format);
if (buf_pos) {
vsnprintf(buf + buf_pos, sizeof(buf) - buf_pos, format, ap);
buf_pos += strlen(buf + buf_pos);
}
va_end(ap);
}
void ulog_end() {
#if defined (RSERV_DEBUG) || defined (ULOG_STDERR)
buf[buf_pos] = 0;
fprintf(stderr, "ULOG: %s\n", buf);
#endif
if (ulog_sock != -1) {
if (ulog_port) {
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(ulog_port);
ulog_path[ulog_dcol] = 0;
sa.sin_addr.s_addr = inet_addr(ulog_path + 6);
ulog_path[ulog_dcol] = ':'; /* we probably don't even need this ... */
sendto(ulog_sock, buf, buf_pos, 0, (struct sockaddr*) &sa, sizeof(sa));
} else {
struct sockaddr_un sa;
if (!buf_pos) return;
memset(&sa, 0, sizeof(sa));
sa.sun_family = AF_LOCAL;
strcpy(sa.sun_path, ulog_path); /* FIXME: check possible overflow? */
sendto(ulog_sock, buf, buf_pos, 0, (struct sockaddr*) &sa, sizeof(sa));
}
}
buf_pos = 0;
}
void ulog_reset() {
if (ulog_sock != -1)
close(ulog_sock);
ulog_sock = -1;
}
void ulog(const char *format, ...) {
va_list(ap);
va_start(ap, format);
ulog_begin();
#if defined (RSERV_DEBUG) || defined (ULOG_STDERR)
/* in case ulog_begin did not start a line */
if (!buf_pos) {
*buf = ' ';
buf_pos = 1;
}
#endif
if (buf_pos) {
vsnprintf(buf + buf_pos, sizeof(buf) - buf_pos, format, ap);
buf_pos += strlen(buf + buf_pos);
ulog_end();
}
va_end(ap);
}
#else
void ulog_set_path(const char *path) { }
void ulog_set_app_name(const char *name) { }
void ulog_begin() {}
void ulog_add(const char *format, ...) { }
void ulog_end() {}
void ulog(const char *format, ...) { }
void ulog_reset() {}
#endif
Rserve/src/qap_decode.c 0000644 0001760 0000144 00000017207 14147646005 014605 0 ustar ripley users #include "qap_decode.h"
#include
#include
#define decode_to_SEXP QAP_decode
/* string encoding handling */
#if (R_VERSION < R_Version(2,8,0)) || (defined DISABLE_ENCODING)
#define mkRChar(X) mkChar(X)
#else
#define USE_ENCODING 1
extern cetype_t string_encoding;
#define mkRChar(X) mkCharCE((X), string_encoding)
#endif
/* this is only used in debugging output for down-casing
pointers to long on Windows as intermediate step */
#ifdef WIN64
typedef unsigned long long temp_ptr_int_t;
#else
typedef unsigned long temp_ptr_int_t;
#endif
/* this is the representation of NAs in strings. We chose 0xff since that should never occur in UTF-8 strings. If 0xff occurs in the beginning of a string anyway, it will be doubled to avoid misrepresentation. */
static const unsigned char NaStringRepresentation[2] = { 255, 0 };
/* decode_toSEXP is used to decode SEXPs from binary form and create
corresponding objects in R. UPC is a pointer to a counter of
UNPROTECT calls which will be necessary after we're done.
The buffer position is advanced to the point where the SEXP ends
(more precisely it points to the next stored SEXP). */
SEXP decode_to_SEXP(unsigned int **buf)
{
unsigned int *b = *buf, *pab = *buf;
char *c, *cc;
SEXP val = 0, vatt = 0;
int ty = PAR_TYPE(ptoi(*b));
rlen_t ln = PAR_LEN(ptoi(*b));
rlen_t i, l;
if (IS_LARGE(ty)) {
ty ^= XT_LARGE;
b++;
ln |= ((rlen_t) (unsigned int) ptoi(*b)) << 24;
}
#ifdef RSERV_DEBUG
printf("decode: type=%d, len=%ld\n", ty, (long)ln);
#endif
b++;
pab = b; /* pre-attr b */
if (ty & XT_HAS_ATTR) {
#ifdef RSERV_DEBUG
printf(" - has attributes\n");
#endif
*buf = b;
vatt = PROTECT(decode_to_SEXP(buf));
b = *buf;
ty = ty ^ XT_HAS_ATTR;
#ifdef RSERV_DEBUG
printf(" - returned from attributes(@%p)\n", (void*)*buf);
#endif
ln -= (((char*)b) - ((char*)pab)); /* adjust length */
}
/* b = beginning of the SEXP data (after attrs)
pab = beginning before attrs (=just behind the heaer)
ln = length of th SEX payload (w/o attr) */
switch(ty) {
case XT_NULL:
val = R_NilValue;
*buf = b;
break;
case XT_INT:
case XT_ARRAY_INT:
l = ln / 4;
val = allocVector(INTSXP, l);
#ifdef NATIVE_COPY
memcpy(INTEGER(val), b, l * sizeof(int));
b += l;
#else
i = 0;
while (i < l) {
INTEGER(val)[i] = ptoi(*b); i++; b++;
}
#endif
*buf = b;
break;
case XT_ARRAY_BOOL:
{
int vl = ptoi(*(b++));
char *cb = (char*) b;
val = allocVector(LGLSXP, vl);
i = 0;
while (i < vl) {
LOGICAL(val)[i] = (cb[i] == 1) ? TRUE : ((cb[i] == 0) ? FALSE : NA_LOGICAL);
i++;
}
while ((i & 3) != 0) i++;
b = (unsigned int*) (cb + i);
}
*buf = b;
break;
case XT_DOUBLE:
case XT_ARRAY_DOUBLE:
l = ln / 8;
val = allocVector(REALSXP, l);
#ifdef NATIVE_COPY
memcpy(REAL(val), b, sizeof(double) * l);
b += l * 2;
#else
i = 0;
while (i < l) {
fixdcpy(REAL(val) + i, b);
b += 2;
i++;
}
#endif
*buf = b;
break;
case XT_ARRAY_CPLX:
l = ln / 16;
val = allocVector(CPLXSXP, l);
#ifdef NATIVE_COPY
memcpy(COMPLEX(val), b, sizeof(Rcomplex) * l);
b += l * 4;
#else
i = 0;
while (i < l) {
fixdcpy(&(COMPLEX(val)[i].r),b); b+=2;
fixdcpy(&(COMPLEX(val)[i].i),b); b+=2;
i++;
}
#endif
*buf = b;
break;
case XT_ARRAY_STR:
{
/* count the number of elements */
char *sen = (c = (char*)(b)) + ln;
i = 0;
while (c < sen) {
if (!*c) i++;
c++;
}
/* protect so we can alloc CHARSXPs */
val = PROTECT(allocVector(STRSXP, i));
i = 0; cc = c = (char*)b;
while (c < sen) {
SEXP sx;
if (!*c) {
if ((unsigned char)cc[0] == NaStringRepresentation[0]) {
if ((unsigned char)cc[1] == NaStringRepresentation[1])
sx = R_NaString;
else
sx = mkRChar(cc + 1);
} else sx = mkRChar(cc);
SET_STRING_ELT(val, i, sx);
i++;
cc = c + 1;
}
c++;
}
UNPROTECT(1);
}
*buf = (unsigned int*)((char*)b + ln);
break;
case XT_RAW:
i = ptoi(*b);
val = allocVector(RAWSXP, i);
memcpy(RAW(val), (b + 1), i);
*buf = (unsigned int*)((char*)b + ln);
break;
case XT_VECTOR:
case XT_VECTOR_EXP:
{
unsigned char *ie = (unsigned char*) b + ln;
rlen_t n = 0;
SEXP vr = PROTECT(CONS(R_NilValue, R_NilValue));
SEXP tail = vr;
*buf = b;
while ((unsigned char*)*buf < ie) {
SEXP v = decode_to_SEXP(buf);
/* CONS() protects its arguments if GC is needed so v is safe */
SEXP ne = CONS(v, R_NilValue);
SETCDR(tail, ne);
tail = ne;
n++;
}
#ifdef RSERV_DEBUG
printf(" vector (%s), %ld elements\n", (ty == XT_VECTOR) ? "generic" : ((ty == XT_VECTOR_EXP) ? "expression" : "string"), (long) n);
#endif
val = PROTECT(allocVector((ty==XT_VECTOR) ? VECSXP : ((ty == XT_VECTOR_EXP) ? EXPRSXP : STRSXP), n));
n = 0;
while (CDR(vr) != R_NilValue) {
vr = CDR(vr);
SET_VECTOR_ELT(val, n++, CAR(vr));
}
#ifdef RSERV_DEBUG
printf(" end of vector %lx/%lx\n",
(unsigned long) ((temp_ptr_int_t) *buf),
(unsigned long) ((temp_ptr_int_t) ie));
#endif
UNPROTECT(2); /* val and vr */
break;
}
case XT_STR:
case XT_SYMNAME:
/* i=ptoi(*b);
b++; */
#ifdef RSERV_DEBUG
printf(" string/symbol(%d) '%s'\n", ty, (char*)b);
#endif
{
char *c = (char*) b;
if (ty == XT_STR) {
val = mkRChar(c);
} else
val = install(c);
}
*buf = (unsigned int*)((char*)b + ln);
break;
case XT_S4:
val = Rf_allocS4Object();
break;
case XT_LIST_NOTAG:
case XT_LIST_TAG:
case XT_LANG_NOTAG:
case XT_LANG_TAG:
{
SEXP vnext = R_NilValue, vtail = 0;
unsigned char *ie = (unsigned char*) b + ln;
val = R_NilValue;
*buf = b;
while ((unsigned char*)*buf < ie) {
#ifdef RSERV_DEBUG
printf(" el %08lx of %08lx\n",
(unsigned long) ((temp_ptr_int_t) *buf),
(unsigned long) ((temp_ptr_int_t) ie));
#endif
SEXP el = PROTECT(decode_to_SEXP(buf));
SEXP ea = R_NilValue;
if (ty == XT_LANG_TAG || ty==XT_LIST_TAG) {
#ifdef RSERV_DEBUG
printf(" tag %08lx of %08lx\n",
(unsigned long) ((temp_ptr_int_t) *buf),
(unsigned long) ((temp_ptr_int_t) ie));
#endif
ea = decode_to_SEXP(buf);
if (ea != R_NilValue) PROTECT(ea);
}
if (ty == XT_LANG_TAG || ty == XT_LANG_NOTAG)
vnext = LCONS(el, R_NilValue);
else
vnext = CONS(el, R_NilValue);
PROTECT(vnext);
if (ea != R_NilValue)
SET_TAG(vnext, ea);
if (vtail) {
SETCDR(vtail, vnext);
UNPROTECT((ea == R_NilValue) ? 2 : 3);
} else {
UNPROTECT((ea == R_NilValue) ? 2 : 3);
val = vnext;
PROTECT(val); /* protect the root */
}
vtail = vnext;
}
if (vtail) UNPROTECT(1);
break;
}
default:
REprintf("Rserve SEXP parsing: unsupported type %d\n", ty);
val = R_NilValue;
*buf = (unsigned int*)((char*)b + ln);
}
if (vatt) {
/* if vatt contains "class" we have to set the object bit [we could use classgets(vec,kls) instead] */
SEXP head = vatt;
int has_class = 0;
PROTECT(val);
SET_ATTRIB(val, vatt);
while (head != R_NilValue) {
if (TAG(head) == R_ClassSymbol) {
has_class = 1; break;
}
head = CDR(head);
}
if (has_class) /* if it has a class slot, we have to set the object bit */
SET_OBJECT(val, 1);
#ifdef SET_S4_OBJECT
/* FIXME: we have currently no way of knowing whether an object
derived from a non-S4 type is actually S4 object. Hence
we can only flag "pure" S4 objects */
if (TYPEOF(val) == S4SXP)
SET_S4_OBJECT(val);
#endif
UNPROTECT(2); /* vatt + val */
}
/* NOTE: val is NOT protected - this guarantees that recursion doesn't fill up the stack */
return val;
}
Rserve/src/ioc.c 0000644 0001760 0000144 00000012171 14147646005 013266 0 ustar ripley users /* threaded buffering of stdout/err to pass back to
a synchronous process
(C)Copyright 2014 Simon Urbanek
License any of: BSD, GPL-2, GPL-3
*/
#ifndef NO_CONFIG_H
#include "config.h"
#endif
#if defined WITH_THREADS || ! defined WIN32
#include
#include
#include
#include
#include
#include
static int stdoutFD, stderrFD, triggerFD;
static volatile unsigned int head, tail;
static unsigned int alloc;
static char *buf;
static volatile int ioc_active = 0;
pthread_mutex_t buffer_mux = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t trigger_mux = PTHREAD_MUTEX_INITIALIZER;
void ulog(const char *format, ...);
static void *feed_thread(void *whichFD) {
int ta = 1024*1024, fd = stdoutFD;
char *thb = (char*) malloc(ta + 8);
unsigned int *h = (unsigned int*) thb, mask = 0;
if (!thb) return 0;
if (whichFD == &stderrFD) {
fd = stderrFD;
mask = 0x80000000;
}
ulog("feed_thread started, mask=0x%x\n", mask);
while (ioc_active) {
int n = read(fd, thb + 4, ta), dst;
ulog("feed_thread n = %d\n", n);
if (n == -1 && errno != EINTR)
break;
pthread_mutex_lock(&buffer_mux);
dst = tail;
tail = (tail + n + 4) & (alloc - 1);
*h = n | mask;
n += 4;
if (tail < dst) {
memcpy(buf + dst, thb, alloc - dst);
n -= alloc - dst;
memcpy(buf, thb + alloc - dst, n);
} else
memcpy(buf + dst, thb, n);
ulog("feed_thread: tail = %d\n", tail);
pthread_mutex_unlock(&buffer_mux);
pthread_mutex_unlock(&trigger_mux);
}
close(fd);
return 0;
}
static void *read_thread(void *dummy) {
ulog("read_thread started\n");
while (ioc_active) {
volatile int head0, tail0;
/* lock just to get a consistent state */
pthread_mutex_lock(&buffer_mux);
head0 = head;
tail0 = tail;
pthread_mutex_unlock(&buffer_mux);
/* if there is nothing to do, lock so
we get notified */
if (head0 == tail0) {
pthread_mutex_lock(&trigger_mux);
continue;
}
ulog("read_thread: [%d/%d]\n", head0, tail0);
if (head0 > tail0) {
while (head0 < alloc) {
int n = write(triggerFD, buf + head0, alloc - head0);
if (n > 0 && n < alloc - head0) {
pthread_mutex_lock(&buffer_mux);
head0 += n;
if (head0 >= alloc) head0 -= alloc;
head = head0;
pthread_mutex_unlock(&buffer_mux);
continue;
}
if (n < 0 && errno != EINTR) {
ulog("ERROR: lost output pipe, aborting\n");
close(triggerFD);
return 0;
}
}
head0 = 0;
}
while (head0 < tail0) {
int n = write(triggerFD, buf + head0, tail0 - head0);
if (n > 0 && n < tail0 - head0) {
pthread_mutex_lock(&buffer_mux);
head0 += n;
head = head0;
pthread_mutex_unlock(&buffer_mux);
continue;
}
if (n < 0 && errno != EINTR) {
ulog("ERROR: lost output pipe, aborting\n");
close(triggerFD);
return 0;
}
head0 += n;
}
pthread_mutex_lock(&buffer_mux);
head = tail0;
pthread_mutex_unlock(&buffer_mux);
/* we don't unlock the trigger mutex
since that's how the feed threads wake us up */
}
return 0;
}
#include
static int readFD;
/* on fork() remove all forwarding from the children */
static void atfork_prepare() { }
static void atfork_parent() { }
static void atfork_child() {
ioc_active = 0;
close(stdoutFD);
close(stderrFD);
close(triggerFD);
}
int ioc_setup() {
int pfd[2];
pthread_t thread;
pthread_attr_t thread_attr;
alloc = 1024*1024;
buf = malloc(alloc);
if (!buf)
Rf_error("cannot allocate buffer");
if (pipe(pfd)) return 0;
dup2(pfd[1], STDOUT_FILENO);
close(pfd[1]);
stdoutFD = pfd[0];
if (pipe(pfd)) return 0;
dup2(pfd[1], STDERR_FILENO);
close(pfd[1]);
stderrFD = pfd[0];
if (pipe(pfd)) return 0;
triggerFD = pfd[1];
ioc_active = 1;
pthread_attr_init(&thread_attr);
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
pthread_create(&thread, &thread_attr, feed_thread, &stdoutFD);
#if defined RSERV_DEBUG || defined ULOG_STDERR
ulog("NOTE: cannot forward stderr in debug builds since it would cause infinite recursion");
#else
pthread_attr_init(&thread_attr);
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
pthread_create(&thread, &thread_attr, feed_thread, &stderrFD);
#endif
pthread_attr_init(&thread_attr);
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
pthread_create(&thread, &thread_attr, read_thread, 0);
pthread_atfork(atfork_prepare, atfork_parent, atfork_child);
ulog("setup done, fd = %d\n", pfd[0]);
return (readFD = pfd[0]);
}
SEXP ioc_read(int *type) {
SEXP res;
unsigned int h;
int n = read(readFD, &h, sizeof(h));
if (n != sizeof(h))
Rf_error("failed to read header");
ulog("header = 0x%x\n", h);
if (type)
type[0] = (h & 0x80000000) ? 1 : 0;
h &= 0x7fffffff;
res = Rf_allocVector(RAWSXP, h);
n = read(readFD, RAW(res), h);
if (n != h)
Rf_error("read error (n=%d)", n);
return res;
}
#else
#include
int ioc_setup() {
return 0;
}
SEXP ioc_read(int *type) {
Rf_error("I/O redirection or threads not supported on this platform");
return R_NilValue;
}
#endif
Rserve/src/RSserver.c 0000644 0001760 0000144 00000012503 14147646005 014266 0 ustar ripley users #include "RSserver.h"
#include "rserr.h"
#define SOCK_ERRORS
#define LISTENQ 16
#include
#ifdef unix
#include /* needed for unix sockets */
#endif
#include
#include
/* AF_LOCAL is the POSIX version of AF_UNIX - we need this e.g. for AIX */
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#endif
/* keep track of all bound server sockets so they can be easily all closed after fork
this is important for two reasons: so ports don't get stuck bound after the server
has been shut down but children are still around, and so that a rogue child cannot
impersonate the server after the server has been shut down (since the port may have
been bound at higher privileges than the child may have at this point) */
#define MAX_SRVS 512
static int active_srv_sockets[MAX_SRVS];
static void add_active_srv_socket(int s) {
int i = 0;
while (active_srv_sockets[i] && i < MAX_SRVS) {
if (active_srv_sockets[i] == s) return;
i++;
}
if (i < MAX_SRVS)
active_srv_sockets[i] = s;
}
static void rm_active_srv_socket(int s) {
int i = 0;
while (i < MAX_SRVS) {
if (active_srv_sockets[i] == s) {
active_srv_sockets[i] = 0;
break;
}
i++;
}
}
/* this is typically used after fork in the child process */
void close_all_srv_sockets() {
int i = 0;
while (i < MAX_SRVS) {
if (active_srv_sockets[i]) closesocket(active_srv_sockets[i]);
i++;
}
}
/* provides client socket from accept() to the server so that it can
modify the socket as needed according to the server flags */
void accepted_server(server_t *srv, int cs) {
#ifdef SO_KEEPALIVE
/* if keep-alive is enabled and supported - try to set it */
if (srv->flags & SRV_KEEPALIVE) {
int ka = 1;
setsockopt(cs, SOL_SOCKET, SO_KEEPALIVE, (const char *) &ka, sizeof(ka));
}
#endif
}
server_t *create_server(int port, const char *localSocketName, int localSocketMode, int flags) {
server_t *srv;
SAIN ssa;
int reuse, ss;
#ifdef HAVE_IPV6
struct sockaddr_in6 ssa6;
#endif
#ifdef unix
struct sockaddr_un lusa;
#endif
#ifdef RSERV_DEBUG
printf(" - create_server(port = %d, socket = %s, mode = %d, flags = 0x%x)\n", port, localSocketName ? localSocketName : "", localSocketMode, flags);
#endif
initsocks();
if (localSocketName) {
#ifndef unix
RSEprintf("ERROR: Local sockets are not supported on non-unix systems.\n");
return 0;
#else
ss = FCF("open socket", socket(AF_LOCAL, SOCK_STREAM, 0));
memset(&lusa, 0, sizeof(lusa));
lusa.sun_family = AF_LOCAL;
if (strlen(localSocketName) > sizeof(lusa.sun_path) - 2) {
RSEprintf("ERROR: Local socket name is too long for this system.\n");
return 0;
}
strcpy(lusa.sun_path, localSocketName);
remove(localSocketName); /* remove existing if possible */
#endif
} else
#ifdef HAVE_IPV6
ss = FCF("open socket", socket((flags & SRV_IPV6) ? AF_INET6 : AF_INET, SOCK_STREAM, 0));
#else
ss = FCF("open socket", socket(AF_INET, SOCK_STREAM, 0));
#endif
srv = (server_t*) calloc(1, sizeof(server_t));
if (!srv) {
RSEprintf("ERROR: cannot allocate memory for server structure\n");
return 0;
}
srv->ss = ss;
srv->unix_socket = localSocketName ? 1 : 0;
srv->flags = flags;
srv->parent = 0;
reuse = 1; /* enable socket address reusage */
setsockopt(ss, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse));
#ifdef unix
if (localSocketName) {
FCF("bind", bind(ss, (SA*) &lusa, sizeof(lusa)));
if (localSocketMode)
chmod(localSocketName, localSocketMode);
} else {
#endif
#ifdef HAVE_IPV6
if (flags & SRV_IPV6) {
memset(&ssa6, 0, sizeof(ssa6));
ssa6.sin6_family = AF_INET6;
ssa6.sin6_port = htons(port);
ssa6.sin6_addr = (flags & SRV_LOCAL) ? in6addr_loopback : in6addr_any;
FCF("bind", bind(ss, (struct sockaddr*) &ssa6, sizeof(ssa6)));
} else {
#endif
memset(&ssa, 0, sizeof(ssa));
ssa.sin_family = AF_INET;
ssa.sin_port = htons(port);
ssa.sin_addr.s_addr = htonl((flags & SRV_LOCAL) ? INADDR_LOOPBACK : INADDR_ANY);
FCF("bind", bind(ss, (struct sockaddr*) &ssa, sizeof(ssa)));
#ifdef HAVE_IPV6
} /* if (flags & SRV_IPV6) else */
#endif
#ifdef unix
} /* if (localSocketName) else */
#endif
add_active_srv_socket(ss);
FCF("listen", listen(ss, LISTENQ));
return srv;
}
void server_fin(void *x) {
server_t *srv = (server_t*) x;
if (srv) {
closesocket(srv->ss);
if (srv->ss != -1) rm_active_srv_socket(srv->ss);
}
}
#define NSPS 16
struct server_stack {
server_stack_t *prev, *next;
int ns;
server_t *srv[NSPS];
};
server_stack_t* create_server_stack() {
server_stack_t *s = (server_stack_t*) malloc(sizeof(server_stack_t));
s->prev = s->next = 0;
s->ns = 0;
return s;
}
void push_server(server_stack_t *s, server_t *srv) {
while (s->ns >= NSPS && s->next) s = s->next;
if (s->ns >= NSPS) {
server_stack_t *ns = create_server_stack();
ns->prev = s;
s = s->next = ns;
}
s->srv[s->ns++] = srv;
}
void release_server_stack(server_stack_t *s) {
while (s && s->next) s = s->next;
while (s) {
int i = s->ns;
while (i-- > 0) {
rm_server(s->srv[i]);
free(s->srv[i]);
}
s->ns = 0;
s = s->prev;
}
}
int server_stack_size(server_stack_t *s) {
int n = 0;
while (s) {
n += s->ns;
s = s->next;
}
return n;
}
/*--- The following makes the indenting behavior of emacs compatible
with Xcode's 4/4 setting ---*/
/* Local Variables: */
/* indent-tabs-mode: t */
/* tab-width: 4 */
/* c-basic-offset: 4 */
/* End: */
Rserve/src/utils.c 0000644 0001760 0000144 00000011120 14147646005 013645 0 ustar ripley users #define USE_RINTERNALS 1
#include
#include
#include
/* string encoding handling */
#if (R_VERSION < R_Version(2,8,0)) || (defined DISABLE_ENCODING)
#define mkRChar(X) mkChar(X)
#else
#define USE_ENCODING 1
/* in Rserv.c */
extern cetype_t string_encoding; /* default is native */
#define mkRChar(X) mkCharCE((X), string_encoding)
#endif
extern Rboolean R_Visible;
/* this is really convoluted - we want to be guaranteed to not leave the call
on one hand, but on the other hand R_ToplevelExec() removes the context
which also removes the traceback. So the trick is to use R_ExecWithCleanup()
to add another layer where we stash the traceback before R_ToplevelExec()
blows it away. It woudl be really just one extra line in R sources, but
what can you do ... */
typedef struct rs_eval {
SEXP what, rho, ctx_obj, last, traceback;
int exp;
} rs_eval_t;
static SEXP Rserve_eval_do(void *arg) {
rs_eval_t *e = (rs_eval_t*) arg;
SEXP what = e->what, rho = e->rho, x;
int i, n;
if (TYPEOF(what) == EXPRSXP) {
n = LENGTH(what);
for (i = 0; i < n; i++) {
e->exp = i;
x = eval(VECTOR_ELT(what, i), rho);
if (i == n - 1) {
R_PreserveObject(x);
e->last = x;
}
if (R_Visible)
PrintValue(x);
}
} else {
e->exp = -1;
x = eval(what, rho);
R_PreserveObject(x);
/* intentionally we don't print if it is not an expression vector */
e->last = x;
}
return R_NilValue;
}
/* it's really stupid becasue R has R_GetTraceback() but we have to
jump through eval() just because it's hidden so we can't access it ... */
static SEXP R_GetTraceback(int skip) {
SEXP d_int = install(".Internal"), tb = install("traceback"), sSkip = PROTECT(ScalarInteger(skip));
SEXP what = PROTECT(lang2(d_int, lang2(tb, sSkip)));
SEXP res = eval(what, R_GlobalEnv);
UNPROTECT(2);
return res;
}
static void Rserve_eval_cleanup(void *arg) {
rs_eval_t *e = (rs_eval_t*) arg;
SEXP tb = R_GetTraceback(0);
if (tb && tb != R_NilValue)
R_PreserveObject((e->traceback = tb));
}
static void Rserve_eval_(void *arg) {
R_ExecWithCleanup(Rserve_eval_do, arg, Rserve_eval_cleanup, arg);
}
static SEXP RS_current_context;
static int RS_current_context_is_protected;
SEXP Rserve_get_context() {
return RS_current_context ? RS_current_context : R_NilValue;
}
SEXP Rserve_set_context(SEXP sObj) {
if (!sObj)
sObj = R_NilValue;
if (RS_current_context == sObj) return sObj;
if (RS_current_context != R_NilValue && RS_current_context_is_protected)
R_ReleaseObject(RS_current_context);
RS_current_context = sObj;
RS_current_context_is_protected = 0;
if (RS_current_context != R_NilValue) {
R_PreserveObject(RS_current_context);
RS_current_context_is_protected = 1;
}
return RS_current_context;
}
SEXP Rserve_eval(SEXP what, SEXP rho, SEXP retLast, SEXP retExp, SEXP ctxObj) {
int need_last = asInteger(retLast), exp_value = asInteger(retExp);
rs_eval_t e = { what, rho, 0, 0, 0, 0 };
SEXP saved_context = RS_current_context;
int saved_context_is_protected = RS_current_context_is_protected;
if (ctxObj != R_NilValue) {
RS_current_context = ctxObj; /* this is transient so no protection */
RS_current_context_is_protected = 0;
}
e.ctx_obj = RS_current_context;
if (!R_ToplevelExec(Rserve_eval_, &e)) {
RS_current_context = saved_context;
RS_current_context_is_protected = saved_context_is_protected;
SEXP res = PROTECT(mkNamed(VECSXP, (const char*[]) { "error", "traceback", "expression", "context", "" }));
SET_VECTOR_ELT(res, 1, e.traceback ? e.traceback : R_NilValue);
const char *errmsg = R_curErrorBuf();
SET_VECTOR_ELT(res, 0, errmsg ? mkString(errmsg) : R_NilValue);
if (exp_value)
SET_VECTOR_ELT(res, 2, (e.exp == -1) ? what : VECTOR_ELT(what, e.exp));
else
SET_VECTOR_ELT(res, 2, ScalarInteger(e.exp < 0 ? NA_INTEGER : (e.exp + 1)));
SET_VECTOR_ELT(res, 3, e.ctx_obj ? e.ctx_obj : R_NilValue);
setAttrib(res, R_ClassSymbol, mkString("Rserve-eval-error"));
UNPROTECT(1);
return res;
}
RS_current_context = saved_context;
RS_current_context_is_protected = saved_context_is_protected;
if (need_last) {
if (e.last) {
R_ReleaseObject(e.last);
return e.last;
}
return R_NilValue;
}
return ScalarLogical(TRUE);
}
Rserve/src/include/ 0000755 0001760 0000144 00000000000 14147646005 013771 5 ustar ripley users Rserve/src/include/Win32/ 0000755 0001760 0000144 00000000000 14147646005 014673 5 ustar ripley users Rserve/src/include/Win32/config.h 0000644 0001760 0000144 00000003440 14147646005 016312 0 ustar ripley users /* config.h for Windows
This file is based on a config.h as generated by configure run
on a MinGW gcc system. Most of it is not used, because many
parts of Rserve have its own Win32 code, but it may become handy
at some later point.
Last update: Rserve 0.4-5, R 2.4.0, MinGW gcc 3.4.5
*/
/* Defined if the platform is little-endian */
#define BS_LITTLE_ENDIAN 1
/* Define to 1 if you have the header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#define HAVE_MALLOC 1
/* Define to 1 if you have the header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `memset' function. */
#define HAVE_MEMSET 1
/* Define to 1 if you have the `mkdir' function. */
#define HAVE_MKDIR 1
/* Define to 1 if you have the `rmdir' function. */
#define HAVE_RMDIR 1
/* Define to 1 if you have the header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to 1 if you can safely include both and . */
#define TIME_WITH_SYS_TIME 1
/* CRAN has OpenSSL so we can use TLS */
#define HAVE_TLS 1
Rserve/src/include/Win32/Startup.h 0000644 0001760 0000144 00000005474 14147646005 016520 0 ustar ripley users /*
* R : A Computer Language for Statistical Data Analysis
* Copyright (C) 1999-2003 The R Development Core Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef STARTUP_H_
#define STARTUP_H_
#include /* TRUE/FALSE */
#ifdef Win32
typedef int (*blah1) (char *, char *, int, int);
typedef void (*blah2) (char *, int);
typedef void (*blah3) ();
typedef void (*blah4) (char *);
typedef int (*blah5) (char *);
typedef void (*blah6) (int);
typedef enum {RGui, RTerm, LinkDLL} UImode;
#endif
/* Startup Actions */
typedef enum {
SA_NORESTORE,/* = 0 */
SA_RESTORE,
SA_DEFAULT,/* was === SA_RESTORE */
SA_NOSAVE,
SA_SAVE,
SA_SAVEASK,
SA_SUICIDE
} SA_TYPE;
typedef struct
{
Rboolean R_Quiet;
Rboolean R_Slave;
Rboolean R_Interactive;
Rboolean R_Verbose;
Rboolean LoadSiteFile;
Rboolean LoadInitFile;
Rboolean DebugInitFile;
SA_TYPE RestoreAction;
SA_TYPE SaveAction;
unsigned long vsize;
unsigned long nsize;
unsigned long max_vsize;
unsigned long max_nsize;
unsigned long ppsize;
int NoRenviron;
/* Permanent copy of the command line arguments and the number
of them passed to the application.
These are populated via the routine R_set_command_line_arguments()
called from R_common_command_line().
*/
int NumCommandLineArgs;
char **CommandLineArgs;
#ifdef Win32
char *rhome; /* R_HOME */
char *home; /* HOME */
blah1 ReadConsole;
blah2 WriteConsole;
blah3 CallBack;
blah4 message;
blah5 yesnocancel;
blah6 busy;
UImode CharacterMode;
Rboolean DebugMenuitem;
#endif
} structRstart;
typedef structRstart *Rstart;
void R_DefParams(Rstart);
void R_SetParams(Rstart);
void R_SetWin32(Rstart);
void R_SizeFromEnv(Rstart);
void R_common_command_line(int *, char **, Rstart);
void R_set_command_line_arguments(int argc, char **argv, Rstart Rp);
void setup_Rmainloop(void);
/* originally from Defn.h : */
void R_CleanUp(SA_TYPE, int, int);
void R_StartUp(void);
FILE *R_OpenInitFile(void);
FILE *R_OpenSysInitFile(void);
FILE *R_OpenSiteFile(void);
#endif
Rserve/src/include/Win32/psignal.h 0000644 0001760 0000144 00000014100 14147646005 016475 0 ustar ripley users /*****************************************************************************
* *
* signal.h *
* *
* Freely redistributable and modifiable. Use at your own risk. *
* *
* Copyright 1994-1999 The Downhill Project *
* http://www.ede.com/free/u2nt *
* *
*****************************************************************************/
/*
Original version taken at
Changes (g.m.):
10.06.1999: Made self contained - Changed some names
11.06.1999: Added 'sigsetjmp' and 'siglongjmp'
12.06.1999: Added pause and sigsuspend (require a version (also
a non POSIX one) of sleep; if your system don't have it
define DONT_HAVE_SLEEP)
27/06/1999: (BDR) convert sigsetjmp and siglongjmp macros to (,,)
12/07/1999: (BDR) fix sigsetjmp macro to set saved_mask
*/
#ifndef _PSIGNAL_H_
#define _PSIGNAL_H_
#include
#include
#include
#define SIGHUP 1 /* hangup */
#define SIGINT 2 /* interrupt */
#define SIGQUIT 3 /* quit */
#define SIGILL 4 /* illegal instruction (not reset when caught) */
#define SIGTRAP 5 /* trace trap (not reset when caught) */
#define SIGEMT 7 /* EMT instruction */
#define SIGFPE 8 /* floating point exception */
#define SIGKILL 9 /* kill (cannot be caught or ignored) */
#define SIGBUS 10 /* bus error */
#define SIGSEGV 11 /* segmentation violation */
#define SIGSYS 12 /* bad argument to system call */
#define SIGPIPE 13 /* write on a pipe with no one to read it */
#define SIGALRM 14 /* alarm clock */
#define SIGTERM 15 /* software termination signal from kill */
#define SIGURG 16 /* urgent condition on IO channel */
#define SIGSTOP 17 /* sendable stop signal not from tty */
#define SIGTSTP 18 /* stop signal from tty */
#define SIGCONT 19 /* continue a stopped process */
#define SIGCHLD 20 /* to parent on child stop or exit */
#define SIGCLD 20 /* System V name for SIGCHLD */
#define SIGBREAK 21 /* to readers pgrp upon background tty read */
#define SIGABRT 22 /* used by abort */
#define SIGIO 23 /* input/output possible signal */
#define SIGPOLL SIGIO /* System V name for SIGIO */
#define SIGXCPU 24 /* exceeded CPU time limit */
#define SIGXFSZ 25 /* exceeded file size limit */
#define SIGVTALRM 26 /* virtual time alarm */
#define SIGPROF 27 /* profiling time alarm */
#define SIGWINCH 28 /* window changed */
#define SIGLOST 29 /* resource lost (eg, record-lock lost) */
#define SIGUSR1 30 /* user defined signal 1 */
#define SIGUSR2 31 /* user defined signal 2 */
#define NSIG 32 /* signal 0 implied */
#ifndef RC_INVOKED
/*
* A pointer to a signal handler function. A signal handler takes a
* single int, which is the signal it handles.
*/
typedef void (*sighandler_t)(int nSig);
#ifndef _SIGSET_T_
#define _SIGSET_T_
typedef int sigset_t;
#endif /* Not _SIGSET_T_ */
/*
* These are special values of signal handler pointers which are
* used to send a signal to the default handler (SIG_DFL), ignore
* the signal (SIG_IGN), or indicate an error return (SIG_ERR).
*/
#define SIG_DFL ((sighandler_t) 0)
#define SIG_IGN ((sighandler_t) 1)
#define SIG_ERR ((sighandler_t) -1)
#ifdef __cplusplus
extern "C" {
#endif
/* Signal mask actions ===================================================== */
#define SIG_BLOCK 0
#define SIG_UNBLOCK 1
#define SIG_SETMASK 2
/* Signal flag actions ===================================================== */
#define SA_NOCLDSTOP 1
#define SA_RESETHAND 2
/* Struct stuff **************************************************************/struct sigaction
{
void (*sa_handler)(int);
sigset_t sa_mask;
int sa_flags;
};
typedef struct
{
jmp_buf jmpbuf; /* Calling environment. */
int mask_was_saved; /* Saved the signal mask? */
sigset_t saved_mask; /* Saved signal mask. */
} sigjmp_buf[1];
/* Prototype stuff ***********************************************************/
unsigned long sigsetmask(unsigned long signal_Block_MaskNew);
unsigned long sigblock(unsigned long signal_Block_MaskNew);
int sighold(int signal_Number);
int sigrelse(int signal_Number);
int sigaction(int signal_Number,struct sigaction* sigaction_Info,
struct sigaction* signaction_InfoOld);
int sigaddset(sigset_t* sigset_Info,int signal_Number);
int sigdelset(sigset_t* sigset_Info,int signal_Number);
int sigemptyset(sigset_t* sigset_Info);
int sigfillset(sigset_t* sigset_Info);
int sigismember(sigset_t* sigset_Info,int signal_Number);
int sigpending(sigset_t* sigset_Info);
int sigprocmask(int mask_Function,sigset_t* sigset_Info,
sigset_t* sigset_InfoOld);
sighandler_t signal(int signal_Number, sighandler_t);
void raise(int);
int pause(void);
int sigsuspend(sigset_t* sigset_Info);
/* Re-mapped functions ===================================================== */
#define sigmask(signal_Index) (1<<(signal_Index-1))
/*
This must be a macro, since we want setjmp working in the
calling environment
*/
/*
#define sigsetjmp(jb, sm) (\
sm?sigprocmask(SIG_SETMASK,NULL,&jb->saved_mask):0,\
jb->mask_was_saved=sm,\
setjmp(jb->jmpbuf))
we only currently use the case sm=0, so avoid compiler warnings by */
#define sigsetjmp(jb, sm) (jb->mask_was_saved=0, setjmp(jb->jmpbuf))
/* We can transform this in a function but ... */
#define siglongjmp(jb, val) (((jb->mask_was_saved)?\
sigprocmask(SIG_SETMASK, &jb->saved_mask, 0):0),\
longjmp(jb->jmpbuf, val))
#ifdef __cplusplus
}
#endif
#endif /* Not RC_INVOKED */
#endif /* Not _PSIGNAL_H_ */
Rserve/src/include/sbthread.h 0000644 0001760 0000144 00000006535 14147646005 015747 0 ustar ripley users /*****************************************************************\
* sbthread - system-independent basic threads *
* (C)Copyright 2001 Simon Urbanek *
*---------------------------------------------------------------*
* Supported platforms: unix w pthread, Win32 *
\*****************************************************************/
#ifndef __SBTHREAD_H__
#define __SBTHREAD_H__
#ifdef unix /* begin unix (pthread) implementation */
#include
#define decl_sbthread void *
#define sbthread_result(A) (void *)(A)
#define sbthread_mutex pthread_mutex_t
sbthread_mutex *sbthread_create_mutex() {
pthread_mutex_t lm=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t *m=(pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
memcpy(m,&lm,sizeof(pthread_mutex_t));
return m;
};
#define sbthread_lock_mutex(M) pthread_mutex_lock(M);
#define sbthread_unlock_mutex(M) pthread_mutex_unlock(M);
void sbthread_destroy_mutex(sbthread_mutex *m) {
pthread_mutex_destroy(m); free(m);
};
int sbthread_create(void * (thr)(void *), void *par) {
pthread_t Thread;
pthread_attr_t ThreadAttr;
pthread_attr_init(&ThreadAttr);
pthread_attr_setdetachstate(&ThreadAttr,PTHREAD_CREATE_DETACHED);
return pthread_create(&Thread,&ThreadAttr,*thr,par);
};
#else /* end of unix, begin of Win32 */
#include
#define decl_sbthread DWORD WINAPI
#define sbthread_result(A) (DWORD)(A)
#define sbthread_mutex char
#ifndef sleep /* this has nothing to do with threads, but may be usefull */
#define sleep(A) Sleep((A)*1000)
#endif
unsigned int sbthread_mutex_counter=1;
sbthread_mutex *sbthread_create_mutex(void) {
char mtxn[64],*c;
unsigned int i,j;
HANDLE m;
strcpy(mtxn,"sbthread_mutex");
/* this isn't really thread-safe, but creating more mutexes
at exactly the same time by different threads on an SMP machine
is ... let's say inprobable. moreover ++ might be atomic.
creating yet another mutex for this single operation seems
to me as an overkill. but if you need 100% thread-safe code,
feel free to implement it here ;) */
sbthread_mutex_counter++;
i=15; j=sbthread_mutex_counter;
while (j>0) { mtxn[i]=65+(j&15); i++; j>>=4; };
mtxn[i]=0; i++;
m=CreateMutex(0,0,mtxn);
if (!m) return 0;
memcpy(&mtxn[i],&m,sizeof(m));
i+=sizeof(m)*2+1;
c=(char*)malloc(i); memcpy(c,mtxn,i);
/* content: name\0[createHANDLE][ownershipHANDLE] */
return c;
};
int sbthread_lock_mutex(sbthread_mutex *m) {
HANDLE h;
int i;
h=OpenMutex(MUTEX_ALL_ACCESS,0,m);
if (!h) return 0;
if (WaitForSingleObject(h,INFINITE)==WAIT_FAILED) return 0;
i=strlen(m);
i+=sizeof(h)+1;
memcpy(&m[i],&h,sizeof(h));
return 1;
};
int sbthread_unlock_mutex(sbthread_mutex *m) {
HANDLE h;
int i;
i=strlen(m); i+=sizeof(h)+1;
memcpy(&h,&m[i],sizeof(h));
if (!h) return 0;
memset(&m[i],0,sizeof(h));
ReleaseMutex(h);
CloseHandle(h);
return 1;
};
void sbthread_destroy_mutex(sbthread_mutex *m) {
HANDLE h;
int i;
i=strlen(m); i+=sizeof(h)+1;
memcpy(&h,&m[i],sizeof(h));
if (h) return; // oh, mutex is still in use
memcpy(&h,&m[i-sizeof(h)],sizeof(h));
CloseHandle(h);
free(m);
};
int sbthread_create(LPTHREAD_START_ROUTINE sa, void *par) {
DWORD tid;
return CreateThread(0,0,sa,par,0,&tid);
};
#endif /* Windows implementation */
#endif /* __SBTHREAD_H__ */
Rserve/src/include/Parse.h 0000644 0001760 0000144 00000000474 14147646005 015221 0 ustar ripley users /* This is a fall-back for R versions that don't have R_ext/Parse.h
(R versions before 2.1.0) */
#ifndef R_EXT_PARSE_H_
#define R_EXT_PARSE_H_
typedef enum {
PARSE_NULL,
PARSE_OK,
PARSE_INCOMPLETE,
PARSE_ERROR,
PARSE_EOF
} ParseStatus;
SEXP R_ParseVector(SEXP, int, ParseStatus *);
#endif
Rserve/src/include/sisocks.h 0000644 0001760 0000144 00000017061 14147646005 015625 0 ustar ripley users /* system independent sockets (basically for unix and Win)
* Copyright (C) 2000,1 Simon Urbanek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 of the License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
conditional defines:
MAIN
should be defined in just one file that will contain the fn definitions and variables
USE_SNPRINTF
emulate snprintf on Win platforms (you will
lose the security which is provided under unix of course)
SOCK_ERRORS
include error code handling and checking functions
*/
#ifndef __SISOCKS_H__
#define __SISOCKS_H__
#if defined __GNUC__ && !defined unix && !defined Win32 /* MacOS X hack (gcc on any platform should behave as unix - except for Win32, where we need to keep using winsock) */
#define unix
#endif
#if defined STANDALONE_RSERVE && defined RSERVE_PKG
#undef RSERVE_PKG
#endif
#if defined SOCK_ERRORS || defined USE_SNPRINTF
#include
#endif
#include
#ifdef unix
#include
#include
#include
#include
#include
#include
#include
#define sockerrno errno
#define SOCKET int
#define INVALID_SOCKET (-1)
#define closesocket(A) close(A)
#else
#define windows
#include
#include
#include
#include
#define inet_aton(A,B) (0, B.s_addr=inet_addr(A))
#define sockerrno WSAGetLastError()
#ifndef ECONNREFUSED
#define ECONNREFUSED WSAECONNREFUSED
#endif
#ifndef EADDRINUSE
#define EADDRINUSE WSAEADDRINUSE
#endif
#ifndef ENOTSOCK
#define ENOTSOCK WSAENOTSOCK
#endif
#ifndef EISCONN
#define EISCONN WSAEISCONN
#endif
#ifndef ETIMEDOUT
#define ETIMEDOUT WSAETIMEDOUT
#endif
#ifndef ENETUNREACH
#define ENETUNREACH WSAENETUNREACH
#endif
#ifndef EINPROGRESS
#define EINPROGRESS WSAEINPROGRESS
#endif
#ifndef EALREADY
#define EALREADY WSAEALREADY
#endif
#ifndef EOPNOTSUPP
#define EOPNOTSUPP WSAEOPNOTSUPP
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK WSAEWOULDBLOCK
#endif
#ifndef WIN64
#ifndef EAFNOSUPPORT
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#endif
#ifndef EBADF
#define EBADF WSAEBADF
#endif
#ifndef EINVAL
#define EINVAL WSAEINVAL
#endif
#ifndef EFAULT
#define EFAULT WSAEFAULT
#endif
#ifndef EACCES
#define EACCES WSAEACCES
#endif
#endif
#ifdef USE_SNPRINTF
#ifdef MAIN
int snprintf(char *buf, int len, char *fmt, ...)
{
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vsprintf(buf, fmt, argptr);
va_end(argptr);
return(cnt);
}
#else
extern int snprintf(char *buf, int len, char *fmt, ...);
#endif
#endif
#endif
#define SA struct sockaddr
#define SAIN struct sockaddr_in
#ifdef windows
#ifdef MAIN
int initsocks(void)
{
WSADATA dt;
/* initialize WinSock 1.1 */
return (WSAStartup(0x0101,&dt))?-1:0;
}
#else
extern int initsocks(void);
#endif
#define donesocks() WSACleanup()
#else
/* no stupid stuff necessary for unix */
#define initsocks()
#define donesocks()
#endif
#ifdef SOCK_ERRORS
#ifdef MAIN
int suppmode=0;
int socklasterr;
FILE *sockerrlog=0;
/* copy error description to buf or set *buf=0 if none */
int sockerrorchecks(char *buf, int blen, int res) {
*buf=0;
if (res==-1) {
switch(sockerrno) {
case EBADF: strncpy(buf,"bad descriptor",blen); break;
case EINVAL: strncpy(buf,"already in use",blen); break;
case EACCES: strncpy(buf,"access denied",blen); break;
case ENOTSOCK: strncpy(buf,"descriptor is not a socket",blen); break;
case EOPNOTSUPP: strncpy(buf,"operation not supported",blen); break;
case EFAULT: strncpy(buf,"fault",blen); break;
case EWOULDBLOCK: strncpy(buf,"operation would block",blen); break;
case EISCONN: strncpy(buf,"is already connected",blen); break;
case ECONNREFUSED: strncpy(buf,"connection refused",blen); break;
case ETIMEDOUT: strncpy(buf,"operation timed out",blen); break;
case ENETUNREACH: strncpy(buf,"network is unreachable",blen); break;
case EADDRINUSE: strncpy(buf,"address already in use",blen); break;
case EINPROGRESS: strncpy(buf,"in progress",blen); break;
case EALREADY: strncpy(buf,"previous connect request not completed yet",blen); break;
#ifdef unix
default: snprintf(buf,blen,"unknown socket error %d",sockerrno);
#else
default: sprintf(buf,"unknown socket error %d",sockerrno);
#endif
}
}
return res;
}
#ifdef RSERVE_PKG /* use error instead of exit */
#include
int sockerrorcheck(char *sn, int rtb, int res) {
if ((signed int)res == -1) {
char sock_err_buf[72];
sockerrorchecks(sock_err_buf, sizeof(sock_err_buf), res);
if (rtb)
Rf_error("%s socket error #%d (%s)", sn, (int) sockerrno, sock_err_buf);
else
Rf_warning("%s socket error #%d (%s)", sn, (int) sockerrno, sock_err_buf);
}
return res;
}
#else
/* check socket error and add to log file if necessary */
int sockerrorcheck(char *sn, int rtb, int res) {
if (!sockerrlog) sockerrlog=stderr;
if ((signed int)res==-1) {
if (socklasterr==sockerrno) {
suppmode++;
} else {
if (suppmode>0) {
fprintf(sockerrlog,"##> REP: (last error has been repeated %d times.)\n",suppmode);
suppmode=0;
}
fprintf(sockerrlog,"##> SOCK_ERROR: %s error #%d",sn,sockerrno);
switch(sockerrno) {
case EBADF: fprintf(sockerrlog,"(bad descriptor)"); break;
case EINVAL: fprintf(sockerrlog,"(already in use)"); break;
case EACCES: fprintf(sockerrlog,"(access denied)"); break;
case ENOTSOCK: fprintf(sockerrlog,"(descriptor is not a socket)"); break;
case EOPNOTSUPP: fprintf(sockerrlog,"(operation not supported)"); break;
case EFAULT: fprintf(sockerrlog,"(fault)"); break;
case EWOULDBLOCK: fprintf(sockerrlog,"(operation would block)"); break;
case EISCONN: fprintf(sockerrlog,"(is already connected)"); break;
case ECONNREFUSED: fprintf(sockerrlog,"(connection refused)"); break;
case ETIMEDOUT: fprintf(sockerrlog,"(operation timed out)"); break;
case ENETUNREACH: fprintf(sockerrlog,"(network is unreachable)"); break;
case EADDRINUSE: fprintf(sockerrlog,"(address already in use)"); break;
case EINPROGRESS: fprintf(sockerrlog,"(in progress)"); break;
case EALREADY: fprintf(sockerrlog,"(previous connect request not completed yet)"); break;
default: fprintf(sockerrlog,"(?)");
}
fprintf(sockerrlog,"\n"); fflush(sockerrlog);
socklasterr=sockerrno;
}
if (rtb) exit(1);
}
return res;
}
#endif
#else
extern int suppmode;
extern int socklasterr;
extern FILE *sockerrlog;
int sockerrorchecks(char *buf, int blen, int res);
int sockerrorcheck(char *sn, int rtb, int res);
#endif
#define FCF(X,F) sockerrorcheck(X,1,F)
#define CF(X,F) sockerrorcheck(X,0,F)
#endif
#ifdef MAIN
struct sockaddr *build_sin(struct sockaddr_in *sa,char *ip,int port) {
memset(sa,0,sizeof(struct sockaddr_in));
sa->sin_family=AF_INET;
sa->sin_port=htons(port);
sa->sin_addr.s_addr=(ip)?inet_addr(ip):htonl(INADDR_ANY);
return (struct sockaddr*)sa;
}
#else
struct sockaddr *build_sin(struct sockaddr_in *sa,char *ip,int port);
#endif
#endif /* __SISOCKS_H__ */
Rserve/src/oc.c 0000644 0001760 0000144 00000007636 14147646005 013127 0 ustar ripley users #include
#include "oc.h"
#include "sha1.h"
#ifndef NO_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_TLS
#include
#endif
#ifndef HAVE_SRANDOMDEV
/* the fall-back is to use time and pid so we need those extra headers */
#include
#include
#endif
static SEXP oc_env;
SEXP oc_resolve(const char *ref) {
SEXP val;
if (!oc_env) return R_NilValue;
val = findVarInFrame(oc_env, install(ref));
if (val == R_UnboundValue) val = R_NilValue;
return val;
}
/* this is where we generate tokens. The current apporach is to generate good random
168-bits and encode them using slightly modified base-64 encoding into a string.
If we can't get good random bits, we generate more pseudo-random bytes and run
SHA1 on it.
The result is almost a valid identifier except that it can start with a number. */
static int rand_inited;
static const char b64map[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_.";
/* currently we use 21 bytes = 168 bits --> 28 bytes encoded */
#define MAX_OC_TOKEN_LEN 31
/* this is used to create multi-tier OCAPs if needed (0=no prefix, default) */
char Rserve_oc_prefix;
static void oc_new(char *dst) {
int have_hash = 0, i;
unsigned char hash[21];
#ifdef HAVE_TLS
#if OPENSSL_VERSION_NUMBER < 0x10100000L
if (RAND_bytes(hash, 21) == 1 || RAND_pseudo_bytes(hash, 21))
have_hash = 1;
#else /* OpenSSL 1.1+ doesn't support pseudo-bytes fall-back, so don't try - have to use random() instead ... */
if (RAND_bytes(hash, 21) == 1)
have_hash = 1;
#endif
#endif
if (!have_hash) { /* should only be used if TLS is not available or it fails */
unsigned char rbuf[64];
if (!rand_inited) {
#ifdef HAVE_SRANDOMDEV
srandomdev();
#else
#ifdef Win32
srand(time(NULL) ^ (getpid() << 12));
#else
/* fall back -- mix of time and pid is the best we can do ... */
srandom(time(NULL) ^ (getpid() << 12));
#endif
#endif
rand_inited = 1;
}
#ifdef Win32
for (i = 0; i < sizeof(rbuf); i++) rbuf[i] = rand();
#else
for (i = 0; i < sizeof(rbuf); i++) rbuf[i] = random();
#endif
/* we use random -> SHA1 .. is it an overkill? */
sha1hash((const char*)rbuf, sizeof(rbuf) - 1, hash);
/* the last byte is the hold-out byte -- just because SHA gives only 160 bits */
hash[20] = rbuf[sizeof(rbuf) - 1];
}
if (Rserve_oc_prefix)
*(dst++) = Rserve_oc_prefix;
for (i = 0; i < 21; i += 3) {
*(dst++) = b64map[hash[i] & 63];
*(dst++) = b64map[((hash[i] >> 6) | (hash[i + 1] << 2)) & 63];
*(dst++) = b64map[((hash[i + 1] >> 4) | (hash[i + 2] << 4)) & 63];
*(dst++) = b64map[hash[i + 2] >> 2];
}
*dst = 0;
}
char *oc_register(SEXP what, char *dst, int len, const char *name) {
SEXP x;
if (len <= MAX_OC_TOKEN_LEN) return NULL;
if (!oc_env) {
SEXP env = eval(PROTECT(lang3(install("new.env"), ScalarLogical(TRUE), R_EmptyEnv)), R_GlobalEnv);
UNPROTECT(1);
if (TYPEOF(env) != ENVSXP) return NULL;
oc_env = env;
R_PreserveObject(oc_env);
}
x = PROTECT(CONS(what, R_NilValue));
if (name) SET_TAG(x, install(name));
oc_new(dst);
Rf_defineVar(install(dst), x, oc_env);
UNPROTECT(1);
return dst;
}
/* --- R-side API --- */
/* NOTE: if you change the signature, you *have* to change the registration
and declaration in standalone.c !! */
SEXP Rserve_oc_register(SEXP what, SEXP sName) {
const char *name = 0;
char token[MAX_OC_TOKEN_LEN + 1];
SEXP res;
if (TYPEOF(sName) == STRSXP && LENGTH(sName) > 0)
name = CHAR(STRING_ELT(sName, 0));
if (!oc_register(what, token, sizeof(token), name))
Rf_error("Cannot create OC reference registry");
res = PROTECT(mkString(token));
setAttrib(res, R_ClassSymbol, mkString("OCref"));
UNPROTECT(1);
return res;
}
SEXP Rserve_oc_resolve(SEXP what) {
if (!inherits(what, "OCref") || TYPEOF(what) != STRSXP || LENGTH(what) != 1)
Rf_error("invalid OCref");
return CAR(oc_resolve(CHAR(STRING_ELT(what, 0))));
}
Rserve/src/winembed.c 0000644 0001760 0000144 00000017170 14147646005 014312 0 ustar ripley users /*
* R : A Computer Language for Statistical Data Analysis
* Copyright (C) 1998--2002 R Development Core Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef WIN32
/* based on rtest.c
implements Rf_initEmbeddedR which is missing in the Windows-version
of R shared library */
/* 27/03/2000 win32-api needs this */
#define NONAMELESSUNION
#include
#include
#include
#include
#include "Rversion.h"
#if R_VERSION < 0x2010
#include "Startup.h"
#else
#include
#include
#endif
/* flag governing interactivity - from Rserv.c */
extern int Rsrv_interactive;
/* I didn't actually check if 2.10.x is really the point where initEmbedded was introduced but it makes pretty much all this file obsolete */
#if R_VERSION > R_Version(2,10,0)
__declspec(dllimport) int R_Interactive;
int Rf_initEmbeddedR(int argc, char **argv)
{
Rf_initialize_R(argc, argv);
R_Interactive = Rsrv_interactive;
setup_Rmainloop();
return 0;
}
#else /* otherwise we have to do all this manually ... */
/* for signal-handling code */
#include "psignal.h"
/* one way to allow user interrupts: called in ProcessEvents */
#if defined _MSC_VER || defined WIN64
__declspec(dllimport) int UserBreak;
#else
#define UserBreak (*_imp__UserBreak)
extern int UserBreak;
#endif
/* calls into the R DLL */
extern char *getDLLVersion();
extern void R_DefParams(Rstart);
extern void R_SetParams(Rstart);
extern void setup_term_ui(void);
extern void ProcessEvents(void);
extern void end_Rmainloop(void), R_ReplDLLinit(void);
extern int R_ReplDLLdo1();
extern void run_Rmainloop(void);
#ifndef YES
#define YES 1
#endif
#ifndef NO
#define NO -1
#endif
#ifndef CANCEL
#define CANCEL 0
#endif
/* simple input, simple output */
/* This version blocks all events: a real one needs to call ProcessEvents
frequently. See rterm.c and ../system.c for one approach using
a separate thread for input */
int myReadConsole(const char *prompt, char *buf, int len, int addtohistory)
{
fputs(prompt, stdout);
fflush(stdout);
if(fgets(buf, len, stdin)) return 1;
else return 0;
}
void myWriteConsole(const char *buf, int len)
{
printf("%s", buf);
}
void myCallBack()
{
/* called during i/o, eval, graphics in ProcessEvents */
}
void myBusy(int which)
{
/* set a busy cursor ... if which = 1, unset if which = 0 */
}
void myMessage(const char *s)
{
if (!s) return;
myWriteConsole(s, strlen(s));
}
int myYesNoCancel(const char *s)
{
char ss[128];
char a[3];
sprintf(ss, "%s [y/n/c]: ", s);
myReadConsole(ss, a, 3, 0);
switch (a[0]) {
case 'y':
case 'Y':
return YES;
case 'n':
case 'N':
return NO;
default:
return CANCEL;
}
}
static void my_onintr(int sig)
{
UserBreak = 1;
}
static char Rversion[25], RUser[MAX_PATH], RHome[MAX_PATH];
static int dir_exists(const char* dn)
{
DWORD att = GetFileAttributes(dn); /* this actually needs Win2k or higher but I suppose that's ok these days ... */
return (att != INVALID_FILE_ATTRIBUTES && ((att & FILE_ATTRIBUTE_DIRECTORY) != 0 || att == FILE_ATTRIBUTE_NORMAL));
/* the last one is weird, but according to MS docs it can happen any we cannot tell whether it's a file or a directory */
}
static char tmpbuf[8192];
int Rf_initEmbeddedR(int argc, char **argv)
{
structRstart rp;
Rstart Rp = &rp;
char *p;
char rhb[MAX_PATH+10];
DWORD t,s=MAX_PATH;
HKEY k;
const char *arch = 0;
const char *path_suf = 0;
sprintf(Rversion, "%s.%s", R_MAJOR, R_MINOR);
{ char *c = Rversion, *d = Rversion; while (*c) { if (*c=='.') d=c; c++; }; *d=0; }
#ifdef RSERV_DEBUG
printf("Windows: Rf_initEmbeddedR; compiled as %s.%s, DLL is %s\n", R_MAJOR, R_MINOR, getDLLVersion());
#endif
if(strncmp(Rversion, getDLLVersion(), strlen(Rversion)) != 0) {
fprintf(stderr, "Error: R.DLL version (%s) does not match (%s.%s)\n", getDLLVersion(),
R_MAJOR, R_MINOR);
return -1;
}
R_DefParams(Rp);
if(getenv("R_HOME")) {
strcpy(RHome, getenv("R_HOME"));
} else { /* fetch R_HOME from the registry */
/* try HKCU first such that users can override the system setting */
if (RegOpenKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\R-core\\R", 0, KEY_QUERY_VALUE, &k) != ERROR_SUCCESS ||
RegQueryValueEx(k, "InstallPath", 0, &t, (LPVOID)RHome, &s) != ERROR_SUCCESS ||
!dir_exists(RHome)) {
/* then try HKLM where teh system-wide installs would be */
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\R-core\\R", 0, KEY_QUERY_VALUE, &k) != ERROR_SUCCESS ||
RegQueryValueEx(k, "InstallPath", 0, &t, (LPVOID)RHome, &s) != ERROR_SUCCESS) {
fprintf(stderr, "R_HOME must be set or R properly installed (\\Software\\R-core\\R\\InstallPath registry entry must exist).\n");
return -2;
}
}
sprintf(rhb,"R_HOME=%s",RHome);
putenv(rhb);
}
/* on Win32 this should set R_Home (in R_SetParams) as well */
Rp->rhome = RHome;
#ifdef RSERV_DEBUG
printf("R_HOME: %s\n", RHome);
#endif
/* check for multi-arch R */
if (!getenv("R_ARCH")) {
strcpy(tmpbuf, RHome);
#ifdef WIN64
strcat(tmpbuf, "\\bin\\x64\\R.dll");
arch = "R_ARCH=/x64";
#else
strcat(tmpbuf, "\\bin\\i386\\R.dll");
arch = "R_ARCH=/i386";
#endif
if (GetFileAttributes(tmpbuf) != -1) { /* muti-arch R, DLL found */
putenv(arch);
#ifdef RSERV_DEBUG
printf("Multi-architecture R found, setting %s\n", arch);
#endif
} else
arch = 0;
}
if (!arch) {
strcpy(tmpbuf, RHome);
strcat(tmpbuf, "\\bin\\R.dll");
if (GetFileAttributes(tmpbuf) == -1)
printf("WARNING: cannot find R DDL at %s\n check your R installation or make sure PATH is set accordingly\n");
}
/*
* try R_USER then HOME then working directory
*/
if (getenv("R_USER")) {
strcpy(RUser, getenv("R_USER"));
} else if (getenv("HOME")) {
strcpy(RUser, getenv("HOME"));
} else if (getenv("HOMEDIR")) {
strcpy(RUser, getenv("HOMEDIR"));
strcat(RUser, getenv("HOMEPATH"));
} else
GetCurrentDirectory(MAX_PATH, RUser);
p = RUser + (strlen(RUser) - 1);
if (*p == '/' || *p == '\\') *p = '\0';
Rp->home = RUser;
Rp->CharacterMode = LinkDLL;
Rp->ReadConsole = myReadConsole;
Rp->WriteConsole = myWriteConsole;
Rp->CallBack = myCallBack;
#if R_VERSION < 0x2010
Rp->message = myMessage;
Rp->yesnocancel = myYesNoCancel;
Rp->busy = myBusy;
#else
Rp->ShowMessage = myMessage;
Rp->YesNoCancel = myYesNoCancel;
Rp->Busy = myBusy;
#endif
Rp->R_Quiet = TRUE;
Rp->R_Interactive = Rsrv_interactive;
Rp->RestoreAction = SA_RESTORE;
Rp->SaveAction = SA_NOSAVE;
#if R_VERSION < 0x2000
Rp->CommandLineArgs = NULL;
Rp->NumCommandLineArgs = 0;
#endif
/* Rp->nsize = 300000;
Rp->vsize = 6e6; */
R_SetParams(Rp); /* so R_ShowMessage is set */
R_SizeFromEnv(Rp);
R_SetParams(Rp);
FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
signal(SIGBREAK, my_onintr);
setup_term_ui();
setup_Rmainloop();
return 0;
}
#endif
#else
#include
#endif
Rserve/src/http.c 0000644 0001760 0000144 00000075070 14147646005 013502 0 ustar ripley users #include "RSserver.h"
#include "tls.h"
#include "http.h"
#include "websockets.h" /* for connection upgrade */
#include "rserr.h"
#include
#include
#include
/* size of the line buffer for each worker (request and header only)
* requests that have longer headers will be rejected with 413
* Note that cookies can be quite big and some browsers send them
* in one line, so this should not be too small */
#define LINE_BUF_SIZE 32768
/* debug output - change the DBG(X) X to enable debugging output */
#ifdef RSERV_DEBUG
#define DBG(X) X
#else
#define DBG(X)
#endif
/* --- httpd --- */
#define PART_REQUEST 0
#define PART_HEADER 1
#define PART_BODY 2
#define METHOD_POST 1
#define METHOD_GET 2
#define METHOD_HEAD 3
#define METHOD_OTHER 8 /* for custom requests only */
/* attributes of a connection/worker */
#define CONNECTION_CLOSE 0x0001 /* Connection: close response behavior is requested */
#define HOST_HEADER 0x0002 /* headers contained Host: header (required for HTTP/1.1) */
#define HTTP_1_0 0x0004 /* the client requested HTTP/1.0 */
#define CONTENT_LENGTH 0x0008 /* Content-length: was specified in the headers */
#define THREAD_OWNED 0x0010 /* the worker is owned by a thread and cannot removed */
#define THREAD_DISPOSE 0x0020 /* the thread should dispose of the worker */
#define CONTENT_TYPE 0x0040 /* message has a specific content type set */
#define CONTENT_FORM_UENC 0x0080 /* message content type is application/x-www-form-urlencoded */
#define WS_UPGRADE 0x0100 /* upgrade to WebSockets protocol */
struct buffer {
struct buffer *next, *prev;
int size, length;
char data[1];
};
#ifdef unix
#include /* needed for unix sockets */
#endif
struct args {
server_t *srv; /* server that instantiated this connection */
SOCKET s;
SOCKET ss;
int msg_id;
void *res1, *res2;
/* the following entries are not populated by Rserve but can be used by server implemetations */
char *buf, *sbuf;
int ver, bp, bl, sp, sl, flags;
long l1, l2;
/* The following fields are informational, populated by Rserve */
SAIN sa;
int ucix;
#ifdef unix
struct sockaddr_un su;
#endif
char *line_buf; /* line buffer (used for request and headers) */
char *url, *body; /* URL and request body */
char *content_type; /* content type (if set) */
unsigned int line_pos, body_pos; /* positions in the buffers */
long content_length; /* desired content length */
char part, method; /* request part, method */
int attr; /* connection attributes */
char *ws_protocol, *ws_version, *ws_key;
struct buffer *headers; /* buffer holding header lines */
};
#define IS_HTTP_1_1(C) (((C)->attr & HTTP_1_0) == 0)
/* returns the HTTP/x.x string for a given connection - we support 1.0 and 1.1 only */
#define HTTP_SIG(C) (IS_HTTP_1_1(C) ? "HTTP/1.1" : "HTTP/1.0")
#ifndef USE_RINTERNALS
#define USE_RINTERNALS
#include
#endif
/* free buffers starting from the tail(!!) */
static void free_buffer(struct buffer *buf) {
if (!buf) return;
if (buf->prev) free_buffer(buf->prev);
free(buf);
}
/* allocate a new buffer */
static struct buffer *alloc_buffer(int size, struct buffer *parent) {
struct buffer *buf = (struct buffer*) malloc(sizeof(struct buffer) + size);
if (!buf) return buf;
buf->next = 0;
buf->prev = parent;
if (parent) parent->next = buf;
buf->size = size;
buf->length = 0;
return buf;
}
/* convert doubly-linked buffers into one big raw vector */
static SEXP collect_buffers(struct buffer *buf) {
SEXP res;
char *dst;
int len = 0;
if (!buf) return allocVector(RAWSXP, 0);
while (buf->prev) { /* count the total length and find the root */
len += buf->length;
buf = buf->prev;
}
res = allocVector(RAWSXP, len + buf->length);
dst = (char*) RAW(res);
while (buf) {
memcpy(dst, buf->data, buf->length);
dst += buf->length;
buf = buf->next;
}
return res;
}
static void free_args(args_t *c)
{
DBG(printf("finalizing worker %p\n", (void*) c));
if (c->url) {
free(c->url);
c->url = NULL;
}
if (c->line_buf) {
free(c->line_buf);
c->line_buf = NULL;
}
if (c->body) {
free(c->body);
c->body = NULL;
}
if (c->content_type) {
free(c->content_type);
c->content_type = NULL;
}
if (c->headers) {
free_buffer(c->headers);
c->headers = NULL;
}
if (c->ws_key) {
free(c->ws_key);
c->ws_key = NULL;
}
if (c->ws_protocol) {
free(c->ws_protocol);
c->ws_protocol = NULL;
}
if (c->ws_version) {
free(c->ws_version);
c->ws_version = NULL;
}
if (c->s != INVALID_SOCKET) {
closesocket(c->s);
c->s = INVALID_SOCKET;
}
}
static int send_response(args_t *c, const char *buf, unsigned int len)
{
server_t *srv = c->srv;
unsigned int i = 0;
/* we have to tell R to ignore SIGPIPE otherwise it can raise an error
and get us into deep trouble */
while (i < len) {
int n = srv->send(c, buf + i, len - i);
if (n < 1) {
return -1;
}
i += n;
}
return 0;
}
/* sends HTTP/x.x plus the text (which should be of the form " XXX ...") */
static int send_http_response(args_t *c, const char *text) {
char buf[96];
server_t *srv = c->srv;
const char *s = HTTP_SIG(c);
int l = strlen(text), res;
/* reduce the number of packets by sending the payload en-block from buf */
if (l < sizeof(buf) - 10) {
strcpy(buf, s);
strcpy(buf + 8, text);
return send_response(c, buf, l + 8);
}
res = srv->send(c, s, 8);
if (res < 8) return -1;
return send_response(c, text, strlen(text));
}
/* decode URI in place (decoding never expands) */
static void uri_decode(char *s)
{
char *t = s;
while (*s) {
if (*s == '+') { /* + -> SPC */
*(t++) = ' '; s++;
} else if (*s == '%') {
unsigned char ec = 0;
s++;
if (*s >= '0' && *s <= '9') ec |= ((unsigned char)(*s - '0')) << 4;
else if (*s >= 'a' && *s <= 'f') ec |= ((unsigned char)(*s - 'a' + 10)) << 4;
else if (*s >= 'A' && *s <= 'F') ec |= ((unsigned char)(*s - 'A' + 10)) << 4;
if (*s) s++;
if (*s >= '0' && *s <= '9') ec |= (unsigned char)(*s - '0');
else if (*s >= 'a' && *s <= 'f') ec |= (unsigned char)(*s - 'a' + 10);
else if (*s >= 'A' && *s <= 'F') ec |= (unsigned char)(*s - 'A' + 10);
if (*s) s++;
*(t++) = (char) ec;
} else *(t++) = *(s++);
}
*t = 0;
}
/* parse a query string into a named character vector - must NOT be
* URI decoded */
static SEXP parse_query(char *query)
{
int parts = 0;
SEXP res, names;
char *s = query, *key = 0, *value = query, *t = query;
while (*s) {
if (*s == '&') parts++;
s++;
}
parts++;
res = PROTECT(allocVector(STRSXP, parts));
names = PROTECT(allocVector(STRSXP, parts));
s = query;
parts = 0;
while (1) {
if (*s == '=' && !key) { /* first '=' in a part */
key = value;
*(t++) = 0;
value = t;
s++;
} else if (*s == '&' || !*s) { /* next part */
int last_entry = !*s;
*(t++) = 0;
if (!key) key = "";
SET_STRING_ELT(names, parts, mkChar(key));
SET_STRING_ELT(res, parts, mkChar(value));
parts++;
if (last_entry) break;
key = 0;
value = t;
s++;
} else if (*s == '+') { /* + -> SPC */
*(t++) = ' '; s++;
} else if (*s == '%') { /* we cannot use uri_decode becasue we need &/= *before* decoding */
unsigned char ec = 0;
s++;
if (*s >= '0' && *s <= '9') ec |= ((unsigned char)(*s - '0')) << 4;
else if (*s >= 'a' && *s <= 'f') ec |= ((unsigned char)(*s - 'a' + 10)) << 4;
else if (*s >= 'A' && *s <= 'F') ec |= ((unsigned char)(*s - 'A' + 10)) << 4;
if (*s) s++;
if (*s >= '0' && *s <= '9') ec |= (unsigned char)(*s - '0');
else if (*s >= 'a' && *s <= 'f') ec |= (unsigned char)(*s - 'a' + 10);
else if (*s >= 'A' && *s <= 'F') ec |= (unsigned char)(*s - 'A' + 10);
if (*s) s++;
*(t++) = (char) ec;
} else *(t++) = *(s++);
}
setAttrib(res, R_NamesSymbol, names);
UNPROTECT(2);
return res;
}
static SEXP R_ContentTypeName;
/* create an object representing the request body. It is NULL if the body is empty (or zero length).
* In the case of a URL encoded form it will have the same shape as the query string (named string vector).
* In all other cases it will be a raw vector with a "content-type" attribute (if specified in the headers) */
static SEXP parse_request_body(args_t *c) {
if (!c || !c->body) return R_NilValue;
if ((c->attr & CONTENT_FORM_UENC) && !(c->srv->flags & HTTP_RAW_BODY)) { /* URL encoded form - return parsed form */
c->body[c->content_length] = 0; /* the body is guaranteed to have an extra byte for the termination */
return parse_query(c->body);
} else { /* something else - pass it as a raw vector */
SEXP res = PROTECT(Rf_allocVector(RAWSXP, c->content_length));
if (c->content_length)
memcpy(RAW(res), c->body, c->content_length);
if (c->content_type) { /* attach the content type so it can be interpreted */
if (!R_ContentTypeName) R_ContentTypeName = install("content-type");
setAttrib(res, R_ContentTypeName, mkString(c->content_type));
}
UNPROTECT(1);
return res;
}
}
/* finalize a request - essentially for HTTP/1.0 it means that
* we have to close the connection */
static void fin_request(args_t *c) {
if (!IS_HTTP_1_1(c))
c->attr |= CONNECTION_CLOSE;
}
/* process a request by calling the httpd() function in R */
static void process_request(args_t *c)
{
const char *ct = "text/html";
char *query = 0, *s;
SEXP sHeaders = R_NilValue;
int code = 200;
DBG(Rprintf("process request for %p\n", (void*) c));
if (!c || !c->url) return; /* if there is not enough to process, bail out */
if ((c->attr & WS_UPGRADE) && (c->srv->flags & HTTP_WS_UPGRADE)) {
WS13_upgrade(c, c->ws_key, c->ws_protocol, c->ws_version);
/* the WS swtich messes up args since it replaces it with its own version so
we can't go back to serving - just bail out (NOTE: only works when forked!) */
exit(0);
}
s = c->url;
while (*s && *s != '?') s++; /* find the query part */
if (*s) {
*(s++) = 0;
query = s;
}
uri_decode(c->url); /* decode the path part */
{ /* construct "try(httpd(url, query, body, headers), silent=TRUE)" */
SEXP sTrue = PROTECT(ScalarLogical(TRUE));
SEXP sBody = PROTECT(parse_request_body(c));
SEXP sQuery = PROTECT(query ? parse_query(query) : R_NilValue);
SEXP sReqHeaders = PROTECT(c->headers ? collect_buffers(c->headers) : R_NilValue);
SEXP sArgs = PROTECT(list4(mkString(c->url), sQuery, sBody, sReqHeaders));
SEXP sTry = install("try");
SEXP y, x = PROTECT(lang3(sTry,
LCONS(install(".http.request"), sArgs),
sTrue));
SET_TAG(CDR(CDR(x)), install("silent"));
DBG(Rprintf("eval(try(.http.request('%s'),silent=TRUE))\n", c->url));
/* evaluate the above in the global namespace */
x = PROTECT(eval(x, R_GlobalEnv));
/* the result is expected to have one of the following forms:
a) character vector of length 1 => error (possibly from try),
will create 500 response
b) list(payload[, content-type[, headers[, status code]]])
payload: can be a character vector of length one or a
raw vector. if the character vector is named "file" then
the content of a file of that name is the payload
content-type: must be a character vector of length one
or NULL (if present, else default is "text/html")
headers: must be a character vector - the elements will
have CRLF appended and neither Content-type nor
Content-length may be used
status code: must be an integer if present (default is 200)
*/
if (TYPEOF(x) == STRSXP && LENGTH(x) > 0) { /* string means there was an error */
const char *s = CHAR(STRING_ELT(x, 0));
send_http_response(c, " 500 Evaluation error\r\nConnection: close\r\nContent-type: text/plain\r\n\r\n");
DBG(Rprintf("respond with 500 and content: %s\n", s));
if (c->method != METHOD_HEAD)
send_response(c, s, strlen(s));
c->attr |= CONNECTION_CLOSE; /* force close */
UNPROTECT(7);
return;
}
if (TYPEOF(x) == VECSXP && LENGTH(x) > 0) { /* a list (generic vector) can be a real payload */
SEXP xNames = getAttrib(x, R_NamesSymbol);
if (LENGTH(x) > 1) {
SEXP sCT = VECTOR_ELT(x, 1); /* second element is content type if present */
if (TYPEOF(sCT) == STRSXP && LENGTH(sCT) > 0)
ct = CHAR(STRING_ELT(sCT, 0));
if (LENGTH(x) > 2) { /* third element is headers vector */
sHeaders = VECTOR_ELT(x, 2);
if (TYPEOF(sHeaders) != STRSXP)
sHeaders = R_NilValue;
if (LENGTH(x) > 3) /* fourth element is HTTP code */
code = asInteger(VECTOR_ELT(x, 3));
}
}
y = VECTOR_ELT(x, 0);
if (TYPEOF(y) == STRSXP && LENGTH(y) > 0) {
char buf[64];
int is_tmp = 0;
const char *cs = CHAR(STRING_ELT(y, 0)), *fn = 0;
if (code == 200)
send_http_response(c, " 200 OK\r\nContent-type: ");
else {
sprintf(buf, "%s %d Code %d\r\nContent-type: ", HTTP_SIG(c), code, code);
send_response(c, buf, strlen(buf));
}
send_response(c, ct, strlen(ct));
if (sHeaders != R_NilValue) {
unsigned int i = 0, n = LENGTH(sHeaders);
for (; i < n; i++) {
const char *hs = CHAR(STRING_ELT(sHeaders, i));
if (*hs) { /* headers must be non-empty */
send_response(c, "\r\n", 2);
send_response(c, hs, strlen(hs));
}
}
}
/* special content - a file: either list(file="") or list(tmpfile="")
the latter will be deleted once served */
if (TYPEOF(xNames) == STRSXP && LENGTH(xNames) > 0 &&
(!strcmp(CHAR(STRING_ELT(xNames, 0)), "file") || (is_tmp = !strcmp(CHAR(STRING_ELT(xNames, 0)), "tmpfile"))))
fn = cs;
if (fn) {
char *fbuf;
FILE *f = fopen(fn, "rb");
long fsz = 0;
if (!f) {
send_response(c, "\r\nContent-length: 0\r\n\r\n", 23);
UNPROTECT(7);
fin_request(c);
return;
}
fseek(f, 0, SEEK_END);
fsz = ftell(f);
fseek(f, 0, SEEK_SET);
sprintf(buf, "\r\nContent-length: %ld\r\n\r\n", fsz);
send_response(c, buf, strlen(buf));
if (c->method != METHOD_HEAD) {
fbuf = (char*) malloc(32768);
if (fbuf) {
while (fsz > 0 && !feof(f)) {
int rd = (fsz > 32768) ? 32768 : fsz;
if (fread(fbuf, 1, rd, f) != rd) {
free(fbuf);
UNPROTECT(7);
c->attr |= CONNECTION_CLOSE;
fclose(f);
if (is_tmp) unlink(fn);
return;
}
send_response(c, fbuf, rd);
fsz -= rd;
}
free(fbuf);
} else { /* allocation error - get out */
UNPROTECT(7);
c->attr |= CONNECTION_CLOSE;
fclose(f);
if (is_tmp) unlink(fn);
return;
}
}
fclose(f);
if (is_tmp) unlink(fn);
UNPROTECT(7);
fin_request(c);
return;
}
sprintf(buf, "\r\nContent-length: %u\r\n\r\n", (unsigned int) strlen(cs));
send_response(c, buf, strlen(buf));
if (c->method != METHOD_HEAD)
send_response(c, cs, strlen(cs));
UNPROTECT(7);
fin_request(c);
return;
}
if (TYPEOF(y) == RAWSXP) {
char buf[64];
Rbyte *cs = RAW(y);
if (code == 200)
send_http_response(c, " 200 OK\r\nContent-type: ");
else {
sprintf(buf, "%s %d Code %d\r\nContent-type: ", HTTP_SIG(c), code, code);
send_response(c, buf, strlen(buf));
}
send_response(c, ct, strlen(ct));
if (sHeaders != R_NilValue) {
unsigned int i = 0, n = LENGTH(sHeaders);
for (; i < n; i++) {
const char *hs = CHAR(STRING_ELT(sHeaders, i));
send_response(c, "\r\n", 2);
send_response(c, hs, strlen(hs));
}
}
sprintf(buf, "\r\nContent-length: %u\r\n\r\n", LENGTH(y));
send_response(c, buf, strlen(buf));
if (c->method != METHOD_HEAD)
send_response(c, (char*) cs, LENGTH(y));
UNPROTECT(7);
fin_request(c);
return;
}
}
UNPROTECT(7);
}
send_http_response(c, " 500 Invalid response from R\r\nConnection: close\r\nContent-type: text/plain\r\n\r\nServer error: invalid response from R\r\n");
c->attr |= CONNECTION_CLOSE; /* force close */
}
static void http_close(args_t *arg) {
closesocket(arg->s);
arg->s = -1;
}
/* this function is called to fetch new data from the client
* connection socket and process it */
static void http_input_iteration(args_t *c) {
int n;
server_t *srv = c->srv;
DBG(printf("worker_input_handler, data=%p\n", (void*) c));
if (!c) return;
DBG(printf("input handler for worker %p (sock=%d, part=%d, method=%d, line_pos=%d)\n", (void*) c, (int)c->s, (int)c->part, (int)c->method, (int)c->line_pos));
/* FIXME: there is one edge case that is not caught on unix: if
* recv reads two or more full requests into the line buffer then
* this function exits after the first one, but input handlers may
* not trigger, because there may be no further data. It is not
* trivial to fix, because just checking for a full line at the
* beginning and not calling recv won't trigger a new input
* handler. However, under normal circumstance this should not
* happen, because clients should wait for the response and even
* if they don't it's unlikely that both requests get combined
* into one packet. */
if (c->part < PART_BODY) {
char *s = c->line_buf;
n = srv->recv(c, c->line_buf + c->line_pos, LINE_BUF_SIZE - c->line_pos - 1);
DBG(printf("[recv n=%d, line_pos=%d, part=%d]\n", n, c->line_pos, (int)c->part));
if (n < 0) { /* error, scrape this worker */
http_close(c);
return;
}
if (n == 0) { /* connection closed -> try to process and then remove */
process_request(c);
http_close(c);
return;
}
c->line_pos += n;
c->line_buf[c->line_pos] = 0;
DBG(printf("in buffer: {%s}\n", c->line_buf));
while (*s) {
/* ok, we have genuine data in the line buffer */
if (s[0] == '\n' || (s[0] == '\r' && s[1] == '\n')) { /* single, empty line - end of headers */
/* --- check request validity --- */
DBG(printf(" end of request, moving to body\n"));
if (!(c->attr & HTTP_1_0) && !(c->attr & HOST_HEADER)) { /* HTTP/1.1 mandates Host: header */
send_http_response(c, " 400 Bad Request (Host: missing)\r\nConnection: close\r\n\r\n");
http_close(c);
return;
}
if (c->attr & CONTENT_LENGTH && c->content_length) {
if (c->content_length < 0 || /* we are parsing signed so negative numbers are bad */
c->content_length > 2147483640 || /* R will currently have issues with body around 2Gb or more, so better to not go there */
!(c->body = (char*) malloc(c->content_length + 1 /* allocate an extra termination byte */ ))) {
send_http_response(c, " 413 Request Entity Too Large (request body too big)\r\nConnection: close\r\n\r\n");
http_close(c);
return;
}
}
c->body_pos = 0;
c->part = PART_BODY;
if (s[0] == '\r') s++;
s++;
/* move the body part to the beginning of the buffer */
c->line_pos -= s - c->line_buf;
memmove(c->line_buf, s, c->line_pos);
/* GET/HEAD or no content length mean no body */
if (c->method == METHOD_GET || c->method == METHOD_HEAD ||
!(c->attr & CONTENT_LENGTH) || c->content_length == 0) {
if ((c->attr & CONTENT_LENGTH) && c->content_length > 0) {
send_http_response(c, " 400 Bad Request (GET/HEAD with body)\r\n\r\n");
http_close(c);
return;
}
process_request(c);
if (c->attr & CONNECTION_CLOSE) {
http_close(c);
return;
}
/* keep-alive - reset the worker so it can process a new request */
if (c->url) { free(c->url); c->url = NULL; }
if (c->body) { free(c->body); c->body = NULL; }
if (c->content_type) { free(c->content_type); c->content_type = NULL; }
if (c->headers) { free_buffer(c->headers); c->headers = NULL; }
if (c->ws_key) { free(c->ws_key); c->ws_key = NULL; }
if (c->ws_protocol) { free(c->ws_protocol); c->ws_protocol = NULL; }
if (c->ws_version) { free(c->ws_version); c->ws_version = NULL; }
c->body_pos = 0;
c->method = 0;
c->part = PART_REQUEST;
c->attr = 0;
c->content_length = 0;
return;
}
/* copy body content (as far as available) */
c->body_pos = (c->content_length < c->line_pos) ? c->content_length : c->line_pos;
if (c->body_pos) {
memcpy(c->body, c->line_buf, c->body_pos);
c->line_pos -= c->body_pos; /* NOTE: we are NOT moving the buffer since non-zero left-over causes connection close */
}
/* POST will continue into the BODY part */
break;
}
{
char *bol = s;
while (*s && *s != '\r' && *s != '\n') s++;
if (!*s) { /* incomplete line */
if (bol == c->line_buf) {
if (c->line_pos < LINE_BUF_SIZE) /* one, incomplete line, but the buffer is not full yet, just return */
return;
/* the buffer is full yet the line is incomplete - we're in trouble */
send_http_response(c, " 413 Request entity too large\r\nConnection: close\r\n\r\n");
http_close(c);
return;
}
/* move the line to the begining of the buffer for later requests */
c->line_pos -= bol - c->line_buf;
memmove(c->line_buf, bol, c->line_pos);
return;
} else { /* complete line, great! */
if (*s == '\r') *(s++) = 0;
if (*s == '\n') *(s++) = 0;
DBG(printf("complete line: {%s}\n", bol));
if (c->part == PART_REQUEST) {
/* --- process request line --- */
unsigned int rll = strlen(bol); /* request line length */
char *url = strchr(bol, ' ');
if (!url || rll < 14 || strncmp(bol + rll - 9, " HTTP/1.", 8)) { /* each request must have at least 14 characters [GET / HTTP/1.0] and have HTTP/1.x */
send_response(c, "HTTP/1.0 400 Bad Request\r\n\r\n", 28);
http_close(c);
return;
}
url++;
if (!strncmp(bol + rll - 3, "1.0", 3)) c->attr |= HTTP_1_0;
if (!strncmp(bol, "GET ", 4)) c->method = METHOD_GET;
if (!strncmp(bol, "POST ", 5)) c->method = METHOD_POST;
if (!strncmp(bol, "HEAD ", 5)) c->method = METHOD_HEAD;
{
char *mend = url - 1;
/* we generate a header with the method so it can be passed to the handler */
if (!c->headers)
c->headers = alloc_buffer(1024, NULL);
/* make sure it fits */
if (c->headers->size - c->headers->length >= 18 + (mend - bol)) {
if (!c->method) c->method = METHOD_OTHER;
/* add "Request-Method: xxx" */
memcpy(c->headers->data + c->headers->length, "Request-Method: ", 16);
c->headers->length += 16;
memcpy(c->headers->data + c->headers->length, bol, mend - bol);
c->headers->length += mend - bol;
c->headers->data[c->headers->length++] = '\n';
}
}
if (!c->method) {
send_http_response(c, " 501 Invalid or unimplemented method\r\n\r\n");
http_close(c);
return;
}
bol[strlen(bol) - 9] = 0;
c->url = strdup(url);
c->part = PART_HEADER;
DBG(printf("parsed request, method=%d, URL='%s'\n", (int)c->method, c->url));
} else if (c->part == PART_HEADER) {
/* --- process headers --- */
char *k = bol;
if (!c->headers)
c->headers = alloc_buffer(1024, NULL);
if (c->headers) { /* record the header line in the buffer */
int l = strlen(bol);
if (l) { /* this should be really always true */
if (c->headers->length + l + 1 > c->headers->size) { /* not enough space? */
int fits = c->headers->size - c->headers->length;
int needs = 2048;
if (fits) {
memcpy(c->headers->data + c->headers->length, bol, fits);
c->headers->length += fits;
}
while (l + 1 - fits >= needs) needs <<= 1;
if (alloc_buffer(needs, c->headers)) {
c->headers = c->headers->next;
memcpy(c->headers->data, bol + fits, l - fits);
c->headers->length = l - fits;
c->headers->data[c->headers->length++] = '\n';
}
} else {
memcpy(c->headers->data + c->headers->length, bol, l);
c->headers->length += l;
c->headers->data[c->headers->length++] = '\n';
}
}
}
/* lower-case all header names */
while (*k && *k != ':') {
if (*k >= 'A' && *k <= 'Z')
*k |= 0x20;
k++;
}
if (*k == ':') {
*(k++) = 0;
while (*k == ' ' || *k == '\t') k++;
DBG(printf("header '%s' => '%s'\n", bol, k));
if (!strcmp(bol, "upgrade") && !strcmp(k, "websocket"))
c->attr |= WS_UPGRADE;
if (!strcmp(bol, "content-length")) {
c->attr |= CONTENT_LENGTH;
c->content_length = atol(k);
}
if (!strcmp(bol, "content-type")) {
char *l = k;
/* change the content type to lower case,
however, stop at ; since training content
may be case-sensitive such as multipart-boundary
(see #149) */
while (*l && *l != ';') { if (*l >= 'A' && *l <= 'Z') *l |= 0x20; l++; }
c->attr |= CONTENT_TYPE;
if (c->content_type) free(c->content_type);
c->content_type = strdup(k);
if (!strncmp(k, "application/x-www-form-urlencoded", 33))
c->attr |= CONTENT_FORM_UENC;
}
if (!strcmp(bol, "host"))
c->attr |= HOST_HEADER;
if (!strcmp(bol, "connection")) {
char *l = k;
while (*l) { if (*l >= 'A' && *l <= 'Z') *l |= 0x20; l++; }
if (!strncmp(k, "close", 5))
c->attr |= CONNECTION_CLOSE;
}
if (!strcmp(bol, "sec-websocket-key")) {
if (c->ws_key) free(c->ws_key);
c->ws_key = strdup(k);
}
if (!strcmp(bol, "sec-websocket-protocol")) {
if (c->ws_protocol) free(c->ws_protocol);
c->ws_protocol = strdup(k);
}
if (!strcmp(bol, "sec-websocket-version")) {
if (c->ws_version) free(c->ws_version);
c->ws_version = strdup(k);
}
DBG(Rprintf(" [attr = %x]\n", c->attr));
}
}
}
}
}
if (c->part < PART_BODY) {
/* we end here if we processed a buffer of exactly one line */
c->line_pos = 0;
return;
}
}
if (c->part == PART_BODY && c->body) { /* BODY - this branch always returns */
if (c->body_pos < c->content_length) { /* need to receive more ? */
DBG(printf("BODY: body_pos=%d, content_length=%ld\n", c->body_pos, c->content_length));
n = srv->recv(c, c->body + c->body_pos, c->content_length - c->body_pos);
DBG(printf(" [recv n=%d - had %u of %lu]\n", n, c->body_pos, c->content_length));
c->line_pos = 0;
if (n < 0) { /* error, scrap this worker */
http_close(c);
return;
}
if (n == 0) { /* connection closed -> try to process and then remove */
process_request(c);
http_close(c);
return;
}
c->body_pos += n;
}
if (c->body_pos == c->content_length) { /* yay! we got the whole body */
process_request(c);
if (c->attr & CONNECTION_CLOSE || c->line_pos) { /* we have to close the connection if there was a double-hit */
http_close(c);
return;
}
/* keep-alive - reset the worker so it can process a new request */
if (c->url) { free(c->url); c->url = NULL; }
if (c->body) { free(c->body); c->body = NULL; }
if (c->content_type) { free(c->content_type); c->content_type = NULL; }
if (c->headers) { free_buffer(c->headers); c->headers = NULL; }
if (c->ws_key) { free(c->ws_key); c->ws_key = NULL; }
if (c->ws_protocol) { free(c->ws_protocol); c->ws_protocol = NULL; }
if (c->ws_version) { free(c->ws_version); c->ws_version = NULL; }
c->line_pos = 0; c->body_pos = 0;
c->method = 0;
c->part = PART_REQUEST;
c->attr = 0;
c->content_length = 0;
return;
}
}
/* we enter here only if recv was used to leave the headers with no body */
if (c->part == PART_BODY && !c->body) {
char *s = c->line_buf;
if (c->line_pos > 0) {
if ((s[0] != '\r' || s[1] != '\n') && (s[0] != '\n')) {
send_http_response(c, " 411 length is required for non-empty body\r\nConnection: close\r\n\r\n");
http_close(c);
return;
}
/* empty body, good */
process_request(c);
if (c->attr & CONNECTION_CLOSE) {
http_close(c);
return;
} else { /* keep-alive */
int sh = 1;
if (s[0] == '\r') sh++;
if (c->line_pos <= sh)
c->line_pos = 0;
else { /* shift the remaining buffer */
memmove(c->line_buf, c->line_buf + sh, c->line_pos - sh);
c->line_pos -= sh;
}
/* keep-alive - reset the worker so it can process a new request */
if (c->url) { free(c->url); c->url = NULL; }
if (c->body) { free(c->body); c->body = NULL; }
if (c->content_type) { free(c->content_type); c->content_type = NULL; }
if (c->headers) { free_buffer(c->headers); c->headers = NULL; }
if (c->ws_key) { free(c->ws_key); c->ws_key = NULL; }
if (c->ws_protocol) { free(c->ws_protocol); c->ws_protocol = NULL; }
if (c->ws_version) { free(c->ws_version); c->ws_version = NULL; }
c->body_pos = 0;
c->method = 0;
c->part = PART_REQUEST;
c->attr = 0;
c->content_length = 0;
return;
}
}
n = srv->recv(c, c->line_buf + c->line_pos, LINE_BUF_SIZE - c->line_pos - 1);
if (n < 0) { /* error, scrap this worker */
http_close(c);
return;
}
if (n == 0) { /* connection closed -> try to process and then remove */
process_request(c);
http_close(c);
return;
}
if ((s[0] != '\r' || s[1] != '\n') && (s[0] != '\n')) {
send_http_response(c, " 411 length is required for non-empty body\r\nConnection: close\r\n\r\n");
http_close(c);
return;
}
}
}
/* from Rserve.c */
int check_tls_client(int verify, const char *cn);
static void HTTP_connected(void *parg) {
args_t *arg = (args_t*) parg;
if (Rserve_prepare_child(arg) != 0) { /* parent or error */
free(arg);
return;
}
if (!(arg->line_buf = (char*) malloc(LINE_BUF_SIZE))) {
RSEprintf("ERROR: unable to allocate line buffer\n");
free(arg);
return;
}
if ((arg->srv->flags & SRV_TLS) && shared_tls(0)) {
char cn[256];
add_tls(arg, shared_tls(0), 1);
if (check_tls_client(verify_peer_tls(arg, cn, 256), cn)) {
close_tls(arg);
closesocket(arg->s);
free_args(arg);
return;
}
}
while (arg->s != -1)
http_input_iteration(arg);
free_args(arg);
}
server_t *create_HTTP_server(int port, int flags) {
server_t *srv = create_server(port, 0, 0, flags);
#ifdef RSERV_DEBUG
fprintf(stderr, "create_HTTP_server(port = %d, flags=0x%x)\n", port, flags);
#endif
if (srv) {
srv->connected = HTTP_connected;
/* srv->send_resp = */
srv->recv = server_recv;
srv->send = server_send;
srv->fin = server_fin;
add_server(srv);
return srv;
}
return 0;
}
/*--- The following makes the indenting behavior of emacs compatible
with Xcode's 4/4 setting ---*/
/* Local Variables: */
/* indent-tabs-mode: t */
/* tab-width: 4 */
/* c-basic-offset: 4 */
/* End: */
Rserve/src/sha1.c 0000644 0001760 0000144 00000026167 14147646005 013362 0 ustar ripley users /*
* sha1.c
*
* Description:
* This file implements the Secure Hashing Algorithm 1 as
* defined in FIPS PUB 180-1 published April 17, 1995.
*
* The SHA-1, produces a 160-bit message digest for a given
* data stream. It should take about 2**n steps to find a
* message with the same digest as a given message and
* 2**(n/2) to find any two messages with the same digest,
* when n is the digest size in bits. Therefore, this
* algorithm can serve as a means of providing a
* "fingerprint" for a message.
*
* Portability Issues:
* SHA-1 is defined in terms of 32-bit "words". This code
* uses (included via "sha1.h" to define 32 and 8
* bit unsigned integer types. If your C compiler does not
* support 32 bit unsigned integers, this code is not
* appropriate.
*
* Caveats:
* SHA-1 is designed to work with messages less than 2^64 bits
* long. Although SHA-1 allows a message digest to be generated
* for messages of any number of bits less than 2^64, this
* implementation only works with messages with a length that is
* a multiple of the size of an 8-bit character.
*
*/
#include
enum {
shaSuccess = 0,
shaNull, /* Null pointer parameter */
shaInputTooLong, /* input data too long */
shaStateError /* called Input after Result */
};
#define SHA1HashSize 20
/*
* This structure will hold context information for the SHA-1
* hashing operation
*/
typedef struct SHA1Context
{
uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
uint32_t Length_Low; /* Message length in bits */
uint32_t Length_High; /* Message length in bits */
/* Index into message block array */
int_least16_t Message_Block_Index;
uint8_t Message_Block[64]; /* 512-bit message blocks */
int Computed; /* Is the digest computed? */
int Corrupted; /* Is the message digest corrupted? */
} SHA1Context;
/*
* Define the SHA1 circular left shift macro
*/
#define SHA1CircularShift(bits,word) \
(((word) << (bits)) | ((word) >> (32-(bits))))
/* Local Function Prototyptes */
static void SHA1PadMessage(SHA1Context *);
static void SHA1ProcessMessageBlock(SHA1Context *);
/*
* SHA1Reset
*
* Description:
* This function will initialize the SHA1Context in preparation
* for computing a new SHA1 message digest.
*
* Parameters:
* context: [in/out]
* The context to reset.
*
* Returns:
* sha Error Code.
*
*/
static int SHA1Reset(SHA1Context *context)
{
if (!context)
{
return shaNull;
}
context->Length_Low = 0;
context->Length_High = 0;
context->Message_Block_Index = 0;
context->Intermediate_Hash[0] = 0x67452301;
context->Intermediate_Hash[1] = 0xEFCDAB89;
context->Intermediate_Hash[2] = 0x98BADCFE;
context->Intermediate_Hash[3] = 0x10325476;
context->Intermediate_Hash[4] = 0xC3D2E1F0;
context->Computed = 0;
context->Corrupted = 0;
return shaSuccess;
}
/*
* SHA1Result
*
* Description:
* This function will return the 160-bit message digest into the
* Message_Digest array provided by the caller.
* NOTE: The first octet of hash is stored in the 0th element,
* the last octet of hash in the 19th element.
*
* Parameters:
* context: [in/out]
* The context to use to calculate the SHA-1 hash.
* Message_Digest: [out]
* Where the digest is returned.
*
* Returns:
* sha Error Code.
*
*/
static int SHA1Result( SHA1Context *context,
uint8_t Message_Digest[SHA1HashSize])
{
int i;
if (!context || !Message_Digest)
{
return shaNull;
}
if (context->Corrupted)
{
return context->Corrupted;
}
if (!context->Computed)
{
SHA1PadMessage(context);
for(i=0; i<64; ++i)
{
/* message may be sensitive, clear it out */
context->Message_Block[i] = 0;
}
context->Length_Low = 0; /* and clear length */
context->Length_High = 0;
context->Computed = 1;
}
for(i = 0; i < SHA1HashSize; ++i)
{
Message_Digest[i] = context->Intermediate_Hash[i>>2]
>> 8 * ( 3 - ( i & 0x03 ) );
}
return shaSuccess;
}
/*
* SHA1Input
*
* Description:
* This function accepts an array of octets as the next portion
* of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update
* message_array: [in]
* An array of characters representing the next portion of
* the message.
* length: [in]
* The length of the message in message_array
*
* Returns:
* sha Error Code.
*
*/
static int SHA1Input( SHA1Context *context,
const uint8_t *message_array,
unsigned length)
{
if (!length)
{
return shaSuccess;
}
if (!context || !message_array)
{
return shaNull;
}
if (context->Computed)
{
context->Corrupted = shaStateError;
return shaStateError;
}
if (context->Corrupted)
{
return context->Corrupted;
}
while(length-- && !context->Corrupted)
{
context->Message_Block[context->Message_Block_Index++] =
(*message_array & 0xFF);
context->Length_Low += 8;
if (context->Length_Low == 0)
{
context->Length_High++;
if (context->Length_High == 0)
{
/* Message is too long */
context->Corrupted = 1;
}
}
if (context->Message_Block_Index == 64)
{
SHA1ProcessMessageBlock(context);
}
message_array++;
}
return shaSuccess;
}
/*
* SHA1ProcessMessageBlock
*
* Description:
* This function will process the next 512 bits of the message
* stored in the Message_Block array.
*
* Parameters:
* None.
*
* Returns:
* Nothing.
*
* Comments:
* Many of the variable names in this code, especially the
* single character names, were used because those were the
* names used in the publication.
*
*
*/
static void SHA1ProcessMessageBlock(SHA1Context *context)
{
const uint32_t K[] = { /* Constants defined in SHA-1 */
0x5A827999,
0x6ED9EBA1,
0x8F1BBCDC,
0xCA62C1D6
};
int t; /* Loop counter */
uint32_t temp; /* Temporary word value */
uint32_t W[80]; /* Word sequence */
uint32_t A, B, C, D, E; /* Word buffers */
/*
* Initialize the first 16 words in the array W
*/
for(t = 0; t < 16; t++)
{
W[t] = context->Message_Block[t * 4] << 24;
W[t] |= context->Message_Block[t * 4 + 1] << 16;
W[t] |= context->Message_Block[t * 4 + 2] << 8;
W[t] |= context->Message_Block[t * 4 + 3];
}
for(t = 16; t < 80; t++)
{
W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
}
A = context->Intermediate_Hash[0];
B = context->Intermediate_Hash[1];
C = context->Intermediate_Hash[2];
D = context->Intermediate_Hash[3];
E = context->Intermediate_Hash[4];
for(t = 0; t < 20; t++)
{
temp = SHA1CircularShift(5,A) +
((B & C) | ((~B) & D)) + E + W[t] + K[0];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for(t = 20; t < 40; t++)
{
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for(t = 40; t < 60; t++)
{
temp = SHA1CircularShift(5,A) +
((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for(t = 60; t < 80; t++)
{
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
context->Intermediate_Hash[0] += A;
context->Intermediate_Hash[1] += B;
context->Intermediate_Hash[2] += C;
context->Intermediate_Hash[3] += D;
context->Intermediate_Hash[4] += E;
context->Message_Block_Index = 0;
}
/*
* SHA1PadMessage
*
* Description:
* According to the standard, the message must be padded to an even
* 512 bits. The first padding bit must be a '1'. The last 64
* bits represent the length of the original message. All bits in
* between should be 0. This function will pad the message
* according to those rules by filling the Message_Block array
* accordingly. It will also call the ProcessMessageBlock function
* provided appropriately. When it returns, it can be assumed that
* the message digest has been computed.
*
* Parameters:
* context: [in/out]
* The context to pad
* ProcessMessageBlock: [in]
* The appropriate SHA*ProcessMessageBlock function
* Returns:
* Nothing.
*
*/
static void SHA1PadMessage(SHA1Context *context)
{
/*
* Check to see if the current message block is too small to hold
* the initial padding bits and length. If so, we will pad the
* block, process it, and then continue padding into a second
* block.
*/
if (context->Message_Block_Index > 55)
{
context->Message_Block[context->Message_Block_Index++] = 0x80;
while(context->Message_Block_Index < 64)
{
context->Message_Block[context->Message_Block_Index++] = 0;
}
SHA1ProcessMessageBlock(context);
while(context->Message_Block_Index < 56)
{
context->Message_Block[context->Message_Block_Index++] = 0;
}
}
else
{
context->Message_Block[context->Message_Block_Index++] = 0x80;
while(context->Message_Block_Index < 56)
{
context->Message_Block[context->Message_Block_Index++] = 0;
}
}
/*
* Store the message length as the last 8 octets
*/
context->Message_Block[56] = context->Length_High >> 24;
context->Message_Block[57] = context->Length_High >> 16;
context->Message_Block[58] = context->Length_High >> 8;
context->Message_Block[59] = context->Length_High;
context->Message_Block[60] = context->Length_Low >> 24;
context->Message_Block[61] = context->Length_Low >> 16;
context->Message_Block[62] = context->Length_Low >> 8;
context->Message_Block[63] = context->Length_Low;
SHA1ProcessMessageBlock(context);
}
void sha1hash(const char *buf, int len, unsigned char hash[20])
{
SHA1Context sha;
SHA1Reset(&sha);
SHA1Input(&sha, (const unsigned char *) buf, len);
SHA1Result(&sha, hash);
}
Rserve/src/client/ 0000755 0001760 0000144 00000000000 14147646005 013624 5 ustar ripley users Rserve/src/client/README.txt 0000644 0001760 0000144 00000001100 14147646005 015312 0 ustar ripley users This directory contains various Rserve clients:
cxx - minimal C++ client
java - Java client based on the REngine API. This is the actively
developed Java client as it is more flexible and
consistent than the older JRclient. It supports multiple
back-ends such as Rserve or JRI.
php - minimal PHP client and example code that can be used to
run FastRWeb via PHP instead of CGI
NOTE: a more complete PHP client written by
Clement Turbelin based on this minimal version is
available from http://code.google.com/p/rserve-php
Rserve/src/client/cxx/ 0000755 0001760 0000144 00000000000 14147646005 014426 5 ustar ripley users Rserve/src/client/cxx/rcons.cc 0000644 0001760 0000144 00000005425 14147646005 016067 0 ustar ripley users /*
* Simple console that uses C++ interface to Rserve
* Copyright (C) 2004 Simon Urbanek, All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2.1 of the License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Leser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id$
*/
#include
using std::cout;
#define MAIN // we are the main program, we need to define this
#define SOCK_ERRORS // we will use verbose socket errors
#include "Rconnection.h"
#ifdef READLINE
#include
#include
#endif
#ifdef READLINE
char *c=0;
#else
char c[1024];
#endif
int main(int argc, char **argv) {
initsocks(); // this is needed for Win32 - it does noting on unix
Rconnection *rc = new Rconnection();
int i=rc->connect();
if (i) {
char msg[128];
sockerrorchecks(msg, 128, -1);
printf("unable to connect (result=%d, socket:%s).\n", i, msg); return i;
}
printf("connected. Type \"q\" to quit.\n");
do {
#ifdef READLINE
c=readline("Rcli> ");
if (c && *c) add_history(c);
#else
printf("Rcli> ");
c[1023]=0;
fgets(c,1023,stdin);
char *rq=c; while(*rq && rq-c<1023) { if (*rq=='\n') *rq=0; rq++; }
#endif
if (!strcmp(c,"q") || !strcmp(c,"quit") || !strcmp(c,"exit")) {
cout << "ok, you got enough, right? leaving.\n";
break;
}
int res=0;
if (!strcmp(c,"shutdown")) { // this is a demo of low-level commands being send via "request"
Rmessage *msg=new Rmessage();
cout << "performing shutdown.\n";
res=rc->request(msg,CMD_shutdown);
delete(msg);
} else if (*c) { // this is a regular "eval" demo
Rexp *xp=rc->eval(c, &res);
if (xp) {
cout << "type=" << xp->type << ", len=" << xp->len << ", result:" << *xp << "\n";
if (xp->attr) cout << "attributes: " << *xp->attr << "\n";
delete(xp);
} else cout << "eval failed with result " << res << "\n";
}
if (res) {
cout << "request failed with error code " << res << "\n";
break;
}
} while (1);
delete(rc);
return 0;
}
Rserve/src/client/cxx/Rconnection.cc 0000644 0001760 0000144 00000062737 14147646005 017235 0 ustar ripley users /*
* C++ Interface to Rserve
* Copyright (C) 2004-8 Simon Urbanek, All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2.1 of the License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Leser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Although this code is licensed under LGPL v2.1, we strongly encourage
* everyone modifying this software to contribute back any improvements and
* bugfixes to the project for the benefit all other users. Thank you.
*
* $Id$
*/
/* external defines:
SWAPEND - needs to be defined for platforms with inverse endianess related to Intel
see also SOCK_ERROR, MAIN and other defines in sisocks.h
*/
/* locally generated status error and return codes:
-1 - operation failed (e.g. connect failed)
-2 - handhake failed
-3 - invalid ID string
-4 - protocol not supported
-5 - not connected
-6 - - unused -
-7 - remote connection close
-8 - malformed packet
-9 - send error
-10 - out of memory
-11 - operation is unsupported (e.g. unix login while crypt is not linked)
-12 - eval didn't return a SEXP (possibly the server is too old/buggy or crashed)
-13 - message requires 64-bit sizes but this binary is linked as 32-bit
*/
#include "Rconnection.h"
#include
#include "sisocks.h"
#ifdef unix
#include
#include
#else
#define AF_LOCAL -1
#endif
#if defined HAVE_NETINET_TCP_H && defined HAVE_NETINET_IN_H
#define CAN_TCP_NODELAY
#include
#include
#endif
#ifdef Win32
#define CAN_TCP_NODELAY
#endif
#include "Rsrv.h"
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#endif
// NOTE: 0103 compatibility has not been established! use at your own risk!
static const char *myID = "Rsrv0103QAP1"; /* this client supports up to protocol version 0103 */
#define IS_LIST_TYPE_(TYPE) ((TYPE) == XT_LIST || (TYPE) == XT_LIST_NOTAG || (TYPE) == XT_LIST_TAG)
#define IS_SYMBOL_TYPE_(TYPE) ((TYPE) == XT_SYM || (TYPE) == XT_SYMNAME)
static Rexp *new_parsed_Rexp(unsigned int *d, Rmessage *msg) {
int type=ptoi(*d)&0x3f;
#ifdef DEBUG_CXX
printf("new_parsed_Rexp(%p, %p) type=%d\n", d, msg, type);
#endif
if (type==XT_ARRAY_INT || type==XT_INT)
return new Rinteger(d,msg);
if (type==XT_ARRAY_DOUBLE || type==XT_DOUBLE)
return new Rdouble(d,msg);
if (IS_LIST_TYPE_(type))
return new Rlist(d,msg);
if (type==XT_VECTOR)
return new Rvector(d,msg);
if (type==XT_STR)
return new Rstring(d,msg);
if (type==XT_SYM || type==XT_SYMNAME)
return new Rsymbol(d,msg);
if (type==XT_ARRAY_STR)
return new Rstrings(d,msg);
return new Rexp(d,msg);
}
static Rexp *new_parsed_Rexp_from_Msg(Rmessage *msg) {
int hl=1;
unsigned int *hp=msg->par[0];
Rsize_t plen=hp[0]>>8;
if ((hp[0]&DT_LARGE)>0) {
hl++;
plen|=((Rsize_t)hp[1])<<24;
}
return new_parsed_Rexp(hp+hl,msg);
}
Rmessage::Rmessage() {
complete=0;
data=0;
len=0;
}
Rmessage::Rmessage(int cmd) {
memset(&head,0,sizeof(head));
head.cmd = cmd;
data=0;
len=0;
complete=1;
}
Rmessage::Rmessage(int cmd, const char *txt) {
memset(&head,0,sizeof(head));
int tl=strlen(txt)+1;
if ((tl&3)>0)
tl=(tl+4)&0xffffc; // allign the text
len=tl+4; // message length is tl + 4 (short format only)
head.cmd=cmd;
head.len=len;
data=(char*)malloc(tl+16);
memset(data,0,tl+16);
*((int*)data)=itop(SET_PAR(DT_STRING,tl));
strcpy(data+4,txt);
complete=1;
}
Rmessage::Rmessage(int cmd, const void *buf, int dlen, int raw_data) {
memset(&head,0,sizeof(head));
len=(raw_data)?dlen:(dlen+4);
head.cmd=cmd;
head.len=len;
data=(char*)malloc(len);
memcpy(data, (raw_data)?buf:((char*)buf+4), dlen);
if (!raw_data)
*((int*)data)=itop(SET_PAR(DT_BYTESTREAM,dlen));
complete=1;
}
Rmessage::Rmessage(int cmd, int i) {
memset(&head,0,sizeof(head));
len=8; // DT_INT+len (4) + payload-1xINT (4)
head.cmd=cmd;
head.len=len;
data=(char*)malloc(8);
*((int*)data)=itop(SET_PAR(DT_INT,4));
((int*)data)[1]=itop(i);
complete=1;
}
Rmessage::~Rmessage() {
if(data) free(data);
complete=0;
}
int Rmessage::read(int s) {
complete=0;
int n=recv(s,(char*)&head,sizeof(head),0);
if (n!=sizeof(head)) {
closesocket(s); s=-1;
return (n==0)?-7:-8;
}
Rsize_t i = len = (unsigned int) (head.len = ptoi(head.len));
head.cmd = ptoi(head.cmd);
head.msg_id = ptoi(head.msg_id);
head.res = ptoi(head.res);
#ifdef __LP64__
if (head.res) { /* process high bits of the length */
unsigned int len_lo = (unsigned int) head.len, len_hi = (unsigned int) head.res;
len = (Rsize_t) (((unsigned long) len_lo) | (((unsigned long) len_hi) << 32));
i = len;
}
#else
if (head.res)
return -13; // 64-bit packet, but only 32-bit long is supported
#endif
if (i>0) {
data=(char*) malloc(i);
if (!data) {
closesocket(s); s=-1;
return -10; // out of memory
}
char *dp=data;
while(i>0 && (n=recv(s,(char*)dp,i,0))>0) {
dp+=n;
i-=n;
}
if (i>0) {
closesocket(s); s=-1;
return -8;
}
}
parse();
complete=1;
return 0;
}
void Rmessage::parse() {
pars=0;
if (len<4) return;
char *c=data, *eop=c+len;
while (c>8;
if ((p1&DT_LARGE)>0) {
hs+=4;
unsigned int p2=ptoi(pp[1]);
len|=((Rsize_t)p2)<<24;
}
#ifdef DEBUG_CXX
printf(" par %d: %d length %ld\n", pars, p1&0x3f, (long) len);
#endif
par[pars++]=(unsigned int*)c;
c+=hs;
c+=len;
if (pars>15) break; // max 16 pars
}
}
int Rmessage::send(int s) {
int failed=0;
head.cmd=itop(head.cmd);
head.len=itop(head.len);
head.msg_id=itop(head.msg_id);
head.res=itop(head.res);
if (::send(s,(char*)&head,sizeof(head),0)!=sizeof(head))
failed=-1;
if (!failed && len>0 && (Rsize_t)::send(s,data,len,0)!=len)
failed=-1;
head.cmd=ptoi(head.cmd);
head.len=ptoi(head.len);
head.msg_id=ptoi(head.msg_id);
head.res=ptoi(head.res);
return failed;
}
Rexp::Rexp(Rmessage *msg) {
#ifdef DEBUG_CXX
printf("new Rexp@%x\n", this);
#endif
master=0; rcount=0; attr=0; attribs=0;
this->msg=msg;
int hl=1;
unsigned int *hp=msg->par[0];
Rsize_t plen=hp[0]>>8;
if ((hp[0]&DT_LARGE)>0) {
hl++;
plen|=((Rsize_t)hp[1])<<24;
}
next=parse(hp+hl);
}
Rexp::Rexp(unsigned int *pos, Rmessage *msg) {
#ifdef DEBUG_CXX
printf("new Rexp@%x\n", this);
#endif
attr=0; master=0; this->msg=msg; rcount=0; attribs=0;
next=parse(pos);
}
Rexp::Rexp(int type, const char *data, Rsize_t len, Rexp *attr) {
this->attr=attr; master=this; rcount=0; attribs=0;
this->type=type;
this->msg=0;
if (len>0) {
#ifdef DEBUG_CXX
fprintf(stderr, "Rexp::Rexp %p: allocating %lu bytes\n", this, (unsigned long) len);
#endif
this->data=(char*) malloc(len);
memcpy(this->data, data, len);
this->len=len;
} else
this->len=0;
next=(char*)data+this->len;
}
Rexp::~Rexp() {
#ifdef DEBUG_CXX
printf("releasing Rexp@%p\n", this);
#endif
if (attr)
delete(attr);
attr=0;
if (master) {
if (master==this) {
free(data); len=0;
} else
master->rcount--;
master=0;
}
if (msg) {
if (rcount>0)
fprintf(stderr, "WARNING! Rexp master %lx delete requested, but %d object(s) are using our memory - refusing to free, leaking...\n", (long)this, rcount);
else
delete(msg);
}
msg=0;
}
void Rexp::set_master(Rexp *m) {
if (master) master->rcount--;
master=m;
if (m) m->rcount++;
}
char *Rexp::parse(unsigned int *pos) { // plen is not used
this->pos=pos;
int hl=1;
unsigned int p1=ptoi(pos[0]);
len=p1>>8;
if ((p1&XT_LARGE)>0) {
hl++;
len|=((Rsize_t)(ptoi(pos[1])))<<24;
}
data=(char*)(pos+hl);
if (p1&XT_HAS_ATTR) {
attr=new_parsed_Rexp((unsigned int*)data, 0);
len-=attr->next-data;
data=attr->next;
if (master || msg)
attr->set_master(master?master:this);
}
type=p1&0x3f;
#ifdef DEBUG_CXX
printf("Rexp(type=%d, len=%d, attr=%p)\n", type, len, attr);
#endif
return data+len;
}
void Rexp::store(char *buf) {
int hl=4;
unsigned int *i = (unsigned int*)buf;
i[0]=SET_PAR(type, len);
i[0]=itop(i[0]);
if (len>0x7fffff) {
buf[0]|=XT_LARGE;
i[1]=itop(len>>24);
hl+=4;
}
memcpy(buf+hl, data, len);
}
Rexp *Rexp::attribute(const char *name) {
return (attr && IS_LIST_TYPE_(attr->type)) ? ((Rlist*)attr)->entryByTagName(name) : 0;
}
const char **Rexp::attributeNames() {
if (!attr || !IS_LIST_TYPE_(attr->type))
return 0;
if (attribs == 0) {
// let us cache attribute names
Rlist *l = (Rlist*) attr;
while (l && (IS_LIST_TYPE_(l->type))) {
if (l->tag && IS_SYMBOL_TYPE_(l->tag->type)) attribs++;
l = l->tail;
}
attrnames = (const char**) malloc(sizeof(char*)*(attribs+1));
l = (Rlist*) attr;
while (l && IS_LIST_TYPE_(l->type)) {
if (l->tag && IS_SYMBOL_TYPE_(l->tag->type))
attrnames[attribs++] = ((Rsymbol*)l->tag)->symbolName();
l = l->tail;
}
attrnames[attribs] = 0;
}
return attrnames;
}
void Rinteger::fix_content() {
if (len<0 || !data) return;
#ifdef SWAPEND
int *i = (int*) data;
int *j = (int*) (data+len);
while (inext;
if (ptrnext;
if (ptrtype!=XT_LIST) {
// if tail is not a list, then something is wrong - just delete it
delete(tail); tail=0;
}
}
}
}
} else if (type == XT_LIST_NOTAG) { /* new style list w/o tags */
Rlist *lt = this;
int n = 0;
while (ptr < eod) {
Rexp *h = new_parsed_Rexp((unsigned int*) ptr, 0);
if (!h) break;
if (n)
lt = lt->tail = new Rlist(type, h, 0, h->next, msg);
else
lt->head = h;
n++;
ptr = h->next;
}
} else if (type == XT_LIST_TAG) { /* new style list with tags */
Rlist *lt = this;
int n = 0;
while (ptr < eod) {
Rexp *h = new_parsed_Rexp((unsigned int*) ptr, 0);
#ifdef DEBUG_CXX
printf(" LIST_TAG: n=%d, ptr=%p, h=%p\n", n, ptr, h);
#endif
if (!h) break;
ptr = h->next;
Rexp *t = new_parsed_Rexp((unsigned int*) ptr, 0);
#ifdef DEBUG_CXX
printf(" tag=%p (ptr=%p)\n", t, ptr);
#endif
if (!t) break;
if (n)
lt = lt->tail = new Rlist(type, h, t, t->next, msg);
else {
lt->head = h;
lt->tag = t;
}
ptr = t->next;
n++;
}
next = ptr;
}
#ifdef DEBUG_CXX
printf(" end of list %p, ptr=%p\n", this, ptr);
#endif
}
Rvector::~Rvector() {
int i=0;
while(itype==XT_STR) sc++;
i++;
}
if (sc==0) return 0;
strs=(char**)malloc(sizeof(char*)*(sc+1));
i=0; sc=0;
while (itype==XT_STR) strs[sc++]=((Rstring*)cont[i])->string();
i++;
}
strs[sc]=0;
return strs;
}
int Rvector::indexOf(Rexp *exp) {
int i=0;
while (itype==XT_STR && !strcmp(((Rstring*)cont[i])->string(),str)) return i;
i++;
}
return -1;
}
int Rstrings::indexOfString(const char *str) {
unsigned int i = 0;
while (i < nel) {
if (cont[i] && !strcmp(cont[i], str)) return i;
i++;
}
return -1;
}
Rexp* Rvector::byName(const char *name) {
/* here we are not using IS_LIST_TYPE_() because XT_LIST_NOTAG is guaranteed to not match */
if (count < 1 || !attr || (attr->type!=XT_LIST && attr->type != XT_LIST_TAG)) return 0;
Rexp *e = ((Rlist*) attr)->head;
if (((Rlist*) attr)->tag)
e = ((Rlist*) attr)->entryByTagName("names");
if (!e || (e->type!=XT_VECTOR && e->type!=XT_ARRAY_STR && e->type!=XT_STR))
return 0;
if (e->type == XT_VECTOR) {
int pos = ((Rvector*)e)->indexOfString(name);
if (pos>-1 && postype == XT_ARRAY_STR) {
int pos = ((Rstrings*)e)->indexOfString(name);
if (pos>-1 && posstring(),name))
return cont[0];
}
return 0;
}
void Rvector::fix_content() {
char *ptr = data;
char *eod = data+len;
capacity=16;
cont=(Rexp**) malloc(sizeof(Rexp*)*capacity);
while (ptrnext;
else break;
count++;
}
}
Rconnection::Rconnection(const char *host, int port) {
if (!host) host = "127.0.0.1";
this->host = strdup(host);
this->port = port;
family = (port==-1) ? AF_LOCAL : AF_INET;
s = -1;
auth = 0;
salt[0] = '.'; salt[1] = '.';
session_key = 0;
}
Rconnection::Rconnection(Rsession *session) {
const char *sHost = session->host();
if (!sHost) sHost="127.0.0.1";
this->host = strdup(sHost);
this->port = session->port();
family = AF_INET;
s = -1;
auth = 0;
salt[0]='.'; salt[1]='.';
session_key = (char*) malloc(32);
memcpy(session_key, session->key(), 32);
}
Rconnection::~Rconnection() {
if (host) free(host);
host = 0;
if (s != -1) closesocket(s);
s = -1;
}
int Rconnection::connect() {
#ifdef unix
struct sockaddr_un sau;
#endif
SAIN sai;
char IDstring[33];
if (family==AF_INET) {
memset(&sai,0,sizeof(sai));
build_sin(&sai,host,port);
} else {
#ifdef unix
memset(&sau,0,sizeof(sau));
sau.sun_family=AF_LOCAL;
strcpy(sau.sun_path,host); // FIXME: possible overflow!
#else
return -11; // unsupported
#endif
}
IDstring[32]=0;
int i;
s=socket(family,SOCK_STREAM,0);
if (family==AF_INET) {
#ifdef CAN_TCP_NODELAY
int opt=1;
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (const char*) &opt, sizeof(opt));
#endif
i=::connect(s,(SA*)&sai,sizeof(sai));
}
#ifdef unix
else
i=::connect(s,(SA*)&sau,sizeof(sau));
#endif
if (i==-1) {
closesocket(s); s=-1;
return -1; // connect failed
}
if (session_key) { // resume a session
int n = send(s, session_key, 32, 0);
if (n != 32) {
closesocket(s); s = -1;
return -2; // handshake failed (session key send error)
}
Rmessage *msg = new Rmessage();
int q = msg->read(s);
delete msg;
return q;
}
int n=recv(s,IDstring,32,0);
if (n!=32) {
closesocket(s); s=-1;
return -2; // handshake failed (no IDstring)
}
if (strncmp(IDstring,myID,4)) {
closesocket(s); s=-1;
return -3; // invalid IDstring
}
if (strncmp(IDstring+8,myID+8,4) || strncmp(IDstring+4,myID+4,4)>0) {
closesocket(s); s=-1;
return -4; // protocol not supported
}
{
int i=12;
while (i<32) {
if (!strncmp(IDstring+i, "ARuc", 4)) auth|=A_required|A_crypt;
if (!strncmp(IDstring+i, "ARpt", 4)) auth|=A_required|A_plain;
if (IDstring[i]=='K') {
salt[0]=IDstring[i+1];
salt[1]=IDstring[i+2];
}
i+=4;
}
}
return 0;
}
int Rconnection::disconnect() {
if (s>-1) {
closesocket(s);
s=-1;
}
return 0;
}
/**--- low-level functions --*/
int Rconnection::request(Rmessage *msg, int cmd, int len, void *par) {
struct phdr ph;
if (s==-1) return -5; // not connected
memset(&ph,0,sizeof(ph));
ph.len=itop(len);
ph.cmd=itop(cmd);
if (send(s,(char*)&ph,sizeof(ph),0)!=sizeof(ph)) {
closesocket(s); s=-1;
return -9;
}
if (len>0 && send(s,(char*)par,len,0)!=len) {
closesocket(s); s=-1;
return -9;
}
return msg->read(s);
}
int Rconnection::request(Rmessage *targetMsg, Rmessage *contents) {
if (s==-1) return -5; // not connected
if (contents->send(s)) {
closesocket(s); s=-1;
return -9; // send error
}
return targetMsg->read(s);
}
/** --- high-level functions -- */
int Rconnection::shutdown(const char *key) {
Rmessage *msg = new Rmessage();
Rmessage *cm = key?new Rmessage(CMD_shutdown, key):new Rmessage(CMD_shutdown);
int res = request(msg, cm);
delete cm;
delete msg;
return res;
}
int Rconnection::assign(const char *symbol, Rexp *exp) {
Rmessage *msg=new Rmessage();
Rmessage *cm=new Rmessage(CMD_setSEXP);
int tl=strlen(symbol)+1;
if (tl&3) tl=(tl+4)&0xfffc;
Rsize_t xl=exp->storageSize();
Rsize_t hl=4+tl+4;
if (xl>0x7fffff) hl+=4;
cm->data=(char*) malloc(hl+xl);
cm->head.len=cm->len=hl+xl;
((unsigned int*)cm->data)[0]=SET_PAR(DT_STRING, tl);
((unsigned int*)cm->data)[0]=itop(((unsigned int*)cm->data)[0]);
strcpy(cm->data+4, symbol);
((unsigned int*)(cm->data+4+tl))[0]=SET_PAR((Rsize_t) ((xl>0x7fffff)?(DT_SEXP|DT_LARGE):DT_SEXP), (Rsize_t) xl);
((unsigned int*)(cm->data+4+tl))[0]=itop(((unsigned int*)(cm->data+4+tl))[0]);
if (xl>0x7fffff)
((unsigned int*)(cm->data+4+tl))[1]=itop(xl>>24);
exp->store(cm->data+hl);
int res=request(msg,cm);
delete (cm);
if (res) {
delete(msg);
return res;
}
if (!res) res = CMD_STAT(msg->command());
delete(msg);
return res;
}
int Rconnection::voidEval(const char *cmd) {
int status=0;
eval(cmd, &status, 1);
return status;
}
Rexp *Rconnection::eval(const char *cmd, int *status, int opt) { /* opt = 1 -> void eval */
Rmessage *msg=new Rmessage();
Rmessage *cmdMessage=new Rmessage((opt&1)?CMD_voidEval:CMD_eval, cmd);
int res=request(msg,cmdMessage);
delete (cmdMessage);
if (opt&1 && !res) {
if (status) *status=0; // we should put response code here
delete(msg);
return 0;
}
if ((opt & 1) == 0 && !res && (msg->pars!=1 || (ptoi(msg->par[0][0])&0x3f)!=DT_SEXP)) {
delete(msg);
if (status) *status=-12; // returned object is not SEXP
return 0;
}
if (res) {
delete(msg);
if (status) *status=res;
return 0;
}
if (status) *status=0;
return new_parsed_Rexp_from_Msg(msg);
}
/** detached eval (aka detached void eval) initiates eval and detaches the session.
* @param cmd command to evaluate. If NULL equivalent to simple detach()
* @param status optional status to be reported (zero on success)
* @return object describintg he session.
* Note that the caller is responsible for freeing the object if not needed. */
Rsession *Rconnection::detachedEval(const char *cmd, int *status) {
Rmessage *msg = new Rmessage();
Rmessage *cmdMessage = cmd ? new Rmessage(CMD_detachedVoidEval, cmd) : new Rmessage(CMD_detachSession);
int res = request(msg, cmdMessage);
delete cmdMessage;
if (res) {
if (status) *status = res;
delete msg;
return 0;
}
if (msg->pars != 2 ||
PAR_TYPE(ptoi(msg->par[0][0])) != DT_INT || PAR_LEN(ptoi(msg->par[0][0])) != sizeof(int) ||
PAR_TYPE(ptoi(msg->par[1][0])) != DT_BYTESTREAM || PAR_LEN(ptoi(msg->par[1][0])) != 32) { // invalid contents
if (status) *status = -12;
delete msg;
return 0;
}
Rsession *session = new Rsession(host, ptoi(msg->par[0][1]), (const char*) (msg->par[1] + 1));
delete msg;
if (status) *status=0;
return session;
}
Rsession *Rconnection::detach(int *status) {
return detachedEval(0, status);
}
int Rconnection::openFile(const char *fn) {
Rmessage *msg=new Rmessage();
Rmessage *cmdMessage=new Rmessage(CMD_openFile, fn);
int res=request(msg,cmdMessage);
delete (cmdMessage);
if (!res) res=CMD_STAT(msg->command());
delete (msg);
return res;
}
int Rconnection::createFile(const char *fn) {
Rmessage *msg=new Rmessage();
Rmessage *cmdMessage=new Rmessage(CMD_createFile, fn);
int res=request(msg,cmdMessage);
delete (cmdMessage);
if (!res) res=CMD_STAT(msg->command());
delete (msg);
return res;
}
int Rconnection::readFile(char *buf, unsigned int len) {
Rmessage *msg=new Rmessage();
Rmessage *cmdMessage=new Rmessage(CMD_readFile, len);
int res=request(msg,cmdMessage);
delete(cmdMessage);
if (!res) {
// FIXME: Rserve up to 0.4-0 actually sends buggy response - it ommits DT_BYTESTREAM header!
if (msg->len > len) {
// we're in trouble here - techincally we should not get this
delete(msg);
return CERR_malformed_packet;
}
if (msg->len > 0) memcpy(buf, msg->data, msg->len);
int rl = msg->len;
delete(msg);
return rl;
}
delete(msg);
return CERR_io_error;
}
int Rconnection::writeFile(const char *buf, unsigned int len) {
Rmessage *msg=new Rmessage();
Rmessage *cmdMessage=new Rmessage(CMD_writeFile, buf, len);
int res=request(msg,cmdMessage);
delete(cmdMessage);
if (!res && msg->command()==RESP_OK) {
delete(msg);
return 0;
}
delete(msg);
// FIXME: this is not really true ...
return (res==0)?CERR_io_error:res;
}
int Rconnection::closeFile() {
Rmessage *msg=new Rmessage();
Rmessage *cmdMessage=new Rmessage(CMD_closeFile);
int res=request(msg,cmdMessage);
delete(cmdMessage);
if (!res && msg->command()==RESP_OK) {
delete(msg);
return 0;
}
delete(msg);
// FIXME: this is not really true ...
return (res==0)?CERR_io_error:res;
}
int Rconnection::removeFile(const char *fn) {
Rmessage *msg=new Rmessage();
Rmessage *cmdMessage=new Rmessage(CMD_removeFile, fn);
int res=request(msg,cmdMessage);
delete (cmdMessage);
if (!res) res=CMD_STAT(msg->command());
delete (msg);
return res;
}
int Rconnection::login(const char *user, const char *pwd) {
char *authbuf, *c;
if (!(auth&A_required)) return 0;
authbuf=(char*) malloc(strlen(user)+strlen(pwd)+22);
strcpy(authbuf, user); c=authbuf+strlen(user);
*c='\n'; c++;
strcpy(c,pwd);
#ifdef unix
if (auth&A_crypt)
strcpy(c,crypt(pwd,salt));
#else
if (!(auth&A_plain)) {
free(authbuf);
return CERR_auth_unsupported;
}
#endif
Rmessage *msg=new Rmessage();
Rmessage *cmdMessage=new Rmessage(CMD_login, authbuf);
int res=request(msg,cmdMessage);
delete (cmdMessage);
if (!res) res=CMD_STAT(msg->command());
delete (msg);
free(authbuf);
return res;
}
#ifdef CMD_ctrl
/* server control methods */
int serverEval(const char *cmd);
int serverSource(const char *fn);
int serverShutdown();
int Rconnection::serverEval(const char *cmd) {
Rmessage *msg = new Rmessage(); /* result message */
Rmessage *cmdMessage = new Rmessage(CMD_ctrlEval, cmd); /* request message */
int res = request(msg, cmdMessage);
delete (cmdMessage);
if (!res) res = CMD_STAT(msg->command());
delete (msg);
return res;
}
int Rconnection::serverSource(const char *fn) {
Rmessage *msg = new Rmessage(); /* result message */
Rmessage *cmdMessage = new Rmessage(CMD_ctrlSource, fn); /* request message */
int res = request(msg, cmdMessage);
delete (cmdMessage);
if (!res) res = CMD_STAT(msg->command());
delete (msg);
return res;
}
int Rconnection::serverShutdown() {
Rmessage *msg = new Rmessage(); /* result message */
Rmessage *cmdMessage = new Rmessage(CMD_ctrlShutdown); /* request message */
int res = request(msg, cmdMessage);
delete (cmdMessage);
if (!res) res = CMD_STAT(msg->command());
delete (msg);
return res;
}
#endif
Rserve/src/client/cxx/Rsrv.h 0000644 0001760 0000144 00000046250 14147646005 015542 0 ustar ripley users /*
* Rsrv.h : constants and macros for Rserve client/server architecture
* Copyright (C) 2002-21 Simon Urbanek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 of the License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Note: This header file is licensed under LGPL to allow other
* programs to use it under LGPL. Rserve itself is licensed under GPL.
*
* $Id$
*/
/* external defines:
MAIN - should be defined in just one file that will contain the fn definitions and variables
*/
#ifndef __RSRV_H__
#define __RSRV_H__
#ifndef NO_CONFIG_H
#include "config.h"
#endif
#define RSRV_VER 0x01080a /* Rserve v1.8-10 */
#define default_Rsrv_port 6311
/* Rserve communication is done over any reliable connection-oriented
protocol (usually TCP/IP or local sockets). After the connection is
established, the server sends 32 bytes of ID-string defining the
capabilities of the server. Each attribute of the ID-string is 4 bytes
long and is meant to be user-readable (i.e. don't use special characters),
and it's a good idea to make "\r\n\r\n" the last attribute
the ID string must be of the form:
[0] "Rsrv" - R-server ID signature
[4] "0100" - version of the R server
[8] "QAP1" - protocol used for communication (here Quad Attributes Packets v1)
[12] any additional attributes follow. \r\n and '-' are ignored.
optional attributes
(in any order; it is legitimate to put dummy attributes, like "----" or
" " between attributes):
"R151" - version of R (here 1.5.1)
"ARpt" - authorization required (here "pt"=plain text, "uc"=unix crypt,
"m5"=MD5)
connection will be closed if the first packet is not CMD_login.
if more AR.. methods are specified, then client is free to
use the one he supports (usually the most secure)
"K***" - key if encoded authentification is challenged (*** is the key)
for unix crypt the first two letters of the key are the salt
required by the server */
/* QAP1 transport protocol header structure
all int and double entries throughout the transfer are in
Intel-endianess format: int=0x12345678 -> char[4]=(0x78,0x56,x34,0x12)
functions/macros for converting from native to protocol format
are available below
Please note also that all values muse be quad-aligned, i.e. the length
must be divisible by 4. This is automatically assured for int/double etc.,
but care must be taken when using strings and byte streams.
*/
struct phdr { /* always 16 bytes */
int cmd; /* command */
int len; /* length of the packet minus header (ergo -16) */
int msg_id; /* message id (since 1.8) [WAS:data offset behind header (ergo usually 0)] */
int res; /* high 32-bit of the packet length (since 0103
and supported on 64-bit platforms only)
aka "lenhi", but the name was not changed to
maintain compatibility */
};
/* each entry in the data section (aka parameter list) is preceded by 4 bytes:
1 byte : parameter type
3 bytes: length
parameter list may be terminated by 0/0/0/0 but doesn't have to since "len"
field specifies the packet length sufficiently (hint: best method for parsing is
to allocate len+4 bytes, set the last 4 bytes to 0 and trverse list of parameters
until (int)0 occurs
since 0102:
if the 7-th bit (0x40) in parameter type is set then the length is encoded
in 7 bytes enlarging the header by 4 bytes.
*/
/* macros for handling the first int - split/combine (24-bit version only!) */
#define PAR_TYPE(X) ((X) & 255)
#define PAR_LEN(X) (((unsigned int)(X)) >> 8)
#define PAR_LENGTH PAR_LEN
#define SET_PAR(TY,LEN) ((((unsigned int) (LEN) & 0xffffff) << 8) | ((TY) & 255))
#define CMD_STAT(X) (((X) >> 24)&127) /* returns the stat code of the response */
#define SET_STAT(X,s) ((X) | (((s) & 127) << 24)) /* sets the stat code */
#define CMD_RESP 0x10000 /* all responses have this flag set */
#define RESP_OK (CMD_RESP|0x0001) /* command succeeded; returned parameters depend
on the command issued */
#define RESP_ERR (CMD_RESP|0x0002) /* command failed, check stats code
attached string may describe the error */
#define CMD_OOB 0x20000 /* out-of-band data - i.e. unsolicited messages */
#define OOB_SEND (CMD_OOB | 0x1000) /* OOB send - unsolicited SEXP sent from the R instance to the client. 12 LSB are reserved for application-specific code */
#define OOB_MSG (CMD_OOB | 0x2000) /* OOB message - unsolicited message sent from the R instance to the client requiring a response. 12 LSB are reserved for application-specific code */
#define IS_OOB_SEND(X) (((X) & 0x0ffff000) == OOB_SEND)
#define IS_OOB_MSG(X) (((X) & 0x0ffff000) == OOB_MSG)
#define OOB_USR_CODE(X) ((X) & 0xfff)
/* flag for create_server: Use QAP object-cap mode */
#define SRV_QAP_OC 0x40
/* mask of all flags that are relevant to QAP (so they can be passed through) */
#define SRV_QAP_FLAGS (SRV_QAP_OC)
/* stat codes; 0-0x3f are reserved for program specific codes - e.g. for R
connection they correspond to the stat of Parse command.
the following codes are returned by the Rserv itself
codes <0 denote Rerror as provided by R_tryEval
*/
#define ERR_auth_failed 0x41 /* auth.failed or auth.requested but no
login came. in case of authentification
failure due to name/pwd mismatch,
server may send CMD_accessDenied instead
*/
#define ERR_conn_broken 0x42 /* connection closed or broken packet killed it */
#define ERR_inv_cmd 0x43 /* unsupported/invalid command */
#define ERR_inv_par 0x44 /* some parameters are invalid */
#define ERR_Rerror 0x45 /* R-error occured, usually followed by
connection shutdown */
#define ERR_IOerror 0x46 /* I/O error */
#define ERR_notOpen 0x47 /* attempt to perform fileRead/Write
on closed file */
#define ERR_accessDenied 0x48 /* this answer is also valid on
CMD_login; otherwise it's sent
if the server deosn;t allow the user
to issue the specified command.
(e.g. some server admins may block
file I/O operations for some users) */
#define ERR_unsupportedCmd 0x49 /* unsupported command */
#define ERR_unknownCmd 0x4a /* unknown command - the difference
between unsupported and unknown is that
unsupported commands are known to the
server but for some reasons (e.g.
platform dependent) it's not supported.
unknown commands are simply not recognized
by the server at all. */
/* The following ERR_.. exist since 1.23/0.1-6 */
#define ERR_data_overflow 0x4b /* incoming packet is too big.
currently there is a limit as of the
size of an incoming packet. */
#define ERR_object_too_big 0x4c /* the requested object is too big
to be transported in that way.
If received after CMD_eval then
the evaluation itself was successful.
optional parameter is the size of the object
*/
/* since 1.29/0.1-9 */
#define ERR_out_of_mem 0x4d /* out of memory. the connection is usually
closed after this error was sent */
/* since 0.6-0 */
#define ERR_ctrl_closed 0x4e /* control pipe to the master process is closed or broken */
/* since 0.4-0 */
#define ERR_session_busy 0x50 /* session is still busy */
#define ERR_detach_failed 0x51 /* unable to detach seesion (cannot determine
peer IP or problems creating a listening
socket for resume) */
/* since 1.7 */
#define ERR_disabled 0x61 /* feature is disabled */
#define ERR_unavailable 0x62 /* feature is not present in this build */
#define ERR_cryptError 0x63 /* crypto-system error */
#define ERR_securityClose 0x64 /* server-initiated close due to security
violation (too many attempts, excessive
timeout etc.) */
/* availiable commands */
#define CMD_login 0x001 /* "name\npwd" : - */
#define CMD_voidEval 0x002 /* string : - */
#define CMD_eval 0x003 /* string | encoded SEXP : encoded SEXP */
#define CMD_shutdown 0x004 /* [admin-pwd] : - */
/* security/encryption - all since 1.7-0 */
#define CMD_switch 0x005 /* string (protocol) : - */
#define CMD_keyReq 0x006 /* string (request) : bytestream (key) */
#define CMD_secLogin 0x007 /* bytestream (encrypted auth) : - */
#define CMD_OCcall 0x00f /* SEXP : SEXP -- it is the only command
supported in object-capability mode
and it requires that the SEXP is a
language construct with OC reference
in the first position */
#define CMD_OCinit 0x434f7352 /* SEXP -- 'RsOC' - command sent from
the server in OC mode with the packet
of initial capabilities. */
/* file I/O routines. server may answe */
#define CMD_openFile 0x010 /* fn : - */
#define CMD_createFile 0x011 /* fn : - */
#define CMD_closeFile 0x012 /* - : - */
#define CMD_readFile 0x013 /* [int size] : data... ; if size not present,
server is free to choose any value - usually
it uses the size of its static buffer */
#define CMD_writeFile 0x014 /* data : - */
#define CMD_removeFile 0x015 /* fn : - */
/* object manipulation */
#define CMD_setSEXP 0x020 /* string(name), REXP : - */
#define CMD_assignSEXP 0x021 /* string(name), REXP : - ; same as setSEXP
except that the name is parsed */
/* session management (since 0.4-0) */
#define CMD_detachSession 0x030 /* : session key */
#define CMD_detachedVoidEval 0x031 /* string : session key; doesn't */
#define CMD_attachSession 0x032 /* session key : - */
/* control commands (since 0.6-0) - passed on to the master process */
/* Note: currently all control commands are asychronous, i.e. RESP_OK
indicates that the command was enqueued in the master pipe, but there
is no guarantee that it will be processed. Moreover non-forked
connections (e.g. the default debug setup) don't process any
control commands until the current client connection is closed so
the connection issuing the control command will never see its
result.
*/
#define CMD_ctrl 0x40 /* -- not a command - just a constant -- */
#define CMD_ctrlEval 0x42 /* string : - */
#define CMD_ctrlSource 0x45 /* string : - */
#define CMD_ctrlShutdown 0x44 /* - : - */
/* 'internal' commands (since 0.1-9) */
#define CMD_setBufferSize 0x081 /* [int sendBufSize]
this commad allow clients to request
bigger buffer sizes if large data is to be
transported from Rserve to the client.
(incoming buffer is resized automatically)
*/
#define CMD_setEncoding 0x082 /* string (one of "native","latin1","utf8") : -; since 0.5-3 */
/* special commands - the payload of packages with this mask does not contain defined parameters */
#define CMD_SPECIAL_MASK 0xf0
#define CMD_serEval 0xf5 /* serialized eval - the packets are raw serialized data without data header */
#define CMD_serAssign 0xf6 /* serialized assign - serialized list with [[1]]=name, [[2]]=value */
#define CMD_serEEval 0xf7 /* serialized expression eval - like serEval with one additional evaluation round */
/* data types for the transport protocol (QAP1)
do NOT confuse with XT_.. values. */
#define DT_INT 1 /* int */
#define DT_CHAR 2 /* char */
#define DT_DOUBLE 3 /* double */
#define DT_STRING 4 /* 0 terminted string */
#define DT_BYTESTREAM 5 /* stream of bytes (unlike DT_STRING may contain 0) */
#define DT_SEXP 10 /* encoded SEXP */
#define DT_ARRAY 11 /* array of objects (i.e. first 4 bytes specify how many
subsequent objects are part of the array; 0 is legitimate) */
#define DT_CUSTOM 32 /* custom types not defined in the protocol but used
by applications */
#define DT_LARGE 64 /* new in 0102: if this flag is set then the length of the object
is coded as 56-bit integer enlarging the header by 4 bytes */
/* XpressionTypes
REXP - R expressions are packed in the same way as command parameters
transport format of the encoded Xpressions:
[0] int type/len (1 byte type, 3 bytes len - same as SET_PAR)
[4] REXP attr (if bit 8 in type is set)
[4/8] data .. */
#define XT_NULL 0 /* P data: [0] */
#define XT_INT 1 /* - data: [4]int */
#define XT_DOUBLE 2 /* - data: [8]double */
#define XT_STR 3 /* P data: [n]char null-term. strg. */
#define XT_LANG 4 /* - data: same as XT_LIST */
#define XT_SYM 5 /* - data: [n]char symbol name */
#define XT_BOOL 6 /* - data: [1]byte boolean
(1=TRUE, 0=FALSE, 2=NA) */
#define XT_S4 7 /* P data: [0] */
#define XT_VECTOR 16 /* P data: [?]REXP,REXP,.. */
#define XT_LIST 17 /* - X head, X vals, X tag (since 0.1-5) */
#define XT_CLOS 18 /* P X formals, X body (closure; since 0.1-5) */
#define XT_SYMNAME 19 /* s same as XT_STR (since 0.5) */
#define XT_LIST_NOTAG 20 /* s same as XT_VECTOR (since 0.5) */
#define XT_LIST_TAG 21 /* P X tag, X val, Y tag, Y val, ... (since 0.5) */
#define XT_LANG_NOTAG 22 /* s same as XT_LIST_NOTAG (since 0.5) */
#define XT_LANG_TAG 23 /* s same as XT_LIST_TAG (since 0.5) */
#define XT_VECTOR_EXP 26 /* s same as XT_VECTOR (since 0.5) */
#define XT_VECTOR_STR 27 /* - same as XT_VECTOR (since 0.5 but unused, use XT_ARRAY_STR instead) */
#define XT_ARRAY_INT 32 /* P data: [n*4]int,int,.. */
#define XT_ARRAY_DOUBLE 33 /* P data: [n*8]double,double,.. */
#define XT_ARRAY_STR 34 /* P data: string,string,.. (string=byte,byte,...,0) padded with '\01' */
#define XT_ARRAY_BOOL_UA 35 /* - data: [n]byte,byte,.. (unaligned! NOT supported anymore) */
#define XT_ARRAY_BOOL 36 /* P data: int(n),byte,byte,... */
#define XT_RAW 37 /* P data: int(n),byte,byte,... */
#define XT_ARRAY_CPLX 38 /* P data: [n*16]double,double,... (Re,Im,Re,Im,...) */
#define XT_UNKNOWN 48 /* P data: [4]int - SEXP type (as from TYPEOF(x)) */
/* |
+--- interesting flags for client implementations:
P = primary type
s = secondary type - its decoding is identical to
a primary type and thus the client doesn't need to
decode it separately.
- = deprecated/removed. if a client doesn't need to
support old Rserve versions, those can be safely
skipped.
Total primary: 4 trivial types (NULL, STR, S4, UNKNOWN) + 6 array types + 3 recursive types
*/
#define XT_LARGE 64 /* new in 0102: if this flag is set then the length of the object
is coded as 56-bit integer enlarging the header by 4 bytes */
#define XT_HAS_ATTR 128 /* flag; if set, the following REXP is the
attribute */
/* the use of attributes and vectors results in recursive storage of REXPs */
#define BOOL_TRUE 1
#define BOOL_FALSE 0
#define BOOL_NA 2
#define GET_XT(X) ((X)&63)
#define GET_DT(X) ((X)&63)
#define HAS_ATTR(X) (((X)&XT_HAS_ATTR)>0)
#define IS_LARGE(X) (((X)&XT_LARGE)>0)
#if defined sun && ! defined ALIGN_DOUBLES
#define ALIGN_DOUBLES
#endif
#ifndef SIZEOF_SIZE_T
#include /* defines SIZEOF_SIZE_T in case we missed it */
#endif
/* long vectors - we don't want to mandate Rinternals.h here
so we use the minimal definition */
#if ( SIZEOF_SIZE_T > 4 )
#include /* for ptrdiff_t, which is required by C99 */
typedef ptrdiff_t rlen_t;
/* this is used for alignment/masking */
#define rlen_max ((rlen_t) 0x7fffffffffffffff)
#else /* old legacy definition using unsigned long */
/* this is the type used to calculate pointer distances */
/* note: we may want to use size_t or something more compatible */
typedef unsigned long rlen_t;
#ifdef ULONG_MAX
#define rlen_max ULONG_MAX
#else
#ifdef __LP64__
#define rlen_max 0xffffffffffffffffL
#else
#define rlen_max 0xffffffffL
#endif /* __LP64__ */
#endif /* ULONG_MAX */
#endif /* long vector fallback */
/* functions/macros to convert native endianess of int/double for transport
currently ony PPC style and Intel style are supported */
/* Since 0.4-5 we no longer use configure-time endianness tests to allow cross-compilation.
Either BS_xx_ENDIAN constant is defined by configure and thus should be relied upon only if
the compiler contants don't work */
#if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN_
#define SWAPEND 1
#elif defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN_ || defined BS_LITTLE_ENDIAN
/* #undef SWAPEND */
#elif defined BS_BIG_ENDIAN
#define SWAPEND 1
#elif __ia64__ || __i386__ || __x86_64__ /* take a guess based on the architecture (Intel-like) */
#define __LITTLE_ENDIAN__ 1
#elif __ppc__ || __ppc64__ /* any ppc */
#define __BIG_ENDIAN__ 1
#define SWAPEND 1
#elif ! defined Win32 /* Windows is little-endian is most cases, anywhere else we're stuck */
#error "Cannot determine endianness. Make sure config.h is included or __{BIG|LITTLE}_ENDIAN__ is defined ."
#endif
/* FIXME: all the mess below needs more efficient implementation - the current one is so messy to work around alignment problems on some platforms like Sun and HP 9000 */
#ifdef SWAPEND /* swap endianness - for PPC and co. */
#ifdef MAIN
unsigned int itop(unsigned int i) { char b[4]; b[0]=((char*)&i)[3]; b[3]=((char*)&i)[0]; b[1]=((char*)&i)[2]; b[2]=((char*)&i)[1]; return *((unsigned int*)b); }
double dtop(double i) { char b[8]; b[0]=((char*)&i)[7]; b[1]=((char*)&i)[6]; b[2]=((char*)&i)[5]; b[3]=((char*)&i)[4]; b[7]=((char*)&i)[0]; b[6]=((char*)&i)[1]; b[5]=((char*)&i)[2]; b[4]=((char*)&i)[3]; return *((double*)b); }
void fixdcpy(void *t,void *s) { int i=0; while (i<8) { ((char*)t)[7-i]=((char*)s)[i]; i++; } }
#else
extern unsigned int itop(unsigned int i);
extern double dtop(double i);
extern void fixdcpy(void *t,void *s);
#endif
#define ptoi(X) itop(X) /* itop*itop=id */
#define ptod(X) dtop(X)
#else
#define itop(X) (X)
#define ptoi(X) (X)
#define dtop(X) (X)
#define ptod(X) (X)
#define fixdcpy(T,S) ((double*)(T))[0]=((double*)(S))[0];
#define NATIVE_COPY 1
#endif
#ifndef HAVE_CONFIG_H
/* this tiny function can be used to make sure that the endianess
is correct (it is not included if the package was configured with
autoconf since then it should be fine anyway) */
#ifdef MAIN
int isByteSexOk() {
int i;
i=itop(0x12345678);
return (*((char*)&i)==0x78);
}
#else
extern int isByteSexOk();
#endif
#else
#define isByteSexOk 1
#endif
/* STANDALONE_RSERVE takes precedence over RSERVE_PKG */
#if defined STANDALONE_RSERVE && defined RSERVE_PKG
#undef RSERVE_PKG
#endif
#endif
/*--- The following makes the indenting behavior of emacs compatible
with Xcode's 4/4 setting ---*/
/* Local Variables: */
/* indent-tabs-mode: t */
/* tab-width: 4 */
/* c-basic-offset: 4 */
/* End: */
Rserve/src/client/cxx/Makefile.in 0000644 0001760 0000144 00000000446 14147646005 016477 0 ustar ripley users # Makefile for C++ Rserve clients.
#
# $Id$
SRC = $(wildcard *.cc)
OBJ = $(SRC:%.cc=%.o)
DST = demo1 rcons rsdown
LIBS+=@LIBS@
CPPFLAGS+=-DHAVE_CONFIG_H
all: $(DST) $(OBJ)
%: Rconnection.o %.o
$(CXX) $^ -o $@ $(LIBS)
debug:
$(MAKE) CXXFLAGS=-g all
clean:
rm -rf *~ *.o \#* .\#* $(DST)
Rserve/src/client/cxx/Rconnection.h 0000644 0001760 0000144 00000032252 14147646005 017064 0 ustar ripley users /*
* C++ Interface to Rserve
* Copyright (C) 2004-8 Simon Urbanek, All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2.1 of the License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Leser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Although this code is licensed under LGPL v2.1, we strongly encourage
* everyone modifying this software to contribute back any improvements and
* bugfixes to the project for the benefit all other users. Thank you.
*
* $Id$
*/
/* external defines:
SWAPEND - needs to be defined for platforms with inverse endianess related to Intel
MAIN - should be defined in just one file that will contain the fn definitions and variables
(this is inherited from Rsrv.h and sisocks.h)
*/
#ifndef __RCONNECTION_H__
#define __RCONNECTION_H__
#if defined __GNUC__ && !defined unix && !defined Win32 && !defined WIN32
#define unix
#endif
#include
#include
#include "sisocks.h"
#include "Rsrv.h"
#ifdef __LP64__
typedef long Rsize_t;
#else
typedef int Rsize_t;
#endif
//=== Rconnection error codes
#define CERR_connect_failed -1
#define CERR_handshake_failed -2
#define CERR_invalid_id -3
#define CERR_protocol_not_supp -4
#define CERR_not_connected -5
#define CERR_peer_closed -7
#define CERR_malformed_packet -8
#define CERR_send_error -9
#define CERR_out_of_mem -10
#define CERR_not_supported -11
#define CERR_io_error -12
// this one is custom - authentication method required by
// the server is not supported in this client
#define CERR_auth_unsupported -20
#define A_required 0x001
#define A_crypt 0x002
#define A_plain 0x004
//===================================== Rmessage ---- QAP1 storage
class Rmessage {
public:
struct phdr head;
char *data;
Rsize_t len;
int complete;
// the following is avaliable only for parsed messages (max 16 pars)
int pars;
unsigned int *par[16];
Rmessage();
Rmessage(int cmd); // 0 data
Rmessage(int cmd, const char *txt); // DT_STRING data
Rmessage(int cmd, int i); // DT_INT data (1 entry)
Rmessage(int cmd, const void *buf, int len, int raw_data=0); // raw data or DT_BYTESTREAM
virtual ~Rmessage();
int command() { return complete?head.cmd:-1; }
Rsize_t length() { return complete?head.len:-1; }
int is_complete() { return complete; }
int read(int s);
void parse();
int send(int s);
};
//===================================== Rexp --- basis for all SEXPs
class Rexp {
public:
Rmessage *msg;
unsigned int *pos;
Rsize_t len;
Rexp *attr;
int type;
/* memory manegement for data/len:
- content is in a message and this Rexp is the master of that message:
master=0; msg=;
- content is in a message, but this Rexp is not the master
master=; msg=0
- content is all self-allocated with no message associated
master=this; msg=0 */
char *data, *next;
protected:
// the next two are only cached if requested, no direct access allowed
int attribs;
const char **attrnames;
Rexp *master; // if this is set then this Rexp allocated the memory for us, so we are not supposed to free anything; if this is set to "this" then the content is self-allocated, including any data
int rcount; // reference count - only for a master - it counts how many children still exist
public:
Rexp(Rmessage *msg);
Rexp(unsigned int *pos, Rmessage *msg=0);
Rexp(int type, const char *data=0, Rsize_t len=0, Rexp *attr=0);
virtual ~Rexp();
void set_master(Rexp *m);
char *parse(unsigned int *pos);
virtual Rsize_t storageSize() { return len+((len>0x7fffff)?8:4); }
virtual void store(char *buf);
Rexp *attribute(const char *name);
const char **attributeNames();
virtual Rsize_t length() { return len; }
friend std::ostream& operator<< (std::ostream& os, const Rexp& exp) {
return ((Rexp&)exp).os_print(os);
}
friend std::ostream& operator<< (std::ostream& os, const Rexp* exp) {
return ((Rexp*)exp)->os_print(os);
}
virtual std::ostream& os_print(std::ostream& os) {
return os << "Rexp[type=" << type << ",len=" << len <<"]";
}
};
//===================================== Rint --- XT_INT/XT_ARRAY_INT
class Rinteger : public Rexp {
public:
Rinteger(Rmessage *msg) : Rexp(msg) { fix_content(); }
Rinteger(unsigned int *ipos, Rmessage *imsg) : Rexp(ipos, imsg) { fix_content(); }
Rinteger(int *array, int count) : Rexp(XT_ARRAY_INT, (char*)array, count*sizeof(int)) { fix_content(); }
int *intArray() { return (int*) data; }
int intAt(int pos) { return (pos>=0 && (unsigned)pos=0 && (unsigned)pos= nel) ? 0 : cont[i]; }
char *string() { return stringAt(0); }
virtual Rsize_t length() { return nel; }
unsigned int count() { return nel; }
int indexOfString(const char *str);
virtual std::ostream& os_print (std::ostream& os) {
return os << "char*[" << nel <<"]\"" << string() <<"\"..";
}
private:
void decode() {
char *c = (char*) data;
unsigned int i = 0;
nel = 0;
while (i < len) { if (!c[i]) nel++; i++; }
if (nel) {
i = 0;
cont = (char**) malloc(sizeof(char*)*nel);
while (i < nel) {
cont[i] = strdup(c);
while (*c) c++;
c++; i++;
}
} else
cont = 0;
}
};
//===================================== Rstring --- XT_STR
class Rstring : public Rexp {
public:
Rstring(Rmessage *msg) : Rexp(msg) {}
Rstring(unsigned int *ipos, Rmessage *imsg) : Rexp(ipos, imsg) {}
Rstring(const char *str) : Rexp(XT_STR, str, strlen(str)+1) {}
char *string() { return (char*) data; }
virtual std::ostream& os_print (std::ostream& os) {
return os << "\"" << string() <<"\"";
}
};
//===================================== Rlist --- XT_LIST (CONS lists)
class Rlist : public Rexp {
public:
Rexp *head, *tag;
Rlist *tail;
Rlist(Rmessage *msg) : Rexp(msg)
{ head=tag=0; tail=0; fix_content(); }
Rlist(unsigned int *ipos, Rmessage *imsg) : Rexp(ipos, imsg)
{ head=tag=0; tail=0; fix_content(); }
/* this is a sort of special constructor that allows to create a Rlist
based solely on its content. This is necessary since 0.5 because
each LISTSXP is no longer represented by its own encoded SEXP
but they are packed in one content list instead */
Rlist(int type, Rexp *head, Rexp *tag, char *next, Rmessage *imsg) : Rexp(type, 0, 0, 0) { this->head = head; this->tag = tag; tail = 0; this->next = next; this->msg = imsg; master = 0; }
virtual ~Rlist();
Rexp *entryByTagName(const char *tagName) {
if (tag && (tag->type==XT_SYM || tag->type==XT_SYMNAME) && !strcmp(((Rsymbol*)tag)->symbolName(),tagName)) return head;
if (tail) return tail->entryByTagName(tagName);
return 0;
}
virtual std::ostream& os_print (std::ostream& os) {
os << "Rlist[tag=";
if (tag) os << *tag; else os << "";
os << ",head=";
if (head) os << *head; else os << "";
if (tail) os << ",tail=" << *tail;
return os << "]";
}
private:
void fix_content();
};
//===================================== Rvector --- XT_VECTOR (general lists)
class Rvector : public Rexp {
protected:
Rexp **cont;
int count;
// cached
char **strs;
public:
Rvector(Rmessage *msg) : Rexp(msg)
{ cont=0; count=0; strs=0; fix_content(); }
Rvector(unsigned int *ipos, Rmessage *imsg) : Rexp(ipos, imsg)
{ cont=0; count=0; strs=0; fix_content(); }
virtual ~Rvector();
char **strings();
int indexOf(Rexp *exp);
int indexOfString(const char *str);
virtual Rsize_t length() { return (Rsize_t) count; }
char *stringAt(int i) {
if (i < 0 || i >= count || !cont[i] || cont[i]->type != XT_STR) return 0;
return ((Rstring*)cont[i])->string();
}
Rexp *elementAt(int i) {
return (i < 0 || i >= count || !cont[i]) ? 0 : cont[i];
}
Rexp* byName(const char *name);
virtual std::ostream& os_print (std::ostream& os) {
os << "Rvector[count=" << count << ":";
int i=0;
while (i