mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 19:34:43 +01:00
Compare commits
110
Commits
stable/6
...
releng/6.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f9161735d | ||
|
|
3adbb43be3 | ||
|
|
bd60f04dc1 | ||
|
|
cb71836b2a | ||
|
|
12654543b1 | ||
|
|
952181054e | ||
|
|
6de6f7e901 | ||
|
|
9e1260e620 | ||
|
|
060a6d9a79 | ||
|
|
c7e7298883 | ||
|
|
7f7ea37f6f | ||
|
|
0146a3ffc6 | ||
|
|
5aad434d14 | ||
|
|
968aa2f3c6 | ||
|
|
f57226bf4c | ||
|
|
10753525fc | ||
|
|
bc57f3a142 | ||
|
|
d533a1a065 | ||
|
|
3d215489fe | ||
|
|
da2cd746e7 | ||
|
|
52b835344d | ||
|
|
ffdda74401 | ||
|
|
d78cc8da72 | ||
|
|
957f5ead91 | ||
|
|
c0a7104606 | ||
|
|
3d888e5914 | ||
|
|
35738380af | ||
|
|
e658bb489d | ||
|
|
21f0307211 | ||
|
|
887d355270 | ||
|
|
6636f48868 | ||
|
|
66308c6270 | ||
|
|
087ac34ec2 | ||
|
|
ede84755f3 | ||
|
|
c5e3056011 | ||
|
|
abf809c118 | ||
|
|
96fb3ac3fc | ||
|
|
17fc0cbcdb | ||
|
|
01b1c3795a | ||
|
|
95dfc0a1cc | ||
|
|
5e4677ca87 | ||
|
|
218f2e0ec5 | ||
|
|
527ef1908a | ||
|
|
b7217bb7d0 | ||
|
|
628f5eef34 | ||
|
|
e6d8fd44a4 | ||
|
|
5f37fe5bda | ||
|
|
18d2ca12a1 | ||
|
|
8cb3b5729f | ||
|
|
e8d38e80bb | ||
|
|
905dbf6afa | ||
|
|
71c60dd1de | ||
|
|
d26e5dee60 | ||
|
|
020ec29a79 | ||
|
|
5dd20217a6 | ||
|
|
d2854f8b92 | ||
|
|
0dbb2e0f34 | ||
|
|
fd47f7362f | ||
|
|
b75aec04ff | ||
|
|
99c293401c | ||
|
|
fe1746fb90 | ||
|
|
2e2bc37c17 | ||
|
|
3b30fd6060 | ||
|
|
22ff0d37be | ||
|
|
f66ce35e97 | ||
|
|
ff7bd1bebf | ||
|
|
3aafcdb5aa | ||
|
|
0fcef6909b | ||
|
|
b79874b1ac | ||
|
|
9a8c805f4e | ||
|
|
ae4c6d68b3 | ||
|
|
75609203af | ||
|
|
9792749811 | ||
|
|
a42a37b2b1 | ||
|
|
a09f52b5b4 | ||
|
|
12abcec092 | ||
|
|
c46ee19798 | ||
|
|
a21bfc1306 | ||
|
|
cfb0cdce75 | ||
|
|
3e0b8fb346 | ||
|
|
1d64cdbb8b | ||
|
|
92ad66505c | ||
|
|
38104e8617 | ||
|
|
34ffcac9fd | ||
|
|
a851385207 | ||
|
|
fdd3ac39c8 | ||
|
|
2ca115c41b | ||
|
|
1101e1b905 | ||
|
|
063395a5a5 | ||
|
|
1b3663cbaa | ||
|
|
ede7fe23cb | ||
|
|
daab09ff7d | ||
|
|
385a4b0a41 | ||
|
|
191bfb282f | ||
|
|
5a02e2d3f6 | ||
|
|
3d0f46b8df | ||
|
|
741347619e | ||
|
|
07d746f573 | ||
|
|
32dc657349 | ||
|
|
8051874cd7 | ||
|
|
a8e6180850 | ||
|
|
8b7a63f7e1 | ||
|
|
75c7560dfb | ||
|
|
f2adbc2073 | ||
|
|
4c096043ce | ||
|
|
e9c4c22b54 | ||
|
|
0f88086d1a | ||
|
|
bdc8787cc2 | ||
|
|
968d7a6a6d | ||
|
|
4f345d81ac |
No files matched your search
+1
-1
@@ -87,7 +87,7 @@ CLEANDIR= cleandir
|
||||
.endif
|
||||
|
||||
CVS?= cvs
|
||||
CVSFLAGS?= -r RELENG_6 -P -d -I!
|
||||
CVSFLAGS?= -r RELENG_6_0 -P -d -I!
|
||||
SUP?= /usr/local/bin/cvsup
|
||||
SUPFLAGS?= -g -L 2 -P -
|
||||
.if defined(SUPHOST)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Updating Information for FreeBSD current users
|
||||
Updating Information for FreeBSD STABLE users
|
||||
|
||||
This file is maintained and copyrighted by M. Warner Losh
|
||||
<[email protected]>. See end of file for further details. For commonly
|
||||
@@ -8,18 +8,108 @@ Items affecting the ports and packages system can be found in
|
||||
/usr/ports/UPDATING. Please read that file before running
|
||||
portupgrade.
|
||||
|
||||
NOTE TO PEOPLE WHO THINK THAT FreeBSD 6.x IS SLOW:
|
||||
FreeBSD 6.x has many debugging features turned on, in
|
||||
both the kernel and userland. These features attempt to detect
|
||||
incorrect use of system primitives, and encourage loud failure
|
||||
through extra sanity checking and fail stop semantics. They
|
||||
also substantially impact system performance. If you want to
|
||||
do performance measurement, benchmarking, and optimization,
|
||||
you'll want to turn them off. This includes various WITNESS-
|
||||
related kernel options, INVARIANTS, malloc debugging flags
|
||||
in userland, and various verbose features in the kernel. Many
|
||||
developers choose to disable these features on build machines
|
||||
to maximize performance.
|
||||
20070214: p18 FreeBSD-EN-07:01.nfs
|
||||
Correct problems with locking, namei leakage, and symlink
|
||||
creation in the NFS subsystem.
|
||||
|
||||
20070111: p17 FreeBSD-SA-07:01.jail
|
||||
Correct jail rc.d script privilege escalation.
|
||||
|
||||
20061206: p16 FreeBSD-SA-06:25.kmem
|
||||
Correct a signedness bug which allowed members of the operator
|
||||
group to read kernel memory.
|
||||
|
||||
20060930: p15 FreeBSD-SA-06:22.openssh
|
||||
Correct multiple vulnerabilities in sshd(8).
|
||||
|
||||
20060929: p14 FreeBSD-SA-06:23.openssl
|
||||
Correct problem in the 2006-09-28 patch concerning the handling of
|
||||
excessively large DH moduli.
|
||||
|
||||
20060928: p13 FreeBSD-SA-06:23.openssl
|
||||
Correct multiple vulnerabilities in crypto(3).
|
||||
Limit the size of public keys used in order to protect applications
|
||||
from a denial of service via insane key sizes.
|
||||
|
||||
20060919: p12 FreeBSD-SA-06:21.gzip
|
||||
Correct multiple vulnerabilities in gzip(1).
|
||||
|
||||
20060906: p11 FreeBSD-SA-06:19.openssl, FreeBSD-SA-06:20.bind
|
||||
Correct incorrect PKCS#1 v1.5 padding validation in
|
||||
crypto(3). [06:19]
|
||||
|
||||
Correct multiple denial-of-service vulnerabilities in BIND related to
|
||||
SIG Query Processing and Excessive Recursive Queries. [06:20]
|
||||
|
||||
20060823: p10 FreeBSD-SA-06:18.ppp
|
||||
Correct buffer overflow in the handling of LCP options in ppp(4).
|
||||
|
||||
20060614: p9 FreeBSD-SA-06:17.sendmail
|
||||
Correct a bug in the handling of multipart messages by sendmail(8)
|
||||
which can allow a malformed message to crash a sendmail queue
|
||||
processing process.
|
||||
|
||||
20060531: p8 FreeBSD-SA-06:15.ypserv, FreeBSD-SA-06:16.smbfs
|
||||
Enable inadvertantly disabled "securenet" access controls in
|
||||
ypserv. [06:15]
|
||||
|
||||
Correct a bug in the handling of backslash characters in smbfs
|
||||
which can allow an attacker to escape from a chroot(2). [06:16]
|
||||
|
||||
20060419: p7 FreeBSD-SA-06:14.fpu
|
||||
Correct a local information leakage bug affecting AMD FPUs.
|
||||
|
||||
20060322: p6 FreeBSD-SA-06:11.ipsec, FreeBSD-SA-06:12.opie,
|
||||
FreeBSD-SA-06:13.sendmail
|
||||
Add missing code needed for the detection of IPSec packet
|
||||
replays. [06:11]
|
||||
|
||||
Correctly identify the user running opiepasswd(1) when the login
|
||||
name differs from the account name. [06:12]
|
||||
|
||||
Modify timeout handling logic in sendmail(8) to correct a reported
|
||||
signal handling race condition. [06:13]
|
||||
|
||||
20060301: p5 FreeBSD-SA-06:10.nfs
|
||||
Correct a remote kernel panic when processing zero-length RPC
|
||||
records via TCP.
|
||||
|
||||
20060125: p4 FreeBSD-SA-06:06.kmem, FreeBSD-SA-06:07.pf
|
||||
Make sure buffers in if_bridge are fully initialized before
|
||||
copying them to userland. Correct a logic error which could
|
||||
allow too much data to be copied into userland. [06:06]
|
||||
|
||||
Correct an error in pf handling of IP packet fragments which
|
||||
could result in a kernel panic. [06:07]
|
||||
|
||||
20060118: p3 FreeBSD-SA-06:05.80211
|
||||
Correct a buffer overflow when scanning for 802.11 wireless
|
||||
networks which can be provoked by corrupt beacon or probe
|
||||
response frames.
|
||||
|
||||
20060111: p2 FreeBSD-SA-06:01.texindex, FreeBSD-SA-06:02.ee,
|
||||
FreeBSD-SA-06:03.cpio, FreeBSD-SA-06:04.ipfw
|
||||
Correct insecure temporary file usage in texindex. [06:01]
|
||||
|
||||
Correct insecure temporary file usage in ee. [06:02]
|
||||
|
||||
Correct a race condition when setting file permissions,
|
||||
sanitize file names by default, and fix a buffer overflow
|
||||
when handling files larger than 4GB in cpio. [06:03]
|
||||
|
||||
Fix an error in the handling of IP fragments in ipfw which
|
||||
can cause a kernel panic. [06:04]
|
||||
|
||||
20051219: p1 FreeBSD-EN-05:04.nfs
|
||||
Correct a locking issue in nfs_lookup() where a call to vrele()
|
||||
might be made while holding the vnode mutex, which resulted
|
||||
in kernel panics under certain load patterns.
|
||||
|
||||
20051101:
|
||||
FreeBSD 6.0-RELEASE
|
||||
|
||||
20051011: FreeBSD-SA-05:21.openssl
|
||||
Correct a man-in-the-middle SSL version rollback vulnerability.
|
||||
|
||||
20051001:
|
||||
kern.polling.enable sysctl MIB is now deprecated. Use ifconfig(8)
|
||||
@@ -238,6 +328,9 @@ COMMON ITEMS:
|
||||
prefix all make commands with 'env -i '. See the env(1) manual
|
||||
page for more details.
|
||||
|
||||
Due to several updates to the build infrastructure, source
|
||||
upgrades from versions prior to 5.3 no longer supported.
|
||||
|
||||
To build a kernel
|
||||
-----------------
|
||||
If you are updating from a prior version of FreeBSD (even one just
|
||||
@@ -256,7 +349,7 @@ COMMON ITEMS:
|
||||
|
||||
To just build a kernel when you know that it won't mess you up
|
||||
--------------------------------------------------------------
|
||||
This assumes you are already running a 5.X system. Replace
|
||||
This assumes you are already running a 6.X system. Replace
|
||||
${arch} with the architecture of your machine (e.g. "i386",
|
||||
"alpha", "amd64", "ia64", "pc98", "sparc64", etc).
|
||||
|
||||
@@ -309,8 +402,8 @@ COMMON ITEMS:
|
||||
<reboot>
|
||||
|
||||
|
||||
To upgrade in-place from 5.x-stable to current
|
||||
----------------------------------------------
|
||||
To upgrade in-place from 5.x-stable or higher to 6.x-stable
|
||||
-----------------------------------------------------------
|
||||
<make sure you have good level 0 dumps>
|
||||
make buildworld [9]
|
||||
make kernel KERNCONF=YOUR_KERNEL_HERE [8]
|
||||
@@ -355,13 +448,10 @@ COMMON ITEMS:
|
||||
|
||||
[5] Usually this step is a noop. However, from time to time
|
||||
you may need to do this if you get unknown user in the following
|
||||
step. It never hurts to do it all the time. You may need to
|
||||
install a new mergemaster (cd src/usr.sbin/mergemaster && make
|
||||
install) after the buildworld before this step if you last updated
|
||||
from current before 20020224 or from -stable before 20020408.
|
||||
step. It never hurts to do it all the time.
|
||||
|
||||
[8] In order to have a kernel that can run the 4.x binaries
|
||||
needed to do an installworld, you must include the COMPAT_FREEBSD4
|
||||
[8] In order to have a kernel that can run the 5.x binaries
|
||||
needed to do an installworld, you must include the COMPAT_FREEBSD5
|
||||
option in your kernel. Failure to do so may leave you with a system
|
||||
that is hard to boot to recover.
|
||||
|
||||
@@ -381,7 +471,7 @@ COMMON ITEMS:
|
||||
FORMAT:
|
||||
|
||||
This file contains a list, in reverse chronological order, of major
|
||||
breakages in tracking -current. Not all things will be listed here,
|
||||
breakages in tracking -STABLE. Not all things will be listed here,
|
||||
and it only starts on October 16, 2004. Updating files can found in
|
||||
previous releases if your system is older than this.
|
||||
|
||||
|
||||
@@ -2389,7 +2389,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
is_zone = ISC_FALSE;
|
||||
|
||||
qtype = event->qtype;
|
||||
if (qtype == dns_rdatatype_rrsig)
|
||||
if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
|
||||
type = dns_rdatatype_any;
|
||||
else
|
||||
type = qtype;
|
||||
@@ -2430,7 +2430,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
/*
|
||||
* If it's a SIG query, we'll iterate the node.
|
||||
*/
|
||||
if (qtype == dns_rdatatype_rrsig)
|
||||
if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
|
||||
type = dns_rdatatype_any;
|
||||
else
|
||||
type = qtype;
|
||||
|
||||
@@ -728,7 +728,8 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
|
||||
INSIST(result != ISC_R_SUCCESS ||
|
||||
dns_rdataset_isassociated(event->rdataset) ||
|
||||
fctx->type == dns_rdatatype_any ||
|
||||
fctx->type == dns_rdatatype_rrsig);
|
||||
fctx->type == dns_rdatatype_rrsig ||
|
||||
fctx->type == dns_rdatatype_sig);
|
||||
|
||||
isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event));
|
||||
}
|
||||
@@ -3153,7 +3154,8 @@ validated(isc_task_t *task, isc_event_t *event) {
|
||||
if (hevent != NULL) {
|
||||
if (!negative && !chaining &&
|
||||
(fctx->type == dns_rdatatype_any ||
|
||||
fctx->type == dns_rdatatype_rrsig)) {
|
||||
fctx->type == dns_rdatatype_rrsig ||
|
||||
fctx->type == dns_rdatatype_sig)) {
|
||||
/*
|
||||
* Don't bind rdatasets; the caller
|
||||
* will iterate the node.
|
||||
@@ -3265,7 +3267,8 @@ validated(isc_task_t *task, isc_event_t *event) {
|
||||
if (!ISC_LIST_EMPTY(fctx->validators)) {
|
||||
INSIST(!negative);
|
||||
INSIST(fctx->type == dns_rdatatype_any ||
|
||||
fctx->type == dns_rdatatype_rrsig);
|
||||
fctx->type == dns_rdatatype_rrsig ||
|
||||
fctx->type == dns_rdatatype_sig);
|
||||
/*
|
||||
* Don't send a response yet - we have
|
||||
* more rdatasets that still need to
|
||||
@@ -3411,14 +3414,15 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) {
|
||||
return (result);
|
||||
anodep = &event->node;
|
||||
/*
|
||||
* If this is an ANY or SIG query, we're not going
|
||||
* to return any rdatasets, unless we encountered
|
||||
* If this is an ANY, SIG or RRSIG query, we're not
|
||||
* going to return any rdatasets, unless we encountered
|
||||
* a CNAME or DNAME as "the answer". In this case,
|
||||
* we're going to return DNS_R_CNAME or DNS_R_DNAME
|
||||
* and we must set up the rdatasets.
|
||||
*/
|
||||
if ((fctx->type != dns_rdatatype_any &&
|
||||
fctx->type != dns_rdatatype_rrsig) ||
|
||||
fctx->type != dns_rdatatype_rrsig &&
|
||||
fctx->type != dns_rdatatype_sig) ||
|
||||
(name->attributes & DNS_NAMEATTR_CHAINING) != 0) {
|
||||
ardataset = event->rdataset;
|
||||
asigrdataset = event->sigrdataset;
|
||||
@@ -3477,7 +3481,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) {
|
||||
*/
|
||||
if (secure_domain && rdataset->trust != dns_trust_glue) {
|
||||
/*
|
||||
* SIGs are validated as part of validating the
|
||||
* RRSIGs are validated as part of validating the
|
||||
* type they cover.
|
||||
*/
|
||||
if (rdataset->type == dns_rdatatype_rrsig)
|
||||
@@ -3547,7 +3551,8 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) {
|
||||
|
||||
if (ANSWER(rdataset) && need_validation) {
|
||||
if (fctx->type != dns_rdatatype_any &&
|
||||
fctx->type != dns_rdatatype_rrsig) {
|
||||
fctx->type != dns_rdatatype_rrsig &&
|
||||
fctx->type != dns_rdatatype_sig) {
|
||||
/*
|
||||
* This is The Answer. We will
|
||||
* validate it, but first we cache
|
||||
@@ -3742,23 +3747,28 @@ ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
|
||||
isc_result_t *eresultp)
|
||||
{
|
||||
isc_result_t result;
|
||||
dns_rdataset_t rdataset;
|
||||
|
||||
if (ardataset == NULL) {
|
||||
dns_rdataset_init(&rdataset);
|
||||
ardataset = &rdataset;
|
||||
}
|
||||
result = dns_ncache_add(message, cache, node, covers, now,
|
||||
maxttl, ardataset);
|
||||
if (result == DNS_R_UNCHANGED) {
|
||||
if (result == DNS_R_UNCHANGED || result == ISC_R_SUCCESS) {
|
||||
/*
|
||||
* The data in the cache are better than the negative cache
|
||||
* entry we're trying to add.
|
||||
* If the cache now contains a negative entry and we
|
||||
* care about whether it is DNS_R_NCACHENXDOMAIN or
|
||||
* DNS_R_NCACHENXRRSET then extract it.
|
||||
*/
|
||||
if (ardataset != NULL && ardataset->type == 0) {
|
||||
if (ardataset->type == 0) {
|
||||
/*
|
||||
* The cache data is also a negative cache
|
||||
* entry.
|
||||
* The cache data is a negative cache entry.
|
||||
*/
|
||||
if (NXDOMAIN(ardataset))
|
||||
*eresultp = DNS_R_NCACHENXDOMAIN;
|
||||
else
|
||||
*eresultp = DNS_R_NCACHENXRRSET;
|
||||
result = ISC_R_SUCCESS;
|
||||
} else {
|
||||
/*
|
||||
* Either we don't care about the nature of the
|
||||
@@ -3770,14 +3780,11 @@ ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
|
||||
* XXXRTH There's a CNAME/DNAME problem here.
|
||||
*/
|
||||
*eresultp = ISC_R_SUCCESS;
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
} else if (result == ISC_R_SUCCESS) {
|
||||
if (NXDOMAIN(ardataset))
|
||||
*eresultp = DNS_R_NCACHENXDOMAIN;
|
||||
else
|
||||
*eresultp = DNS_R_NCACHENXRRSET;
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
if (ardataset == &rdataset && dns_rdataset_isassociated(ardataset))
|
||||
dns_rdataset_disassociate(ardataset);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
@@ -1,705 +0,0 @@
|
||||
Notes on the Free Translation Project
|
||||
*************************************
|
||||
|
||||
Free software is going international! The Free Translation Project is
|
||||
a way to get maintainers of free software, translators, and users all
|
||||
together, so that will gradually become able to speak many languages.
|
||||
A few packages already provide translations for their messages.
|
||||
|
||||
If you found this `ABOUT-NLS' file inside a distribution, you may
|
||||
assume that the distributed package does use GNU `gettext' internally,
|
||||
itself available at your nearest GNU archive site. But you do _not_
|
||||
need to install GNU `gettext' prior to configuring, installing or using
|
||||
this package with messages translated.
|
||||
|
||||
Installers will find here some useful hints. These notes also
|
||||
explain how users should proceed for getting the programs to use the
|
||||
available translations. They tell how people wanting to contribute and
|
||||
work at translations should contact the appropriate team.
|
||||
|
||||
When reporting bugs in the `intl/' directory or bugs which may be
|
||||
related to internationalization, you should tell about the version of
|
||||
`gettext' which is used. The information can be found in the
|
||||
`intl/VERSION' file, in internationalized packages.
|
||||
|
||||
Quick configuration advice
|
||||
==========================
|
||||
|
||||
If you want to exploit the full power of internationalization, you
|
||||
should configure it using
|
||||
|
||||
./configure --with-included-gettext
|
||||
|
||||
to force usage of internationalizing routines provided within this
|
||||
package, despite the existence of internationalizing capabilities in the
|
||||
operating system where this package is being installed. So far, only
|
||||
the `gettext' implementation in the GNU C library version 2 provides as
|
||||
many features (such as locale alias, message inheritance, automatic
|
||||
charset conversion or plural form handling) as the implementation here.
|
||||
It is also not possible to offer this additional functionality on top
|
||||
of a `catgets' implementation. Future versions of GNU `gettext' will
|
||||
very likely convey even more functionality. So it might be a good idea
|
||||
to change to GNU `gettext' as soon as possible.
|
||||
|
||||
So you need _not_ provide this option if you are using GNU libc 2 or
|
||||
you have installed a recent copy of the GNU gettext package with the
|
||||
included `libintl'.
|
||||
|
||||
INSTALL Matters
|
||||
===============
|
||||
|
||||
Some packages are "localizable" when properly installed; the programs
|
||||
they contain can be made to speak your own native language. Most such
|
||||
packages use GNU `gettext'. Other packages have their own ways to
|
||||
internationalization, predating GNU `gettext'.
|
||||
|
||||
By default, this package will be installed to allow translation of
|
||||
messages. It will automatically detect whether the system already
|
||||
provides the GNU `gettext' functions. If not, the GNU `gettext' own
|
||||
library will be used. This library is wholly contained within this
|
||||
package, usually in the `intl/' subdirectory, so prior installation of
|
||||
the GNU `gettext' package is _not_ required. Installers may use
|
||||
special options at configuration time for changing the default
|
||||
behaviour. The commands:
|
||||
|
||||
./configure --with-included-gettext
|
||||
./configure --disable-nls
|
||||
|
||||
will respectively bypass any pre-existing `gettext' to use the
|
||||
internationalizing routines provided within this package, or else,
|
||||
_totally_ disable translation of messages.
|
||||
|
||||
When you already have GNU `gettext' installed on your system and run
|
||||
configure without an option for your new package, `configure' will
|
||||
probably detect the previously built and installed `libintl.a' file and
|
||||
will decide to use this. This might be not what is desirable. You
|
||||
should use the more recent version of the GNU `gettext' library. I.e.
|
||||
if the file `intl/VERSION' shows that the library which comes with this
|
||||
package is more recent, you should use
|
||||
|
||||
./configure --with-included-gettext
|
||||
|
||||
to prevent auto-detection.
|
||||
|
||||
The configuration process will not test for the `catgets' function
|
||||
and therefore it will not be used. The reason is that even an
|
||||
emulation of `gettext' on top of `catgets' could not provide all the
|
||||
extensions of the GNU `gettext' library.
|
||||
|
||||
Internationalized packages have usually many `po/LL.po' files, where
|
||||
LL gives an ISO 639 two-letter code identifying the language. Unless
|
||||
translations have been forbidden at `configure' time by using the
|
||||
`--disable-nls' switch, all available translations are installed
|
||||
together with the package. However, the environment variable `LINGUAS'
|
||||
may be set, prior to configuration, to limit the installed set.
|
||||
`LINGUAS' should then contain a space separated list of two-letter
|
||||
codes, stating which languages are allowed.
|
||||
|
||||
Using This Package
|
||||
==================
|
||||
|
||||
As a user, if your language has been installed for this package, you
|
||||
only have to set the `LANG' environment variable to the appropriate
|
||||
`LL_CC' combination. Here `LL' is an ISO 639 two-letter language code,
|
||||
and `CC' is an ISO 3166 two-letter country code. For example, let's
|
||||
suppose that you speak German and live in Germany. At the shell
|
||||
prompt, merely execute `setenv LANG de_DE' (in `csh'),
|
||||
`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash').
|
||||
This can be done from your `.login' or `.profile' file, once and for
|
||||
all.
|
||||
|
||||
You might think that the country code specification is redundant.
|
||||
But in fact, some languages have dialects in different countries. For
|
||||
example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The
|
||||
country code serves to distinguish the dialects.
|
||||
|
||||
The locale naming convention of `LL_CC', with `LL' denoting the
|
||||
language and `CC' denoting the country, is the one use on systems based
|
||||
on GNU libc. On other systems, some variations of this scheme are
|
||||
used, such as `LL' or `LL_CC.ENCODING'. You can get the list of
|
||||
locales supported by your system for your country by running the command
|
||||
`locale -a | grep '^LL''.
|
||||
|
||||
Not all programs have translations for all languages. By default, an
|
||||
English message is shown in place of a nonexistent translation. If you
|
||||
understand other languages, you can set up a priority list of languages.
|
||||
This is done through a different environment variable, called
|
||||
`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG'
|
||||
for the purpose of message handling, but you still need to have `LANG'
|
||||
set to the primary language; this is required by other parts of the
|
||||
system libraries. For example, some Swedish users who would rather
|
||||
read translations in German than English for when Swedish is not
|
||||
available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'.
|
||||
|
||||
In the `LANGUAGE' environment variable, but not in the `LANG'
|
||||
environment variable, `LL_CC' combinations can be abbreviated as `LL'
|
||||
to denote the language's main dialect. For example, `de' is equivalent
|
||||
to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT'
|
||||
(Portuguese as spoken in Portugal) in this context.
|
||||
|
||||
Translating Teams
|
||||
=================
|
||||
|
||||
For the Free Translation Project to be a success, we need interested
|
||||
people who like their own language and write it well, and who are also
|
||||
able to synergize with other translators speaking the same language.
|
||||
Each translation team has its own mailing list. The up-to-date list of
|
||||
teams can be found at the Free Translation Project's homepage,
|
||||
`http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams"
|
||||
area.
|
||||
|
||||
If you'd like to volunteer to _work_ at translating messages, you
|
||||
should become a member of the translating team for your own language.
|
||||
The subscribing address is _not_ the same as the list itself, it has
|
||||
`-request' appended. For example, speakers of Swedish can send a
|
||||
message to `[email protected]', having this message body:
|
||||
|
||||
subscribe
|
||||
|
||||
Keep in mind that team members are expected to participate
|
||||
_actively_ in translations, or at solving translational difficulties,
|
||||
rather than merely lurking around. If your team does not exist yet and
|
||||
you want to start one, or if you are unsure about what to do or how to
|
||||
get started, please write to `[email protected]' to reach the
|
||||
coordinator for all translator teams.
|
||||
|
||||
The English team is special. It works at improving and uniformizing
|
||||
the terminology in use. Proven linguistic skill are praised more than
|
||||
programming skill, here.
|
||||
|
||||
Available Packages
|
||||
==================
|
||||
|
||||
Languages are not equally supported in all packages. The following
|
||||
matrix shows the current state of internationalization, as of November
|
||||
2003. The matrix shows, in regard of each package, for which languages
|
||||
PO files have been submitted to translation coordination, with a
|
||||
translation percentage of at least 50%.
|
||||
|
||||
Ready PO files am az be bg ca cs da de el en en_GB eo es
|
||||
+-------------------------------------------+
|
||||
a2ps | [] [] [] [] |
|
||||
aegis | () |
|
||||
ant-phone | () |
|
||||
anubis | |
|
||||
ap-utils | |
|
||||
bash | [] [] [] [] |
|
||||
batchelor | |
|
||||
bfd | [] [] |
|
||||
binutils | [] [] |
|
||||
bison | [] [] [] |
|
||||
bluez-pin | [] [] |
|
||||
clisp | [] [] [] |
|
||||
clisp | |
|
||||
coreutils | [] [] [] [] |
|
||||
cpio | [] [] [] |
|
||||
darkstat | [] () [] |
|
||||
diffutils | [] [] [] [] [] [] [] |
|
||||
e2fsprogs | [] [] |
|
||||
enscript | [] [] [] [] |
|
||||
error | [] [] [] [] [] |
|
||||
fetchmail | [] () [] [] [] [] |
|
||||
fileutils | [] [] [] |
|
||||
findutils | [] [] [] [] [] [] [] |
|
||||
flex | [] [] [] [] |
|
||||
fslint | |
|
||||
gas | [] |
|
||||
gawk | [] [] [] [] |
|
||||
gbiff | [] |
|
||||
gcal | [] |
|
||||
gcc | [] [] |
|
||||
gettext | [] [] [] [] [] |
|
||||
gettext-examples | [] [] [] |
|
||||
gettext-runtime | [] [] [] [] [] |
|
||||
gettext-tools | [] [] [] |
|
||||
gimp-print | [] [] [] [] [] |
|
||||
gliv | |
|
||||
glunarclock | [] [] [] |
|
||||
gnubiff | [] |
|
||||
gnucash | [] () [] [] |
|
||||
gnucash-glossary | [] () [] |
|
||||
gnupg | [] () [] [] [] [] |
|
||||
gpe-aerial | [] |
|
||||
gpe-beam | [] [] |
|
||||
gpe-calendar | [] [] |
|
||||
gpe-clock | [] [] |
|
||||
gpe-conf | [] [] |
|
||||
gpe-contacts | [] [] |
|
||||
gpe-edit | [] |
|
||||
gpe-go | [] |
|
||||
gpe-login | [] [] |
|
||||
gpe-ownerinfo | [] [] |
|
||||
gpe-sketchbook | [] [] |
|
||||
gpe-su | [] [] |
|
||||
gpe-taskmanager | [] [] |
|
||||
gpe-timesheet | [] |
|
||||
gpe-today | [] [] |
|
||||
gpe-todo | [] [] |
|
||||
gphoto2 | [] [] [] [] |
|
||||
gprof | [] [] [] |
|
||||
gpsdrive | () () () |
|
||||
gramadoir | [] |
|
||||
grep | [] [] [] [] [] [] |
|
||||
gretl | [] |
|
||||
gtick | () |
|
||||
hello | [] [] [] [] [] [] |
|
||||
id-utils | [] [] |
|
||||
indent | [] [] [] [] |
|
||||
jpilot | [] [] [] |
|
||||
jtag | |
|
||||
jwhois | [] |
|
||||
kbd | [] [] [] [] [] |
|
||||
latrine | () |
|
||||
ld | [] [] |
|
||||
libc | [] [] [] [] [] [] |
|
||||
libgpewidget | [] [] |
|
||||
libiconv | [] [] [] [] [] |
|
||||
lifelines | [] () |
|
||||
lilypond | [] |
|
||||
lingoteach | |
|
||||
lingoteach_lessons | () () |
|
||||
lynx | [] [] [] [] |
|
||||
m4 | [] [] [] [] |
|
||||
mailutils | [] [] |
|
||||
make | [] [] [] |
|
||||
man-db | [] () [] [] () |
|
||||
minicom | [] [] [] |
|
||||
mysecretdiary | [] [] [] |
|
||||
nano | [] () [] [] [] |
|
||||
nano_1_0 | [] () [] [] [] |
|
||||
opcodes | [] |
|
||||
parted | [] [] [] [] [] |
|
||||
ptx | [] [] [] [] [] |
|
||||
python | |
|
||||
radius | |
|
||||
recode | [] [] [] [] [] [] [] |
|
||||
screem | |
|
||||
scrollkeeper | [] [] [] [] [] [] |
|
||||
sed | [] [] [] [] [] |
|
||||
sh-utils | [] [] [] |
|
||||
shared-mime-info | |
|
||||
sharutils | [] [] [] [] [] [] |
|
||||
sketch | [] () [] |
|
||||
soundtracker | [] [] [] |
|
||||
sp | [] |
|
||||
tar | [] [] [] [] |
|
||||
texinfo | [] [] [] |
|
||||
textutils | [] [] [] [] |
|
||||
tin | () () |
|
||||
tuxpaint | [] [] [] [] [] [] [] |
|
||||
util-linux | [] [] [] [] [] |
|
||||
vorbis-tools | [] [] [] [] |
|
||||
wastesedge | () |
|
||||
wdiff | [] [] [] [] |
|
||||
wget | [] [] [] [] [] [] |
|
||||
xchat | [] [] [] [] |
|
||||
xfree86_xkb_xml | [] |
|
||||
xpad | [] |
|
||||
+-------------------------------------------+
|
||||
am az be bg ca cs da de el en en_GB eo es
|
||||
0 1 8 3 37 37 54 73 15 1 5 12 62
|
||||
|
||||
et fa fi fr ga gl he hr hu id is it ja
|
||||
+----------------------------------------+
|
||||
a2ps | [] [] [] () |
|
||||
aegis | |
|
||||
ant-phone | |
|
||||
anubis | [] |
|
||||
ap-utils | [] |
|
||||
bash | [] [] |
|
||||
batchelor | [] |
|
||||
bfd | [] |
|
||||
binutils | [] [] |
|
||||
bison | [] [] [] [] |
|
||||
bluez-pin | [] [] [] [] [] |
|
||||
clisp | [] |
|
||||
clisp | |
|
||||
coreutils | [] [] [] [] [] [] |
|
||||
cpio | [] [] [] |
|
||||
darkstat | () [] [] [] |
|
||||
diffutils | [] [] [] [] [] [] [] |
|
||||
e2fsprogs | |
|
||||
enscript | [] [] |
|
||||
error | [] [] [] [] |
|
||||
fetchmail | [] |
|
||||
fileutils | [] [] [] [] [] [] |
|
||||
findutils | [] [] [] [] [] [] [] [] [] [] |
|
||||
flex | [] [] |
|
||||
fslint | |
|
||||
gas | [] |
|
||||
gawk | [] [] [] |
|
||||
gbiff | |
|
||||
gcal | [] |
|
||||
gcc | [] |
|
||||
gettext | [] [] |
|
||||
gettext-examples | [] [] |
|
||||
gettext-runtime | [] [] [] [] |
|
||||
gettext-tools | [] [] |
|
||||
gimp-print | [] [] |
|
||||
gliv | () |
|
||||
glunarclock | [] [] [] [] [] |
|
||||
gnubiff | |
|
||||
gnucash | () [] |
|
||||
gnucash-glossary | [] |
|
||||
gnupg | [] [] [] [] [] [] [] |
|
||||
gpe-aerial | [] |
|
||||
gpe-beam | [] |
|
||||
gpe-calendar | [] [] [] |
|
||||
gpe-clock | [] |
|
||||
gpe-conf | [] |
|
||||
gpe-contacts | [] [] |
|
||||
gpe-edit | [] [] |
|
||||
gpe-go | [] |
|
||||
gpe-login | [] [] |
|
||||
gpe-ownerinfo | [] [] [] |
|
||||
gpe-sketchbook | [] |
|
||||
gpe-su | [] |
|
||||
gpe-taskmanager | [] |
|
||||
gpe-timesheet | [] [] [] |
|
||||
gpe-today | [] [] |
|
||||
gpe-todo | [] [] |
|
||||
gphoto2 | [] [] [] |
|
||||
gprof | [] [] |
|
||||
gpsdrive | () [] () () |
|
||||
gramadoir | [] |
|
||||
grep | [] [] [] [] [] [] [] [] [] [] [] |
|
||||
gretl | [] |
|
||||
gtick | [] [] |
|
||||
hello | [] [] [] [] [] [] [] [] [] [] [] [] |
|
||||
id-utils | [] [] [] [] |
|
||||
indent | [] [] [] [] [] [] [] [] [] |
|
||||
jpilot | [] () |
|
||||
jtag | |
|
||||
jwhois | [] [] [] [] |
|
||||
kbd | [] |
|
||||
latrine | |
|
||||
ld | [] |
|
||||
libc | [] [] [] [] [] |
|
||||
libgpewidget | [] [] [] [] |
|
||||
libiconv | [] [] [] [] [] [] [] [] [] |
|
||||
lifelines | () |
|
||||
lilypond | [] |
|
||||
lingoteach | [] [] |
|
||||
lingoteach_lessons | |
|
||||
lynx | [] [] [] [] |
|
||||
m4 | [] [] [] [] |
|
||||
mailutils | |
|
||||
make | [] [] [] [] [] |
|
||||
man-db | () () |
|
||||
minicom | [] [] [] [] |
|
||||
mysecretdiary | [] [] |
|
||||
nano | [] [] [] [] |
|
||||
nano_1_0 | [] [] [] [] |
|
||||
opcodes | [] |
|
||||
parted | [] [] [] |
|
||||
ptx | [] [] [] [] [] [] [] |
|
||||
python | |
|
||||
radius | |
|
||||
recode | [] [] [] [] [] [] |
|
||||
screem | |
|
||||
scrollkeeper | [] |
|
||||
sed | [] [] [] [] [] [] [] [] [] |
|
||||
sh-utils | [] [] [] [] [] [] [] |
|
||||
shared-mime-info | [] |
|
||||
sharutils | [] [] [] [] [] |
|
||||
sketch | [] |
|
||||
soundtracker | [] [] [] [] |
|
||||
sp | [] () |
|
||||
tar | [] [] [] [] [] [] [] [] [] |
|
||||
texinfo | [] [] [] [] |
|
||||
textutils | [] [] [] [] [] |
|
||||
tin | [] () |
|
||||
tuxpaint | [] [] [] [] [] [] [] [] |
|
||||
util-linux | [] [] [] [] () [] |
|
||||
vorbis-tools | [] |
|
||||
wastesedge | () |
|
||||
wdiff | [] [] [] [] [] [] |
|
||||
wget | [] [] [] [] [] [] [] |
|
||||
xchat | [] [] [] |
|
||||
xfree86_xkb_xml | |
|
||||
xpad | [] |
|
||||
+----------------------------------------+
|
||||
et fa fi fr ga gl he hr hu id is it ja
|
||||
21 1 24 84 24 24 8 10 38 31 1 22 33
|
||||
|
||||
ko lg lt lv ms nb nl nn no pl pt pt_BR ro
|
||||
+-------------------------------------------+
|
||||
a2ps | () [] [] () () [] [] |
|
||||
aegis | () () |
|
||||
ant-phone | [] [] |
|
||||
anubis | [] [] [] [] [] |
|
||||
ap-utils | [] () [] |
|
||||
bash | [] [] |
|
||||
batchelor | [] |
|
||||
bfd | [] |
|
||||
binutils | |
|
||||
bison | [] [] [] [] |
|
||||
bluez-pin | [] [] [] |
|
||||
clisp | [] |
|
||||
clisp | |
|
||||
coreutils | [] |
|
||||
cpio | [] [] [] [] [] |
|
||||
darkstat | [] [] [] [] |
|
||||
diffutils | [] [] [] [] |
|
||||
e2fsprogs | [] |
|
||||
enscript | [] [] [] |
|
||||
error | [] [] [] |
|
||||
fetchmail | [] [] () |
|
||||
fileutils | [] |
|
||||
findutils | [] [] [] [] [] |
|
||||
flex | [] [] [] [] |
|
||||
fslint | [] [] |
|
||||
gas | |
|
||||
gawk | [] [] [] |
|
||||
gbiff | [] [] |
|
||||
gcal | |
|
||||
gcc | |
|
||||
gettext | [] [] [] |
|
||||
gettext-examples | [] [] |
|
||||
gettext-runtime | [] [] [] |
|
||||
gettext-tools | [] [] [] |
|
||||
gimp-print | [] |
|
||||
gliv | [] [] [] |
|
||||
glunarclock | [] [] [] |
|
||||
gnubiff | |
|
||||
gnucash | [] [] () |
|
||||
gnucash-glossary | [] [] |
|
||||
gnupg | [] |
|
||||
gpe-aerial | [] [] [] |
|
||||
gpe-beam | [] [] [] |
|
||||
gpe-calendar | [] [] [] |
|
||||
gpe-clock | [] [] [] |
|
||||
gpe-conf | [] [] [] |
|
||||
gpe-contacts | [] [] [] |
|
||||
gpe-edit | [] [] [] |
|
||||
gpe-go | [] [] |
|
||||
gpe-login | [] [] [] |
|
||||
gpe-ownerinfo | [] [] [] |
|
||||
gpe-sketchbook | [] [] [] |
|
||||
gpe-su | [] [] [] |
|
||||
gpe-taskmanager | [] [] [] |
|
||||
gpe-timesheet | [] [] [] |
|
||||
gpe-today | [] [] [] |
|
||||
gpe-todo | [] [] [] |
|
||||
gphoto2 | [] |
|
||||
gprof | [] [] |
|
||||
gpsdrive | () () () [] |
|
||||
gramadoir | [] |
|
||||
grep | [] [] [] [] |
|
||||
gretl | |
|
||||
gtick | [] [] |
|
||||
hello | [] [] [] [] [] [] [] [] [] [] |
|
||||
id-utils | [] [] [] |
|
||||
indent | [] [] [] |
|
||||
jpilot | () () |
|
||||
jtag | |
|
||||
jwhois | [] [] [] [] |
|
||||
kbd | [] [] [] |
|
||||
latrine | [] |
|
||||
ld | |
|
||||
libc | [] [] [] [] [] |
|
||||
libgpewidget | [] [] [] |
|
||||
libiconv | [] [] [] [] |
|
||||
lifelines | |
|
||||
lilypond | |
|
||||
lingoteach | |
|
||||
lingoteach_lessons | |
|
||||
lynx | [] [] |
|
||||
m4 | [] [] [] [] |
|
||||
mailutils | [] |
|
||||
make | [] [] [] [] |
|
||||
man-db | [] |
|
||||
minicom | [] [] [] |
|
||||
mysecretdiary | [] [] [] |
|
||||
nano | [] [] [] [] |
|
||||
nano_1_0 | [] [] [] [] [] |
|
||||
opcodes | [] [] |
|
||||
parted | [] [] [] [] |
|
||||
ptx | [] [] [] [] [] [] [] |
|
||||
python | |
|
||||
radius | [] |
|
||||
recode | [] [] [] |
|
||||
screem | |
|
||||
scrollkeeper | [] [] [] [] |
|
||||
sed | [] [] [] |
|
||||
sh-utils | [] |
|
||||
shared-mime-info | [] |
|
||||
sharutils | [] |
|
||||
sketch | [] [] |
|
||||
soundtracker | |
|
||||
sp | |
|
||||
tar | [] [] [] [] [] [] |
|
||||
texinfo | [] [] [] |
|
||||
textutils | [] [] |
|
||||
tin | |
|
||||
tuxpaint | [] [] [] [] [] [] [] [] [] |
|
||||
util-linux | [] [] |
|
||||
vorbis-tools | [] [] |
|
||||
wastesedge | |
|
||||
wdiff | [] [] [] [] |
|
||||
wget | [] [] |
|
||||
xchat | [] [] |
|
||||
xfree86_xkb_xml | [] |
|
||||
xpad | [] [] |
|
||||
+-------------------------------------------+
|
||||
ko lg lt lv ms nb nl nn no pl pt pt_BR ro
|
||||
11 0 1 2 12 10 60 4 4 38 23 34 74
|
||||
|
||||
ru sk sl sr sv ta tr uk vi wa zh_CN zh_TW
|
||||
+-------------------------------------------+
|
||||
a2ps | [] [] [] [] [] | 16
|
||||
aegis | () | 0
|
||||
ant-phone | | 2
|
||||
anubis | [] [] [] | 9
|
||||
ap-utils | () | 3
|
||||
bash | [] | 9
|
||||
batchelor | | 2
|
||||
bfd | [] [] | 6
|
||||
binutils | [] [] [] | 7
|
||||
bison | [] [] [] | 14
|
||||
bluez-pin | [] [] [] | 13
|
||||
clisp | | 5
|
||||
clisp | | 0
|
||||
coreutils | [] [] [] [] [] | 16
|
||||
cpio | [] [] [] | 14
|
||||
darkstat | [] [] [] () () | 12
|
||||
diffutils | [] [] [] [] | 22
|
||||
e2fsprogs | [] [] | 5
|
||||
enscript | [] [] [] | 12
|
||||
error | [] [] [] | 15
|
||||
fetchmail | [] [] [] | 11
|
||||
fileutils | [] [] [] [] [] [] | 16
|
||||
findutils | [] [] [] [] [] [] [] | 29
|
||||
flex | [] [] [] | 13
|
||||
fslint | | 2
|
||||
gas | [] | 3
|
||||
gawk | [] [] | 12
|
||||
gbiff | | 3
|
||||
gcal | [] [] | 4
|
||||
gcc | [] | 4
|
||||
gettext | [] [] [] [] [] [] | 16
|
||||
gettext-examples | [] [] | 9
|
||||
gettext-runtime | [] [] [] [] [] [] [] [] [] | 21
|
||||
gettext-tools | [] [] [] [] [] [] | 14
|
||||
gimp-print | [] [] | 10
|
||||
gliv | | 3
|
||||
glunarclock | [] [] [] [] | 15
|
||||
gnubiff | | 1
|
||||
gnucash | [] [] [] | 9
|
||||
gnucash-glossary | [] [] [] | 8
|
||||
gnupg | [] [] [] [] | 17
|
||||
gpe-aerial | [] [] | 7
|
||||
gpe-beam | [] [] | 8
|
||||
gpe-calendar | [] [] [] [] [] | 13
|
||||
gpe-clock | [] [] [] | 9
|
||||
gpe-conf | [] [] [] | 9
|
||||
gpe-contacts | [] [] [] [] | 11
|
||||
gpe-edit | [] [] [] [] [] | 11
|
||||
gpe-go | [] | 5
|
||||
gpe-login | [] [] [] [] [] | 12
|
||||
gpe-ownerinfo | [] [] [] [] | 12
|
||||
gpe-sketchbook | [] [] [] | 9
|
||||
gpe-su | [] [] [] | 9
|
||||
gpe-taskmanager | [] [] [] | 9
|
||||
gpe-timesheet | [] [] [] [] | 11
|
||||
gpe-today | [] [] [] [] [] | 12
|
||||
gpe-todo | [] [] [] [] [] | 12
|
||||
gphoto2 | [] [] [] | 11
|
||||
gprof | [] [] | 9
|
||||
gpsdrive | [] [] | 4
|
||||
gramadoir | | 3
|
||||
grep | [] [] [] [] [] | 26
|
||||
gretl | | 2
|
||||
gtick | [] | 5
|
||||
hello | [] [] [] [] [] | 33
|
||||
id-utils | [] [] [] | 12
|
||||
indent | [] [] [] [] [] | 21
|
||||
jpilot | [] [] [] [] [] | 9
|
||||
jtag | [] | 1
|
||||
jwhois | () () [] [] | 11
|
||||
kbd | [] [] | 11
|
||||
latrine | | 1
|
||||
ld | [] [] | 5
|
||||
libc | [] [] [] [] | 20
|
||||
libgpewidget | [] [] [] | 12
|
||||
libiconv | [] [] [] [] [] [] [] [] [] | 27
|
||||
lifelines | [] | 2
|
||||
lilypond | [] | 3
|
||||
lingoteach | | 2
|
||||
lingoteach_lessons | () | 0
|
||||
lynx | [] [] [] [] | 14
|
||||
m4 | [] [] [] | 15
|
||||
mailutils | [] | 4
|
||||
make | [] [] [] [] | 16
|
||||
man-db | [] | 5
|
||||
minicom | [] | 11
|
||||
mysecretdiary | [] [] | 10
|
||||
nano | [] [] [] [] [] | 17
|
||||
nano_1_0 | [] [] [] [] | 17
|
||||
opcodes | [] [] | 6
|
||||
parted | [] [] [] | 15
|
||||
ptx | [] [] [] | 22
|
||||
python | | 0
|
||||
radius | [] | 2
|
||||
recode | [] [] [] [] | 20
|
||||
screem | [] [] | 2
|
||||
scrollkeeper | [] [] [] [] | 15
|
||||
sed | [] [] [] [] [] [] | 23
|
||||
sh-utils | [] [] [] | 14
|
||||
shared-mime-info | [] [] | 4
|
||||
sharutils | [] [] [] [] [] | 17
|
||||
sketch | [] | 6
|
||||
soundtracker | [] [] | 9
|
||||
sp | [] | 3
|
||||
tar | [] [] [] [] [] | 24
|
||||
texinfo | [] [] [] [] | 14
|
||||
textutils | [] [] [] [] [] | 16
|
||||
tin | | 1
|
||||
tuxpaint | [] [] [] [] [] | 29
|
||||
util-linux | [] [] [] | 15
|
||||
vorbis-tools | [] | 8
|
||||
wastesedge | | 0
|
||||
wdiff | [] [] [] [] | 18
|
||||
wget | [] [] [] [] [] [] [] [] | 23
|
||||
xchat | [] [] [] [] [] | 14
|
||||
xfree86_xkb_xml | [] [] [] [] | 6
|
||||
xpad | | 4
|
||||
+-------------------------------------------+
|
||||
51 teams ru sk sl sr sv ta tr uk vi wa zh_CN zh_TW
|
||||
117 domains 58 41 16 16 78 0 53 12 1 10 21 22 1230
|
||||
|
||||
Some counters in the preceding matrix are higher than the number of
|
||||
visible blocks let us expect. This is because a few extra PO files are
|
||||
used for implementing regional variants of languages, or language
|
||||
dialects.
|
||||
|
||||
For a PO file in the matrix above to be effective, the package to
|
||||
which it applies should also have been internationalized and
|
||||
distributed as such by its maintainer. There might be an observable
|
||||
lag between the mere existence a PO file and its wide availability in a
|
||||
distribution.
|
||||
|
||||
If November 2003 seems to be old, you may fetch a more recent copy
|
||||
of this `ABOUT-NLS' file on most GNU archive sites. The most
|
||||
up-to-date matrix with full percentage details can be found at
|
||||
`http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'.
|
||||
|
||||
Using `gettext' in new packages
|
||||
===============================
|
||||
|
||||
If you are writing a freely available program and want to
|
||||
internationalize it you are welcome to use GNU `gettext' in your
|
||||
package. Of course you have to respect the GNU Library General Public
|
||||
License which covers the use of the GNU `gettext' library. This means
|
||||
in particular that even non-free programs can use `libintl' as a shared
|
||||
library, whereas only free software can use `libintl' as a static
|
||||
library or use modified versions of `libintl'.
|
||||
|
||||
Once the sources are changed appropriately and the setup can handle
|
||||
the use of `gettext' the only thing missing are the translations. The
|
||||
Free Translation Project is also available for packages which are not
|
||||
developed inside the GNU project. Therefore the information given above
|
||||
applies also for every other Free Software Project. Contact
|
||||
`[email protected]' to make the `.pot' files available to
|
||||
the translation teams.
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
Authors of GNU cpio
|
||||
|
||||
Phil Nelson <[email protected]>
|
||||
David MacKenzie <[email protected]>
|
||||
John Oleynick <[email protected]>
|
||||
Sergey Poznyakoff <[email protected]>
|
||||
@@ -1,231 +0,0 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. (Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.)
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You only need
|
||||
`configure.ac' if you want to change it or regenerate `configure' using
|
||||
a newer version of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
|
||||
Running `configure' takes awhile. While running, it prints some
|
||||
messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that the
|
||||
`configure' script does not know about. Run `./configure --help' for
|
||||
details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you must use a version of `make' that
|
||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
If you have to use a `make' that does not support the `VPATH'
|
||||
variable, you have to compile the package for one architecture at a
|
||||
time in the source code directory. After you have installed the
|
||||
package for one architecture, use `make distclean' before reconfiguring
|
||||
for another architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' will install the package's files in
|
||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
||||
installation prefix other than `/usr/local' by giving `configure' the
|
||||
option `--prefix=PREFIX'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
give `configure' the option `--exec-prefix=PREFIX', the package will
|
||||
use PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files will still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out automatically,
|
||||
but needs to determine by the type of machine the package will run on.
|
||||
Usually, assuming the package is built to be run on the _same_
|
||||
architectures, `configure' can figure that out, but if it prints a
|
||||
message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the `--target=TYPE' option to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share, you
|
||||
can create a site shell script called `config.site' that gives default
|
||||
values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
will cause the specified gcc to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
GNU cpio THANKS file
|
||||
|
||||
GNU cpio has originally been written by Phil Nelson <[email protected]>
|
||||
and David MacKenzie <[email protected]>. It was further modified
|
||||
by John Oleynick <[email protected]> and Sergey Poznyakoff <[email protected]>
|
||||
who currently maintains it.
|
||||
|
||||
The following is a list of people who contributed to GNU cpio by
|
||||
reporting problems, suggesting various improvements or submitting actual
|
||||
code. Help us keep it complete and exempt of errors.
|
||||
|
||||
Matthew Braithwaite <[email protected]>
|
||||
Mitsuru Chinen <[email protected]>
|
||||
Holger Fleischmann <[email protected]>
|
||||
@@ -1,356 +0,0 @@
|
||||
Following is the list of cpio-related reports to bug-gnu-utils.
|
||||
Many of them appear to be fixed, but quite a number of them is
|
||||
probably still waiting for being handled. The list is sorted
|
||||
in reverse chronological order.
|
||||
|
||||
4. copyin.c cpio probably questions/rfc (score: 35)
|
||||
Author: Grzegorz Jaskiewicz <[email protected]>
|
||||
Date: Tue, 24 Jun 2003 17:12:45 +0100
|
||||
Hi! I am currently working on module that (in GNU software)
|
||||
will be able to read/write cpio format (only ascii). Thus i am
|
||||
separating some of cpio structures into libcpio. I've been
|
||||
going through cop
|
||||
/archive/html/bug-gnu-utils/2003-06/msg00422.html (5,430 bytes)
|
||||
|
||||
5. RE: Problem when building on HP-UX 11i(11.11) (score: 4)
|
||||
Author: "Leon Strydom" <[email protected]>
|
||||
Date: Thu, 13 Mar 2003 09:10:02 +0200
|
||||
Hi Bob, I got it to compile, thanks. The reason why I had to
|
||||
try GNU-Tar is because of the 2GB file size limit problems:
|
||||
Here are the errors I got: With TAR(hp-ux 11i tar): CMD: tar
|
||||
cvf backup.tar /a
|
||||
/archive/html/bug-gnu-utils/2003-03/msg00106.html (5,191 bytes)
|
||||
|
||||
6. cpio - large file support (score: 35)
|
||||
Author: "Keith Ansell" <[email protected]>
|
||||
Date: Tue, 4 Mar 2003 16:24:37 -0000
|
||||
Can you help. I need to archive a large database, this will
|
||||
create a cpio file greater than 2 Gigabytes. Have you added
|
||||
large file support to the build of cpio. Regards Keith
|
||||
Ansell.....
|
||||
/archive/html/bug-gnu-utils/2003-03/msg00024.html (4,329 bytes)
|
||||
|
||||
7. cpio-2.5 typos (score: 36)
|
||||
Author: Thomas Klausner <[email protected]>
|
||||
Date: Sat, 21 Dec 2002 23:53:38 +0100
|
||||
In cpio-2.5, in cpio.texi (and thus cpio.1) and main.c the word
|
||||
'compatibility' is misspelled as 'compatability'. Please fix,
|
||||
thanks. Thomas -- Thomas Klausner - [email protected] What
|
||||
is wanted
|
||||
/archive/html/bug-gnu-utils/2002-12/msg00200.html (3,783 bytes)
|
||||
|
||||
9. Re: bug in cpio with tapechange in copy-in-mode (score: 46)
|
||||
Author: Paul Eggert <[email protected]>
|
||||
Date: Mon, 5 Aug 2002 12:28:33 -0700 (PDT)
|
||||
Thanks for your bug report. Can you please verify that the bug
|
||||
still exists in the latest CPIO version
|
||||
<ftp://ftp.gnu.org/gnu/cpio/cpio-2.5.tar.gz>, and if so, please
|
||||
send a patch to <bug-cpio@bogus.
|
||||
/archive/html/bug-gnu-utils/2002-08/msg00127.html (4,275 bytes)
|
||||
|
||||
10. bug in cpio with tapechange in copy-in-mode (score: 34)
|
||||
Author: Bernd =?ISO-8859-1?Q?Sch=FCler?=
|
||||
<[email protected]>
|
||||
Date: 05 Aug 2002 18:37:56 +0200
|
||||
Hello, last i made a restore from tape, and no request for next
|
||||
tape happend, only an read-error occured. Here is an quick
|
||||
patch, please verify the problem and the patch-code. I'm not
|
||||
sure, if the pr
|
||||
/archive/html/bug-gnu-utils/2002-08/msg00122.html (4,518 bytes)
|
||||
|
||||
11. Re: CPIO Bug ? (score: 36)
|
||||
Author: Albert Chin <[email protected]>
|
||||
Date: Thu, 4 Jul 2002 19:31:04 -0500
|
||||
I think the default CPIO format understands only 16-bit inodes.
|
||||
Look at the -H option. '-H newc' should work better for you. --
|
||||
albert chin ([email protected])
|
||||
/archive/html/bug-gnu-utils/2002-07/msg00091.html (4,286 bytes)
|
||||
|
||||
14. Re: bug in cpio? (score: 40)
|
||||
Author: [email protected] (Stepan Kasal)
|
||||
Date: Thu, 13 Jun 2002 07:44:14 +0000 (UTC)
|
||||
Hallo, the following option should help: -d, --make-directories
|
||||
Create leading directories where needed. Details: cpio won't
|
||||
create the directory for the file. Observe: kasal$ echo
|
||||
/home/kasal/tmp/db
|
||||
/archive/html/bug-gnu-utils/2002-06/msg00306.html (4,862 bytes)
|
||||
|
||||
15. bug in cpio? (score: 34)
|
||||
Author: "Jeff Holt" <[email protected]>
|
||||
Date: Wed, 12 Jun 2002 14:07:59 -0500
|
||||
According to the man page, I should be able to extract an
|
||||
absolute pathname from an archive and have the file created
|
||||
relative to the current directory (by removing the leading
|
||||
‘/’).<o:p>
|
||||
/archive/html/bug-gnu-utils/2002-06/msg00296.html (5,331 bytes)
|
||||
|
||||
16. CPIO Bug ? (score: 35)
|
||||
Author: =?iso-8859-1?Q?Gr=E9goire_Fiot?=
|
||||
<[email protected]>
|
||||
Date: Tue, 14 May 2002 17:01:18 +0200
|
||||
Hello, We ve got a problem here using cpio: many "troncating
|
||||
inode number" appear during the process: cpio -ocv Is that a
|
||||
real problem? Does it corrupt files? Well.. what does that
|
||||
mean? We have look
|
||||
/archive/html/bug-gnu-utils/2002-05/msg00333.html (3,855 bytes)
|
||||
|
||||
23. [cpio texinfo] typo (score: 2)
|
||||
Author: fabrice bauzac <[email protected]>
|
||||
Date: Tue, 7 May 2002 16:37:28 +0200
|
||||
Good afternoon, There is a typo in the Texinfo documentation of
|
||||
GNU cpio, node "Copy-in mode": [--format=format]
|
||||
[--owner=[user][:.][group]] [--no- preserve-owner]
|
||||
[--message=message] [--help] [--ver
|
||||
/archive/html/bug-gnu-utils/2002-05/msg00153.html (4,040 bytes)
|
||||
|
||||
26. cpio: memory exhausted (score: 43)
|
||||
Author: Thomas McLaughlin <[email protected]>
|
||||
Date: Thu, 18 Apr 2002 09:51:18 +0100
|
||||
This is probably not the place for my query, but I have
|
||||
exhausted other avenues and would be glad of some help. I can't
|
||||
work out what's going on with my nightly cpio backup. If I do:
|
||||
cd / find . -pri
|
||||
/archive/html/bug-gnu-utils/2002-04/msg00406.html (4,988 bytes)
|
||||
|
||||
30. cpio 2.4.2 bug? (score: 40)
|
||||
Author: "H.J. Thomassen" <[email protected]>
|
||||
Date: Thu, 10 Jan 2002 18:09:10 +0100 (CET)
|
||||
Hello, We use GNU-cpio 2.4.2 and have the following problem:
|
||||
Short: Assume I have a directory with two filenames, which are
|
||||
hardlinks to the same i-node. I make a crc-cpio archive with
|
||||
both files; th
|
||||
/archive/html/bug-gnu-utils/2002-01/msg00161.html (5,624 bytes)
|
||||
|
||||
32. GNU cpio suggestion (score: 42)
|
||||
Author: "H.J.Thomassen" <[email protected]>
|
||||
Date: Mon, 17 Dec 2001 11:27:11 +0100
|
||||
Re: suggestion for GNU-cpio extension (plus reference
|
||||
implementation) We use cpio for our backup purposes. The backup
|
||||
is started automatically in the middle of the night. To chase
|
||||
away all users we d
|
||||
/archive/html/bug-gnu-utils/2001-12/msg00244.html (7,474 bytes)
|
||||
|
||||
35. GNU cpio compile problem (score: 34)
|
||||
Author: Daniel Savard <[email protected]>
|
||||
Date: Wed, 14 Nov 2001 12:43:11 -0500
|
||||
Hi, I am trying to make the GNU cpio utility (version 2.4.2)
|
||||
using the gcc 3.0.2 compiler. The make failed on the userspec.c
|
||||
file compilation. I then tried to compile with gcc 2.95.3 with
|
||||
the followi
|
||||
/archive/html/bug-gnu-utils/2001-11/msg00180.html (5,518 bytes)
|
||||
|
||||
36. cpio -d bug (fwd) (score: 47)
|
||||
Author: Christian Smith <[email protected]>
|
||||
Date: Wed, 14 Nov 2001 02:06:46 +0000 (GMT)
|
||||
This was bounced from [email protected] I guess that
|
||||
isn't set up yet. -- /"\ \ / ASCII RIBBON CAMPAIGN - AGAINST
|
||||
HTML MAIL X - AGAINST MS ATTACHMENTS / \ $ cpio --version GNU
|
||||
cpio version 2
|
||||
/archive/html/bug-gnu-utils/2001-11/msg00170.html (4,548 bytes)
|
||||
|
||||
38. [cpio] man page enhancement: a Example section ? (score: 5)
|
||||
Author: Yannick Patois <[email protected]>
|
||||
Date: Wed, 24 Oct 2001 12:48:33 +0200 (CEST)
|
||||
Hello, I seldom use cpio (as I think many people) and only had
|
||||
to use it once or twice. IMHA, would be good to have a small
|
||||
section with an example of most often performed actions
|
||||
(creating an archiv
|
||||
/archive/html/bug-gnu-utils/2001-10/msg00270.html (4,336 bytes)
|
||||
|
||||
39. Patch to cpio to enable verbose *skipping* of files (score: 40)
|
||||
Author: Tomas Pospisek <[email protected]>
|
||||
Date: Mon, 8 Oct 2001 13:54:14 +0200 (CEST)
|
||||
This patch enables cpio to be verbose about the files that it
|
||||
does not copy, which is very handy for seeing cpio's progress
|
||||
through a tape or simply for debuging. The patch along with a
|
||||
Debian packag
|
||||
/archive/html/bug-gnu-utils/2001-10/msg00083.html (4,548 bytes)
|
||||
|
||||
40. cpio-2.4.2 patch (score: 39)
|
||||
Author: Alex Efros <[email protected]>
|
||||
Date: Wed, 29 Aug 2001 07:36:31 +0300 (EEST)
|
||||
Hi. Linux-2.4.9, GCC-3.0, GLIBC-2.2.4, cpio-2.4.2. Compile-time
|
||||
errors: --cut-- gcc -c -DRETSIGTYPE=void -DHAVE_SYS_MTIO_H=1
|
||||
-DHAVE_NETDB_H=1 -DSTDC_HEADERS=1 -DHAVE_UNISTD_H=1
|
||||
-DHAVE_STRING_H=1 -DHA
|
||||
/archive/html/bug-gnu-utils/2001-08/msg00264.html (5,259 bytes)
|
||||
|
||||
41. cpio copy-in and multiply-linked files (score: 35)
|
||||
Author: Chris Jaeger <[email protected]>
|
||||
Date: Tue, 07 Aug 2001 23:46:04 -0700
|
||||
Hi, I was wondering whether it was a bug or a feature that GNU
|
||||
cpio, while in copy-in mode, will create a multiply-linked set
|
||||
of files all of size 0 if the last linked file is not copied in
|
||||
due to th
|
||||
/archive/html/bug-gnu-utils/2001-08/msg00074.html (4,142 bytes)
|
||||
|
||||
42. Re: minor problems with slackware-current (score: 7)
|
||||
Author: Cezary Sliwa <[email protected]>
|
||||
Date: Wed, 1 Aug 2001 10:43:37 +0200
|
||||
"cpio --sparse" corrupts data. A fix attached. C.S. Attachment:
|
||||
cpio-2.4.2-sparse.diff Description: Text document
|
||||
/archive/html/bug-gnu-utils/2001-08/msg00000.html (3,989 bytes)
|
||||
|
||||
43. (no subject) (score: 2)
|
||||
Author: [email protected] (Brian Mays)
|
||||
Date: Sat, 07 Jul 2001 16:35:13 -0400
|
||||
When hard-linked files (along with many other files) are
|
||||
archived to a cpio ustar format archive, the files are _not_
|
||||
all archived as hard links to each other in the archive. When
|
||||
the same set of fil
|
||||
/archive/html/bug-gnu-utils/2001-07/msg00080.html (5,666 bytes)
|
||||
|
||||
44. gnu cpio and files over 2G (score: 37)
|
||||
Author: [email protected]
|
||||
Date: Wed, 2 May 2001 06:28:18 +0100
|
||||
As an increasing number of opertaing systems now support files
|
||||
over 2G I took a look at the cpio (2.4.2) source to see how
|
||||
hard it would be to make it cope, and was slightly shocked at
|
||||
the number of
|
||||
/archive/html/bug-gnu-utils/2001-05/msg00010.html (4,802 bytes)
|
||||
|
||||
45. cpio suggestion + patch (score: 38)
|
||||
Author: Taylor Gautier <[email protected]>
|
||||
Date: Fri, 20 Apr 2001 09:40:05 -0700
|
||||
I have a suggestion for cpio. The suggestion is to make it copy
|
||||
files into a temporary name and then rename the file as the
|
||||
last operation. Since UNIX filesystems are supposed to
|
||||
gaurantee atomicity
|
||||
/archive/html/bug-gnu-utils/2001-04/msg00169.html (10,674
|
||||
bytes)
|
||||
|
||||
46. [cpio 2.4.2] rmt build fails (score: 8)
|
||||
Author: Gert <[email protected]>
|
||||
Date: Thu, 29 Mar 2001 21:28:52 +0200 (CEST)
|
||||
Hi, The cpio 2.4.2 rmt tool fails to build on my system. I run
|
||||
the following software: - Linux 2.4.2 - GCC 2.95.2 - GNU Make
|
||||
3.79.1 - GNU ld 2.10 (with BFD 2.10) - glibc 2.1.3 The build
|
||||
fails like th
|
||||
/archive/html/bug-gnu-utils/2001-03/msg00262.html (5,498 bytes)
|
||||
|
||||
47. cpio --sparse (score: 34)
|
||||
Author: Cezary Sliwa <[email protected]>
|
||||
Date: Mon, 26 Mar 2001 10:43:34 +0200 (CEST)
|
||||
the '--sparse' option of gnu cpio causes data corruption
|
||||
(blocks of zeros are lost or appended to other files). C.S.
|
||||
/archive/html/bug-gnu-utils/2001-03/msg00235.html (3,671 bytes)
|
||||
|
||||
49. Re: bug with gnu cpio 2.4.2 (score: 38)
|
||||
Author: Hans-Bernhard Broeker <[email protected]>
|
||||
Date: 6 Mar 2001 15:19:34 GMT
|
||||
This would happen if cpio want to do any user interaction (ask
|
||||
for the next tape cartridge, because the current one is full,
|
||||
e.g.). Cron jobs don't have access to a terminal (/dev/tty), so
|
||||
this will
|
||||
/archive/html/bug-gnu-utils/2001-03/msg00029.html (5,062 bytes)
|
||||
|
||||
50. bug with gnu cpio 2.4.2 (score: 37)
|
||||
Author: [email protected]
|
||||
Date: Tue, 6 Mar 2001 12:27:14 +0100
|
||||
Hi, I have a problem using cpio with a Red Hat 6.2 whith a
|
||||
2.2.14-5.0smp kernel. The backup device is a HP DAT DDS4 20/40
|
||||
with the right cartridge. The cpio is launched by the cron.
|
||||
During the backup
|
||||
/archive/html/bug-gnu-utils/2001-03/msg00024.html (4,315 bytes)
|
||||
|
||||
52. [PATCH] cpio 2.4.2 does not compile with libc 2.2, gcc 2.95
|
||||
(score: 38)
|
||||
Author: "John Fremlin" <[email protected]>
|
||||
Date: 11 Feb 2001 22:19:09 +0000
|
||||
In fact it violates the GNU coding standards by declaring stuff
|
||||
when it shouldn't. Tsk, tsk. Attachment: cpio-2.4.2-build.patch
|
||||
Description: Text Data -- http://www.penguinpowered.com/~vii
|
||||
/archive/html/bug-gnu-utils/2001-02/msg00065.html (4,169 bytes)
|
||||
|
||||
53. cpio-2.4.2: data corruption bug (score: 35)
|
||||
Author: Todd Kelley <[email protected]>
|
||||
Date: Fri, 09 Feb 2001 17:00:06 -0500
|
||||
Hello, Recently at OEone we fixed a bug in GNU cpio-2.4.2: When
|
||||
a file over about 0.5 megabyes grows while it is being
|
||||
archived, it and all files following it in the archive are
|
||||
corrupted. The crc do
|
||||
/archive/html/bug-gnu-utils/2001-02/msg00062.html (4,297 bytes)
|
||||
|
||||
54. cpio 2.4.2 unconditionally takes the tape drive offline (score:
|
||||
39)
|
||||
Author: Scott Larson <[email protected]>
|
||||
Date: Thu, 11 Jan 2001 13:15:52 -0800
|
||||
We have been copying multiple volumes to a single tape with the
|
||||
System 5 version of cpio. The gnu version of cpio doesn't
|
||||
support this since it takes the tape offline (i.e. ejects the
|
||||
tape) after rea
|
||||
/archive/html/bug-gnu-utils/2001-01/msg00087.html (4,264 bytes)
|
||||
|
||||
55. cpio -t can see international filenames, find -ls also suffers
|
||||
(score: 35)
|
||||
Author: "Dan Jacobson" <[email protected]>
|
||||
Date: Tue, 26 Dec 2000 07:38:53 +0800
|
||||
GNU cpio version 2.4.2 with cpio -t I can see Chinese [big5]
|
||||
filenames. with -tv, they become \267\247 etc Just like what
|
||||
happens with find . -print vs. find . -ls --
|
||||
http://www.geocities.com/jidanni
|
||||
/archive/html/bug-gnu-utils/2000-12/msg00143.html (4,084 bytes)
|
||||
|
||||
56. cpio-2.4.2 compilation problems (score: 34)
|
||||
Author: Thomas =?iso-8859-1?q?K=F6ller?= <[email protected]>
|
||||
Date: Wed, 20 Dec 2000 02:50:24 +0100
|
||||
I encountered several problems building cpio-2.4.2. I am
|
||||
running linux-2.2.17, glibc-2.1.3 and gcc 2.95.2. The errors I
|
||||
received were mostly due to the source files re-declaring
|
||||
things unconditionall
|
||||
/archive/html/bug-gnu-utils/2000-12/msg00109.html (5,782 bytes)
|
||||
|
||||
58. cpio-2.4.2 & glibc-2.* (score: 46)
|
||||
Author: Florian Wunderlich <[email protected]>
|
||||
Date: Mon, 18 Dec 2000 16:25:00 +0100
|
||||
I still do not see a new version of cpio or at least extra
|
||||
patches that fix it so it works with the glibc. Thus, here is a
|
||||
simple patch to make it compile with glibc: diff -u
|
||||
cpio-2.4.2-old/rmt.c cpi
|
||||
/archive/html/bug-gnu-utils/2000-12/msg00098.html (4,846 bytes)
|
||||
|
||||
60. cpio-2.4.2 signed-unsigned int disagreement with malloc (score:
|
||||
39)
|
||||
Author: Antonomasia <[email protected]>
|
||||
Date: Mon, 27 Nov 2000 07:05:01 GMT
|
||||
copyin.c: 534 link_name = (char *) xmalloc ((unsigned int)
|
||||
file_hdr.c_filesize + 1); 535 link_name[file_hdr.c_filesize] =
|
||||
'\0'; file_hdr.c_filesize can be a large negative number as
|
||||
seen here then th
|
||||
/archive/html/bug-gnu-utils/2000-11/msg00171.html (4,718 bytes)
|
||||
|
||||
61. gnu CPIO (score: 38)
|
||||
Author: Clark Cooper <[email protected]>
|
||||
Date: Mon, 13 Nov 2000 13:21:07 -0500 (EST)
|
||||
The gnu version of CPIO appears to send all output to stderr.
|
||||
Take for instance a need to have the list of files copied and
|
||||
any errors separated as should be produced by the following:
|
||||
find . -print
|
||||
/archive/html/bug-gnu-utils/2000-11/msg00089.html (3,903 bytes)
|
||||
|
||||
62. Desire enhancement to GNU cpio 2.4.2 (score: 35)
|
||||
Author: Dave Dykstra <[email protected]>
|
||||
Date: Mon, 13 Nov 2000 10:24:56 -0600
|
||||
I have a new GNU/Linux system with large disks on which I need
|
||||
to generate cpio files for many different systems including
|
||||
older ones that don't support the "newc" format, only the "odc"
|
||||
format. The
|
||||
/archive/html/bug-gnu-utils/2000-11/msg00087.html (5,115 bytes)
|
||||
|
||||
65. cpio pass-through can corrupt files (score: 36)
|
||||
Author: "Parrott, Jeff" <[email protected]>
|
||||
Date: Mon, 16 Oct 2000 13:32:57 -0400
|
||||
I have seen corrupted files as a result of using the
|
||||
pass-through option in cpio. The corruption occurs when
|
||||
active/in-use (and growing) files are being copied. The problem
|
||||
is that the file size has
|
||||
/archive/html/bug-gnu-utils/2000-10/msg00087.html (4,974 bytes)
|
||||
|
||||
66. [Bug-gnu-utils] A small problem with cpio (score: 36)
|
||||
Author: Chris Hall <[email protected]>
|
||||
Date: Fri, 15 Sep 2000 11:05:56 +0100
|
||||
Hi, I'm running cpio 2.4.2 on AIX 4.3.3 and have a problem with
|
||||
very large files, I get this output when running the command: $
|
||||
ls -l total 2867988 drwxrwxrwx 2 root sys 512 Sep 14 17:05
|
||||
chris/ -rw-r
|
||||
/archive/html/bug-gnu-utils/2000-09/msg00004.html (4,481 bytes)
|
||||
+91
-26
@@ -46,6 +46,19 @@ $FreeBSD$
|
||||
#define lchown chown
|
||||
#endif
|
||||
|
||||
# ifndef DIRECTORY_SEPARATOR
|
||||
# define DIRECTORY_SEPARATOR '/'
|
||||
# endif
|
||||
|
||||
# ifndef ISSLASH
|
||||
# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
|
||||
# endif
|
||||
|
||||
# ifndef FILE_SYSTEM_PREFIX_LEN
|
||||
# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
|
||||
# endif
|
||||
|
||||
|
||||
static void read_pattern_file ();
|
||||
static void tape_skip_padding ();
|
||||
static void defer_copyin ();
|
||||
@@ -376,6 +389,54 @@ swab_array (ptr, count)
|
||||
/* Current time for verbose table. */
|
||||
static time_t current_time;
|
||||
|
||||
/* Return a safer suffix of FILE_NAME, or "." if it has no safer
|
||||
suffix. Check for fully specified file names and other atrocities. */
|
||||
|
||||
static const char *
|
||||
safer_name_suffix (char const *file_name)
|
||||
{
|
||||
char const *p;
|
||||
|
||||
/* Skip file system prefixes, leading file name components that contain
|
||||
"..", and leading slashes. */
|
||||
|
||||
size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (file_name);
|
||||
|
||||
for (p = file_name + prefix_len; *p;)
|
||||
{
|
||||
if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2]))
|
||||
prefix_len = p + 2 - file_name;
|
||||
|
||||
do
|
||||
{
|
||||
char c = *p++;
|
||||
if (ISSLASH (c))
|
||||
break;
|
||||
}
|
||||
while (*p);
|
||||
}
|
||||
|
||||
for (p = file_name + prefix_len; ISSLASH (*p); p++)
|
||||
continue;
|
||||
prefix_len = p - file_name;
|
||||
|
||||
if (prefix_len)
|
||||
{
|
||||
char *prefix = alloca (prefix_len + 1);
|
||||
memcpy (prefix, file_name, prefix_len);
|
||||
prefix[prefix_len] = '\0';
|
||||
|
||||
|
||||
error (0, 0, "Removing leading `%s' from member names", prefix);
|
||||
}
|
||||
|
||||
if (!*p)
|
||||
p = ".";
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/* Read the collection from standard input and create files
|
||||
in the file system. */
|
||||
|
||||
@@ -396,6 +457,7 @@ process_copy_in ()
|
||||
int in_file_des; /* Input file descriptor. */
|
||||
char skip_file; /* Flag for use with patterns. */
|
||||
int existing_dir; /* True if file is a dir & already exists. */
|
||||
mode_t existing_mode;
|
||||
int i; /* Loop index variable. */
|
||||
char *link_name = NULL; /* Name of hard and symbolic links. */
|
||||
#ifdef HPUX_CDF
|
||||
@@ -494,18 +556,11 @@ process_copy_in ()
|
||||
|
||||
/* Do we have to ignore absolute paths, and if so, does the filename
|
||||
have an absolute path? */
|
||||
if (no_abs_paths_flag && file_hdr.c_name && file_hdr.c_name [0] == '/')
|
||||
if (!abs_paths_flag && file_hdr.c_name && file_hdr.c_name[0])
|
||||
{
|
||||
char *p;
|
||||
const char *p = safer_name_suffix (file_hdr.c_name);
|
||||
|
||||
p = file_hdr.c_name;
|
||||
while (*p == '/')
|
||||
++p;
|
||||
if (*p == '\0')
|
||||
{
|
||||
strcpy (file_hdr.c_name, ".");
|
||||
}
|
||||
else
|
||||
if (p != file_hdr.c_name)
|
||||
{
|
||||
char *non_abs_name;
|
||||
|
||||
@@ -642,6 +697,7 @@ process_copy_in ()
|
||||
we are trying to create, don't complain about
|
||||
it. */
|
||||
existing_dir = TRUE;
|
||||
existing_mode = file_stat.st_mode;
|
||||
}
|
||||
else if (!unconditional_flag
|
||||
&& file_hdr.c_mtime <= file_stat.st_mtime)
|
||||
@@ -778,8 +834,6 @@ process_copy_in ()
|
||||
}
|
||||
copy_files_tape_to_disk (in_file_des, out_file_des, file_hdr.c_filesize);
|
||||
disk_empty_output_buffer (out_file_des);
|
||||
if (close (out_file_des) < 0)
|
||||
error (0, errno, "%s", file_hdr.c_name);
|
||||
|
||||
if (archive_format == arf_crcascii)
|
||||
{
|
||||
@@ -789,13 +843,15 @@ process_copy_in ()
|
||||
}
|
||||
/* File is now copied; set attributes. */
|
||||
if (!no_chown_flag)
|
||||
if ((chown (file_hdr.c_name,
|
||||
if ((fchown (out_file_des,
|
||||
set_owner_flag ? set_owner : file_hdr.c_uid,
|
||||
set_group_flag ? set_group : file_hdr.c_gid) < 0)
|
||||
&& errno != EPERM)
|
||||
error (0, errno, "%s", file_hdr.c_name);
|
||||
/* chown may have turned off some permissions we wanted. */
|
||||
if (chmod (file_hdr.c_name, (int) file_hdr.c_mode) < 0)
|
||||
if (fchmod (out_file_des, (int) file_hdr.c_mode) < 0)
|
||||
error (0, errno, "%s", file_hdr.c_name);
|
||||
if (close (out_file_des) < 0)
|
||||
error (0, errno, "%s", file_hdr.c_name);
|
||||
if (retain_time_flag)
|
||||
{
|
||||
@@ -847,14 +903,23 @@ process_copy_in ()
|
||||
cdf_flag = 1;
|
||||
}
|
||||
#endif
|
||||
res = mkdir (file_hdr.c_name, file_hdr.c_mode);
|
||||
res = mkdir (file_hdr.c_name, file_hdr.c_mode & ~077);
|
||||
}
|
||||
else
|
||||
res = 0;
|
||||
{
|
||||
if (!no_chown_flag && (existing_mode & 077) != 0
|
||||
&& chmod (file_hdr.c_name, existing_mode & 07700) < 0)
|
||||
{
|
||||
error (0, errno, "%s: chmod", file_hdr.c_name);
|
||||
return;
|
||||
}
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if (res < 0 && create_dir_flag)
|
||||
{
|
||||
create_all_directories (file_hdr.c_name);
|
||||
res = mkdir (file_hdr.c_name, file_hdr.c_mode);
|
||||
res = mkdir (file_hdr.c_name, file_hdr.c_mode & ~077);
|
||||
}
|
||||
if (res < 0)
|
||||
{
|
||||
@@ -936,20 +1001,20 @@ process_copy_in ()
|
||||
|
||||
#ifdef CP_IFIFO
|
||||
if ((file_hdr.c_mode & CP_IFMT) == CP_IFIFO)
|
||||
res = mkfifo (file_hdr.c_name, file_hdr.c_mode);
|
||||
res = mkfifo (file_hdr.c_name, file_hdr.c_mode & ~077);
|
||||
else
|
||||
#endif
|
||||
res = mknod (file_hdr.c_name, file_hdr.c_mode,
|
||||
res = mknod (file_hdr.c_name, file_hdr.c_mode & ~077,
|
||||
makedev (file_hdr.c_rdev_maj, file_hdr.c_rdev_min));
|
||||
if (res < 0 && create_dir_flag)
|
||||
{
|
||||
create_all_directories (file_hdr.c_name);
|
||||
#ifdef CP_IFIFO
|
||||
if ((file_hdr.c_mode & CP_IFMT) == CP_IFIFO)
|
||||
res = mkfifo (file_hdr.c_name, file_hdr.c_mode);
|
||||
res = mkfifo (file_hdr.c_name, file_hdr.c_mode & ~077);
|
||||
else
|
||||
#endif
|
||||
res = mknod (file_hdr.c_name, file_hdr.c_mode,
|
||||
res = mknod (file_hdr.c_name, file_hdr.c_mode & ~077,
|
||||
makedev (file_hdr.c_rdev_maj,
|
||||
file_hdr.c_rdev_min));
|
||||
}
|
||||
@@ -1376,18 +1441,18 @@ create_final_defers ()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (close (out_file_des) < 0)
|
||||
error (0, errno, "%s", d->header.c_name);
|
||||
|
||||
|
||||
/* File is now copied; set attributes. */
|
||||
if (!no_chown_flag)
|
||||
if ((chown (d->header.c_name,
|
||||
if ((fchown (out_file_des,
|
||||
set_owner_flag ? set_owner : d->header.c_uid,
|
||||
set_group_flag ? set_group : d->header.c_gid) < 0)
|
||||
&& errno != EPERM)
|
||||
error (0, errno, "%s", d->header.c_name);
|
||||
/* chown may have turned off some permissions we wanted. */
|
||||
if (chmod (d->header.c_name, (int) d->header.c_mode) < 0)
|
||||
if (fchmod (out_file_des, (int) d->header.c_mode) < 0)
|
||||
error (0, errno, "%s", d->header.c_name);
|
||||
if (close (out_file_des) < 0)
|
||||
error (0, errno, "%s", d->header.c_name);
|
||||
if (retain_time_flag)
|
||||
{
|
||||
|
||||
+20
-2
@@ -49,12 +49,13 @@ write_out_header (file_hdr, out_des)
|
||||
{
|
||||
char ascii_header[112];
|
||||
char *magic_string;
|
||||
int ret;
|
||||
|
||||
if (archive_format == arf_crcascii)
|
||||
magic_string = "070702";
|
||||
else
|
||||
magic_string = "070701";
|
||||
sprintf (ascii_header,
|
||||
ret = snprintf (ascii_header, sizeof(ascii_header),
|
||||
"%6s%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx",
|
||||
magic_string,
|
||||
file_hdr->c_ino, file_hdr->c_mode, file_hdr->c_uid,
|
||||
@@ -62,6 +63,10 @@ write_out_header (file_hdr, out_des)
|
||||
file_hdr->c_filesize, file_hdr->c_dev_maj, file_hdr->c_dev_min,
|
||||
file_hdr->c_rdev_maj, file_hdr->c_rdev_min, file_hdr->c_namesize,
|
||||
file_hdr->c_chksum);
|
||||
if (ret >= sizeof(ascii_header)) {
|
||||
fprintf(stderr, "Internal overflow, aborting\n");
|
||||
exit (1);
|
||||
}
|
||||
tape_buffered_write (ascii_header, out_des, 110L);
|
||||
|
||||
/* Write file name to output. */
|
||||
@@ -71,6 +76,7 @@ write_out_header (file_hdr, out_des)
|
||||
else if (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
|
||||
{
|
||||
char ascii_header[78];
|
||||
int ret;
|
||||
#ifndef __MSDOS__
|
||||
dev_t dev;
|
||||
dev_t rdev;
|
||||
@@ -112,7 +118,7 @@ write_out_header (file_hdr, out_des)
|
||||
if ((file_hdr->c_ino >> 16) != 0)
|
||||
error (0, 0, "%s: truncating inode number", file_hdr->c_name);
|
||||
|
||||
sprintf (ascii_header,
|
||||
ret = snprintf (ascii_header, sizeof(ascii_header),
|
||||
"%06o%06o%06lo%06lo%06lo%06lo%06lo%06o%011lo%06lo%011lo",
|
||||
file_hdr->c_magic & 0xFFFF, dev & 0xFFFF,
|
||||
file_hdr->c_ino & 0xFFFF, file_hdr->c_mode & 0xFFFF,
|
||||
@@ -120,6 +126,10 @@ write_out_header (file_hdr, out_des)
|
||||
file_hdr->c_nlink & 0xFFFF, rdev & 0xFFFF,
|
||||
file_hdr->c_mtime, file_hdr->c_namesize & 0xFFFF,
|
||||
file_hdr->c_filesize);
|
||||
if (ret >= sizeof(ascii_header)) {
|
||||
fprintf(stderr, "Internal overflow, aborting\n");
|
||||
exit (1);
|
||||
}
|
||||
tape_buffered_write (ascii_header, out_des, 76L);
|
||||
|
||||
/* Write file name to output. */
|
||||
@@ -258,6 +268,14 @@ process_copy_out ()
|
||||
file_hdr.c_dev_maj = major (file_stat.st_dev);
|
||||
file_hdr.c_dev_min = minor (file_stat.st_dev);
|
||||
file_hdr.c_ino = file_stat.st_ino;
|
||||
|
||||
/* Skip files larger than 4GB which will cause problems on
|
||||
64bit platforms (and just not work on 32bit). */
|
||||
if (file_stat.st_size > 0xffffffff) {
|
||||
error (0, 0, "%s: skipping >4GB file", input_name.ds_string);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* For POSIX systems that don't define the S_IF macros,
|
||||
we can't assume that S_ISfoo means the standard Unix
|
||||
S_IFfoo bit(s) are set. So do it manually, with a
|
||||
|
||||
+20
-11
@@ -174,18 +174,18 @@ process_copy_pass ()
|
||||
disk_empty_output_buffer (out_file_des);
|
||||
if (close (in_file_des) < 0)
|
||||
error (0, errno, "%s", input_name.ds_string);
|
||||
if (close (out_file_des) < 0)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
|
||||
/* Set the attributes of the new file. */
|
||||
if (!no_chown_flag)
|
||||
if ((chown (output_name.ds_string,
|
||||
if ((fchown (out_file_des,
|
||||
set_owner_flag ? set_owner : in_file_stat.st_uid,
|
||||
set_group_flag ? set_group : in_file_stat.st_gid) < 0)
|
||||
&& errno != EPERM)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
/* chown may have turned off some permissions we wanted. */
|
||||
if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
|
||||
if (fchmod (out_file_des, in_file_stat.st_mode) < 0)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
if (close (out_file_des) < 0)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
if (reset_time_flag)
|
||||
{
|
||||
@@ -224,15 +224,24 @@ process_copy_pass ()
|
||||
cdf_flag = 1;
|
||||
}
|
||||
#endif
|
||||
res = mkdir (output_name.ds_string, in_file_stat.st_mode);
|
||||
res = mkdir (output_name.ds_string, in_file_stat.st_mode & ~077);
|
||||
|
||||
}
|
||||
else
|
||||
res = 0;
|
||||
{
|
||||
if (!no_chown_flag && (out_file_stat.st_mode & 077) != 0
|
||||
&& chmod (output_name.ds_string, out_file_stat.st_mode & 07700) < 0)
|
||||
{
|
||||
error (0, errno, "%s: chmod", output_name.ds_string);
|
||||
continue;
|
||||
}
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if (res < 0 && create_dir_flag)
|
||||
{
|
||||
create_all_directories (output_name.ds_string);
|
||||
res = mkdir (output_name.ds_string, in_file_stat.st_mode);
|
||||
res = mkdir (output_name.ds_string, in_file_stat.st_mode & ~077);
|
||||
}
|
||||
if (res < 0)
|
||||
{
|
||||
@@ -298,20 +307,20 @@ process_copy_pass ()
|
||||
{
|
||||
#ifdef S_ISFIFO
|
||||
if (S_ISFIFO (in_file_stat.st_mode))
|
||||
res = mkfifo (output_name.ds_string, in_file_stat.st_mode);
|
||||
res = mkfifo (output_name.ds_string, in_file_stat.st_mode & ~077);
|
||||
else
|
||||
#endif
|
||||
res = mknod (output_name.ds_string, in_file_stat.st_mode,
|
||||
res = mknod (output_name.ds_string, in_file_stat.st_mode & ~077,
|
||||
in_file_stat.st_rdev);
|
||||
if (res < 0 && create_dir_flag)
|
||||
{
|
||||
create_all_directories (output_name.ds_string);
|
||||
#ifdef S_ISFIFO
|
||||
if (S_ISFIFO (in_file_stat.st_mode))
|
||||
res = mkfifo (output_name.ds_string, in_file_stat.st_mode);
|
||||
res = mkfifo (output_name.ds_string, in_file_stat.st_mode & ~077);
|
||||
else
|
||||
#endif
|
||||
res = mknod (output_name.ds_string, in_file_stat.st_mode,
|
||||
res = mknod (output_name.ds_string, in_file_stat.st_mode & ~077,
|
||||
in_file_stat.st_rdev);
|
||||
}
|
||||
if (res < 0)
|
||||
|
||||
+4
-4
@@ -19,7 +19,7 @@ cpio \- copy files to and from archives
|
||||
[\-\-unconditional] [\-\-verbose] [\-\-block-size=blocks] [\-\-swap-halfwords]
|
||||
[\-\-io-size=bytes] [\-\-pattern-file=file] [\-\-format=format]
|
||||
[\-\-owner=[user][:.][group]] [\-\-no-preserve-owner] [\-\-message=message]
|
||||
[\-\-force\-local] [\-\-no\-absolute\-filenames] [\-\-sparse] [\-\-only\-verify\-crc]
|
||||
[\-\-force\-local] [\-\-absolute\-filenames] [\-\-sparse] [\-\-only\-verify\-crc]
|
||||
[\-\-quiet] [\-\-help] [\-\-version] [pattern...] [< archive]
|
||||
|
||||
.B cpio
|
||||
@@ -251,9 +251,9 @@ current volume number (starting at 1).
|
||||
In the verbose table of contents listing, show numeric UID and GID
|
||||
instead of translating them into names.
|
||||
.TP
|
||||
.I " \-\-no-absolute-filenames"
|
||||
In copy-in mode, create all files relative to the current directory,
|
||||
even if they have an absolute file name in the archive.
|
||||
.I " \-\-absolute-filenames"
|
||||
Do not strip leading file name components that contain ".."
|
||||
and leading slashes from file names in copy-in mode
|
||||
.TP
|
||||
.I " \-\-no-preserve-owner"
|
||||
In copy-in mode and copy-pass mode, do not change the ownership of the
|
||||
|
||||
@@ -46,7 +46,7 @@ extern int no_chown_flag;
|
||||
extern int sparse_flag;
|
||||
extern int quiet_flag;
|
||||
extern int only_verify_crc_flag;
|
||||
extern int no_abs_paths_flag;
|
||||
extern int abs_paths_flag;
|
||||
|
||||
extern int last_header_start;
|
||||
extern int copy_matching_files;
|
||||
|
||||
@@ -98,8 +98,8 @@ int quiet_flag = FALSE;
|
||||
actually extract the files. */
|
||||
int only_verify_crc_flag = FALSE;
|
||||
|
||||
/* If TRUE, don't use any absolute paths, prefix them by `./'. */
|
||||
int no_abs_paths_flag = FALSE;
|
||||
/* If TRUE, allow any absolute paths */
|
||||
int abs_paths_flag = FALSE;
|
||||
|
||||
#ifdef DEBUG_CPIO
|
||||
/* If TRUE, print debugging information. */
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/* Memory allocation on the stack.
|
||||
|
||||
Copyright (C) 1995, 1999, 2001, 2002, 2003, 2004 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
USA. */
|
||||
|
||||
/* When this file is included, it may be preceded only by preprocessor
|
||||
declarations. Thanks to AIX. Therefore we include it right after
|
||||
"config.h", not later. */
|
||||
|
||||
#ifndef _ALLOCA_H
|
||||
# define _ALLOCA_H
|
||||
|
||||
/* alloca (N) returns a pointer to N bytes of memory
|
||||
allocated on the stack, which will last until the function returns.
|
||||
Use of alloca should be avoided:
|
||||
- inside arguments of function calls - undefined behaviour,
|
||||
- in inline functions - the allocation may actually last until the
|
||||
calling function returns,
|
||||
- for huge N (say, N >= 65536) - you never know how large (or small)
|
||||
the stack is, and when the stack cannot fulfill the memory allocation
|
||||
request, the program just crashes.
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define alloca __builtin_alloca
|
||||
#elif defined _AIX
|
||||
# define alloca __alloca
|
||||
#elif defined _MSC_VER
|
||||
# include <malloc.h>
|
||||
# define alloca _alloca
|
||||
#else
|
||||
# include <stddef.h>
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
void *alloca (size_t);
|
||||
#endif
|
||||
|
||||
#endif /* _ALLOCA_H */
|
||||
@@ -1,25 +0,0 @@
|
||||
/* Default definition for ARGP_PROGRAM_BUG_ADDRESS.
|
||||
Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* If set by the user program, it should point to string that is the
|
||||
bug-reporting address for the program. It will be printed by argp_help if
|
||||
the ARGP_HELP_BUG_ADDR flag is set (as it is by various standard help
|
||||
messages), embedded in a sentence that says something like `Report bugs to
|
||||
ADDR.'. */
|
||||
const char *argp_program_bug_address;
|
||||
@@ -1,31 +0,0 @@
|
||||
/* Default definition for ARGP_ERR_EXIT_STATUS
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sysexits.h>
|
||||
|
||||
#include "argp.h"
|
||||
|
||||
/* The exit status that argp will use when exiting due to a parsing error.
|
||||
If not defined or set by the user program, this defaults to EX_USAGE from
|
||||
<sysexits.h>. */
|
||||
error_t argp_err_exit_status = EX_USAGE;
|
||||
@@ -1,440 +0,0 @@
|
||||
/* Word-wrapping and line-truncating streams
|
||||
Copyright (C) 1997,1998,1999,2001,2002,2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* This package emulates glibc `line_wrap_stream' semantics for systems that
|
||||
don't have that. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "argp-fmtstream.h"
|
||||
#include "argp-namefrob.h"
|
||||
|
||||
#ifndef ARGP_FMTSTREAM_USE_LINEWRAP
|
||||
|
||||
#ifndef isblank
|
||||
#define isblank(ch) ((ch)==' ' || (ch)=='\t')
|
||||
#endif
|
||||
|
||||
#if defined _LIBC && defined USE_IN_LIBIO
|
||||
# include <wchar.h>
|
||||
# include <libio/libioP.h>
|
||||
# define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
|
||||
#endif
|
||||
|
||||
#define INIT_BUF_SIZE 200
|
||||
#define PRINTF_SIZE_GUESS 150
|
||||
|
||||
/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines
|
||||
written on it with LMARGIN spaces and limits them to RMARGIN columns
|
||||
total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by
|
||||
replacing the whitespace before them with a newline and WMARGIN spaces.
|
||||
Otherwise, chars beyond RMARGIN are simply dropped until a newline.
|
||||
Returns NULL if there was an error. */
|
||||
argp_fmtstream_t
|
||||
__argp_make_fmtstream (FILE *stream,
|
||||
size_t lmargin, size_t rmargin, ssize_t wmargin)
|
||||
{
|
||||
argp_fmtstream_t fs;
|
||||
|
||||
fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream));
|
||||
if (fs != NULL)
|
||||
{
|
||||
fs->stream = stream;
|
||||
|
||||
fs->lmargin = lmargin;
|
||||
fs->rmargin = rmargin;
|
||||
fs->wmargin = wmargin;
|
||||
fs->point_col = 0;
|
||||
fs->point_offs = 0;
|
||||
|
||||
fs->buf = (char *) malloc (INIT_BUF_SIZE);
|
||||
if (! fs->buf)
|
||||
{
|
||||
free (fs);
|
||||
fs = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fs->p = fs->buf;
|
||||
fs->end = fs->buf + INIT_BUF_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
return fs;
|
||||
}
|
||||
#if 0
|
||||
/* Not exported. */
|
||||
#ifdef weak_alias
|
||||
weak_alias (__argp_make_fmtstream, argp_make_fmtstream)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Flush FS to its stream, and free it (but don't close the stream). */
|
||||
void
|
||||
__argp_fmtstream_free (argp_fmtstream_t fs)
|
||||
{
|
||||
__argp_fmtstream_update (fs);
|
||||
if (fs->p > fs->buf)
|
||||
{
|
||||
#ifdef USE_IN_LIBIO
|
||||
if (_IO_fwide (fs->stream, 0) > 0)
|
||||
__fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf);
|
||||
else
|
||||
#endif
|
||||
fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
|
||||
}
|
||||
free (fs->buf);
|
||||
free (fs);
|
||||
}
|
||||
#if 0
|
||||
/* Not exported. */
|
||||
#ifdef weak_alias
|
||||
weak_alias (__argp_fmtstream_free, argp_fmtstream_free)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Process FS's buffer so that line wrapping is done from POINT_OFFS to the
|
||||
end of its buffer. This code is mostly from glibc stdio/linewrap.c. */
|
||||
void
|
||||
__argp_fmtstream_update (argp_fmtstream_t fs)
|
||||
{
|
||||
char *buf, *nl;
|
||||
size_t len;
|
||||
|
||||
/* Scan the buffer for newlines. */
|
||||
buf = fs->buf + fs->point_offs;
|
||||
while (buf < fs->p)
|
||||
{
|
||||
size_t r;
|
||||
|
||||
if (fs->point_col == 0 && fs->lmargin != 0)
|
||||
{
|
||||
/* We are starting a new line. Print spaces to the left margin. */
|
||||
const size_t pad = fs->lmargin;
|
||||
if (fs->p + pad < fs->end)
|
||||
{
|
||||
/* We can fit in them in the buffer by moving the
|
||||
buffer text up and filling in the beginning. */
|
||||
memmove (buf + pad, buf, fs->p - buf);
|
||||
fs->p += pad; /* Compensate for bigger buffer. */
|
||||
memset (buf, ' ', pad); /* Fill in the spaces. */
|
||||
buf += pad; /* Don't bother searching them. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No buffer space for spaces. Must flush. */
|
||||
size_t i;
|
||||
for (i = 0; i < pad; i++)
|
||||
{
|
||||
#ifdef USE_IN_LIBIO
|
||||
if (_IO_fwide (fs->stream, 0) > 0)
|
||||
putwc_unlocked (L' ', fs->stream);
|
||||
else
|
||||
#endif
|
||||
putc_unlocked (' ', fs->stream);
|
||||
}
|
||||
}
|
||||
fs->point_col = pad;
|
||||
}
|
||||
|
||||
len = fs->p - buf;
|
||||
nl = memchr (buf, '\n', len);
|
||||
|
||||
if (fs->point_col < 0)
|
||||
fs->point_col = 0;
|
||||
|
||||
if (!nl)
|
||||
{
|
||||
/* The buffer ends in a partial line. */
|
||||
|
||||
if (fs->point_col + len < fs->rmargin)
|
||||
{
|
||||
/* The remaining buffer text is a partial line and fits
|
||||
within the maximum line width. Advance point for the
|
||||
characters to be written and stop scanning. */
|
||||
fs->point_col += len;
|
||||
break;
|
||||
}
|
||||
else
|
||||
/* Set the end-of-line pointer for the code below to
|
||||
the end of the buffer. */
|
||||
nl = fs->p;
|
||||
}
|
||||
else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin)
|
||||
{
|
||||
/* The buffer contains a full line that fits within the maximum
|
||||
line width. Reset point and scan the next line. */
|
||||
fs->point_col = 0;
|
||||
buf = nl + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This line is too long. */
|
||||
r = fs->rmargin - 1;
|
||||
|
||||
if (fs->wmargin < 0)
|
||||
{
|
||||
/* Truncate the line by overwriting the excess with the
|
||||
newline and anything after it in the buffer. */
|
||||
if (nl < fs->p)
|
||||
{
|
||||
memmove (buf + (r - fs->point_col), nl, fs->p - nl);
|
||||
fs->p -= buf + (r - fs->point_col) - nl;
|
||||
/* Reset point for the next line and start scanning it. */
|
||||
fs->point_col = 0;
|
||||
buf += r + 1; /* Skip full line plus \n. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The buffer ends with a partial line that is beyond the
|
||||
maximum line width. Advance point for the characters
|
||||
written, and discard those past the max from the buffer. */
|
||||
fs->point_col += len;
|
||||
fs->p -= fs->point_col - r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do word wrap. Go to the column just past the maximum line
|
||||
width and scan back for the beginning of the word there.
|
||||
Then insert a line break. */
|
||||
|
||||
char *p, *nextline;
|
||||
int i;
|
||||
|
||||
p = buf + (r + 1 - fs->point_col);
|
||||
while (p >= buf && !isblank (*p))
|
||||
--p;
|
||||
nextline = p + 1; /* This will begin the next line. */
|
||||
|
||||
if (nextline > buf)
|
||||
{
|
||||
/* Swallow separating blanks. */
|
||||
if (p >= buf)
|
||||
do
|
||||
--p;
|
||||
while (p >= buf && isblank (*p));
|
||||
nl = p + 1; /* The newline will replace the first blank. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A single word that is greater than the maximum line width.
|
||||
Oh well. Put it on an overlong line by itself. */
|
||||
p = buf + (r + 1 - fs->point_col);
|
||||
/* Find the end of the long word. */
|
||||
do
|
||||
++p;
|
||||
while (p < nl && !isblank (*p));
|
||||
if (p == nl)
|
||||
{
|
||||
/* It already ends a line. No fussing required. */
|
||||
fs->point_col = 0;
|
||||
buf = nl + 1;
|
||||
continue;
|
||||
}
|
||||
/* We will move the newline to replace the first blank. */
|
||||
nl = p;
|
||||
/* Swallow separating blanks. */
|
||||
do
|
||||
++p;
|
||||
while (isblank (*p));
|
||||
/* The next line will start here. */
|
||||
nextline = p;
|
||||
}
|
||||
|
||||
/* Note: There are a bunch of tests below for
|
||||
NEXTLINE == BUF + LEN + 1; this case is where NL happens to fall
|
||||
at the end of the buffer, and NEXTLINE is in fact empty (and so
|
||||
we need not be careful to maintain its contents). */
|
||||
|
||||
if ((nextline == buf + len + 1
|
||||
? fs->end - nl < fs->wmargin + 1
|
||||
: nextline - (nl + 1) < fs->wmargin)
|
||||
&& fs->p > nextline)
|
||||
{
|
||||
/* The margin needs more blanks than we removed. */
|
||||
if (fs->end - fs->p > fs->wmargin + 1)
|
||||
/* Make some space for them. */
|
||||
{
|
||||
size_t mv = fs->p - nextline;
|
||||
memmove (nl + 1 + fs->wmargin, nextline, mv);
|
||||
nextline = nl + 1 + fs->wmargin;
|
||||
len = nextline + mv - buf;
|
||||
*nl++ = '\n';
|
||||
}
|
||||
else
|
||||
/* Output the first line so we can use the space. */
|
||||
{
|
||||
#ifdef USE_IN_LIBIO
|
||||
if (_IO_fwide (fs->stream, 0) > 0)
|
||||
__fwprintf (fs->stream, L"%.*s\n",
|
||||
(int) (nl - fs->buf), fs->buf);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (nl > fs->buf)
|
||||
fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream);
|
||||
putc_unlocked ('\n', fs->stream);
|
||||
}
|
||||
len += buf - fs->buf;
|
||||
nl = buf = fs->buf;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* We can fit the newline and blanks in before
|
||||
the next word. */
|
||||
*nl++ = '\n';
|
||||
|
||||
if (nextline - nl >= fs->wmargin
|
||||
|| (nextline == buf + len + 1 && fs->end - nextline >= fs->wmargin))
|
||||
/* Add blanks up to the wrap margin column. */
|
||||
for (i = 0; i < fs->wmargin; ++i)
|
||||
*nl++ = ' ';
|
||||
else
|
||||
for (i = 0; i < fs->wmargin; ++i)
|
||||
#ifdef USE_IN_LIBIO
|
||||
if (_IO_fwide (fs->stream, 0) > 0)
|
||||
putwc_unlocked (L' ', fs->stream);
|
||||
else
|
||||
#endif
|
||||
putc_unlocked (' ', fs->stream);
|
||||
|
||||
/* Copy the tail of the original buffer into the current buffer
|
||||
position. */
|
||||
if (nl < nextline)
|
||||
memmove (nl, nextline, buf + len - nextline);
|
||||
len -= nextline - buf;
|
||||
|
||||
/* Continue the scan on the remaining lines in the buffer. */
|
||||
buf = nl;
|
||||
|
||||
/* Restore bufp to include all the remaining text. */
|
||||
fs->p = nl + len;
|
||||
|
||||
/* Reset the counter of what has been output this line. If wmargin
|
||||
is 0, we want to avoid the lmargin getting added, so we set
|
||||
point_col to a magic value of -1 in that case. */
|
||||
fs->point_col = fs->wmargin ? fs->wmargin : -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remember that we've scanned as far as the end of the buffer. */
|
||||
fs->point_offs = fs->p - fs->buf;
|
||||
}
|
||||
|
||||
/* Ensure that FS has space for AMOUNT more bytes in its buffer, either by
|
||||
growing the buffer, or by flushing it. True is returned iff we succeed. */
|
||||
int
|
||||
__argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount)
|
||||
{
|
||||
if ((size_t) (fs->end - fs->p) < amount)
|
||||
{
|
||||
ssize_t wrote;
|
||||
|
||||
/* Flush FS's buffer. */
|
||||
__argp_fmtstream_update (fs);
|
||||
|
||||
#ifdef USE_IN_LIBIO
|
||||
if (_IO_fwide (fs->stream, 0) > 0)
|
||||
{
|
||||
__fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf);
|
||||
wrote = fs->p - fs->buf;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
|
||||
if (wrote == fs->p - fs->buf)
|
||||
{
|
||||
fs->p = fs->buf;
|
||||
fs->point_offs = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fs->p -= wrote;
|
||||
fs->point_offs -= wrote;
|
||||
memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((size_t) (fs->end - fs->buf) < amount)
|
||||
/* Gotta grow the buffer. */
|
||||
{
|
||||
size_t old_size = fs->end - fs->buf;
|
||||
size_t new_size = old_size + amount;
|
||||
char *new_buf;
|
||||
|
||||
if (new_size < old_size || ! (new_buf = realloc (fs->buf, new_size)))
|
||||
{
|
||||
__set_errno (ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fs->buf = new_buf;
|
||||
fs->end = new_buf + new_size;
|
||||
fs->p = fs->buf;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
__argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...)
|
||||
{
|
||||
int out;
|
||||
size_t avail;
|
||||
size_t size_guess = PRINTF_SIZE_GUESS; /* How much space to reserve. */
|
||||
|
||||
do
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (! __argp_fmtstream_ensure (fs, size_guess))
|
||||
return -1;
|
||||
|
||||
va_start (args, fmt);
|
||||
avail = fs->end - fs->p;
|
||||
out = __vsnprintf (fs->p, avail, fmt, args);
|
||||
va_end (args);
|
||||
if ((size_t) out >= avail)
|
||||
size_guess = out + 1;
|
||||
}
|
||||
while ((size_t) out >= avail);
|
||||
|
||||
fs->p += out;
|
||||
|
||||
return out;
|
||||
}
|
||||
#if 0
|
||||
/* Not exported. */
|
||||
#ifdef weak_alias
|
||||
weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* !ARGP_FMTSTREAM_USE_LINEWRAP */
|
||||
@@ -1,309 +0,0 @@
|
||||
/* Word-wrapping and line-truncating streams.
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* This package emulates glibc `line_wrap_stream' semantics for systems that
|
||||
don't have that. If the system does have it, it is just a wrapper for
|
||||
that. This header file is only used internally while compiling argp, and
|
||||
shouldn't be installed. */
|
||||
|
||||
#ifndef _ARGP_FMTSTREAM_H
|
||||
#define _ARGP_FMTSTREAM_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef __attribute__
|
||||
/* This feature is available in gcc versions 2.5 and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
|
||||
# define __attribute__(Spec) /* empty */
|
||||
# endif
|
||||
/* The __-protected variants of `format' and `printf' attributes
|
||||
are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || __STRICT_ANSI__
|
||||
# define __format__ format
|
||||
# define __printf__ printf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if (_LIBC - 0 && !defined (USE_IN_LIBIO)) \
|
||||
|| (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H))
|
||||
/* line_wrap_stream is available, so use that. */
|
||||
#define ARGP_FMTSTREAM_USE_LINEWRAP
|
||||
#endif
|
||||
|
||||
#ifdef ARGP_FMTSTREAM_USE_LINEWRAP
|
||||
/* Just be a simple wrapper for line_wrap_stream; the semantics are
|
||||
*slightly* different, as line_wrap_stream doesn't actually make a new
|
||||
object, it just modifies the given stream (reversibly) to do
|
||||
line-wrapping. Since we control who uses this code, it doesn't matter. */
|
||||
|
||||
#include <linewrap.h>
|
||||
|
||||
typedef FILE *argp_fmtstream_t;
|
||||
|
||||
#define argp_make_fmtstream line_wrap_stream
|
||||
#define __argp_make_fmtstream line_wrap_stream
|
||||
#define argp_fmtstream_free line_unwrap_stream
|
||||
#define __argp_fmtstream_free line_unwrap_stream
|
||||
|
||||
#define __argp_fmtstream_putc(fs,ch) putc(ch,fs)
|
||||
#define argp_fmtstream_putc(fs,ch) putc(ch,fs)
|
||||
#define __argp_fmtstream_puts(fs,str) fputs(str,fs)
|
||||
#define argp_fmtstream_puts(fs,str) fputs(str,fs)
|
||||
#define __argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs)
|
||||
#define argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs)
|
||||
#define __argp_fmtstream_printf fprintf
|
||||
#define argp_fmtstream_printf fprintf
|
||||
|
||||
#define __argp_fmtstream_lmargin line_wrap_lmargin
|
||||
#define argp_fmtstream_lmargin line_wrap_lmargin
|
||||
#define __argp_fmtstream_set_lmargin line_wrap_set_lmargin
|
||||
#define argp_fmtstream_set_lmargin line_wrap_set_lmargin
|
||||
#define __argp_fmtstream_rmargin line_wrap_rmargin
|
||||
#define argp_fmtstream_rmargin line_wrap_rmargin
|
||||
#define __argp_fmtstream_set_rmargin line_wrap_set_rmargin
|
||||
#define argp_fmtstream_set_rmargin line_wrap_set_rmargin
|
||||
#define __argp_fmtstream_wmargin line_wrap_wmargin
|
||||
#define argp_fmtstream_wmargin line_wrap_wmargin
|
||||
#define __argp_fmtstream_set_wmargin line_wrap_set_wmargin
|
||||
#define argp_fmtstream_set_wmargin line_wrap_set_wmargin
|
||||
#define __argp_fmtstream_point line_wrap_point
|
||||
#define argp_fmtstream_point line_wrap_point
|
||||
|
||||
#else /* !ARGP_FMTSTREAM_USE_LINEWRAP */
|
||||
/* Guess we have to define our own version. */
|
||||
|
||||
#ifndef __const
|
||||
#define __const const
|
||||
#endif
|
||||
|
||||
struct argp_fmtstream
|
||||
{
|
||||
FILE *stream; /* The stream we're outputting to. */
|
||||
|
||||
size_t lmargin, rmargin; /* Left and right margins. */
|
||||
ssize_t wmargin; /* Margin to wrap to, or -1 to truncate. */
|
||||
|
||||
/* Point in buffer to which we've processed for wrapping, but not output. */
|
||||
size_t point_offs;
|
||||
/* Output column at POINT_OFFS, or -1 meaning 0 but don't add lmargin. */
|
||||
ssize_t point_col;
|
||||
|
||||
char *buf; /* Output buffer. */
|
||||
char *p; /* Current end of text in BUF. */
|
||||
char *end; /* Absolute end of BUF. */
|
||||
};
|
||||
|
||||
typedef struct argp_fmtstream *argp_fmtstream_t;
|
||||
|
||||
/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines
|
||||
written on it with LMARGIN spaces and limits them to RMARGIN columns
|
||||
total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by
|
||||
replacing the whitespace before them with a newline and WMARGIN spaces.
|
||||
Otherwise, chars beyond RMARGIN are simply dropped until a newline.
|
||||
Returns NULL if there was an error. */
|
||||
extern argp_fmtstream_t __argp_make_fmtstream (FILE *__stream,
|
||||
size_t __lmargin,
|
||||
size_t __rmargin,
|
||||
ssize_t __wmargin);
|
||||
extern argp_fmtstream_t argp_make_fmtstream (FILE *__stream,
|
||||
size_t __lmargin,
|
||||
size_t __rmargin,
|
||||
ssize_t __wmargin);
|
||||
|
||||
/* Flush __FS to its stream, and free it (but don't close the stream). */
|
||||
extern void __argp_fmtstream_free (argp_fmtstream_t __fs);
|
||||
extern void argp_fmtstream_free (argp_fmtstream_t __fs);
|
||||
|
||||
extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs,
|
||||
__const char *__fmt, ...)
|
||||
__attribute__ ((__format__ (printf, 2, 3)));
|
||||
extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs,
|
||||
__const char *__fmt, ...)
|
||||
__attribute__ ((__format__ (printf, 2, 3)));
|
||||
|
||||
extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
|
||||
extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
|
||||
|
||||
extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str);
|
||||
extern int argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str);
|
||||
|
||||
extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs,
|
||||
__const char *__str, size_t __len);
|
||||
extern size_t argp_fmtstream_write (argp_fmtstream_t __fs,
|
||||
__const char *__str, size_t __len);
|
||||
|
||||
/* Access macros for various bits of state. */
|
||||
#define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin)
|
||||
#define argp_fmtstream_rmargin(__fs) ((__fs)->rmargin)
|
||||
#define argp_fmtstream_wmargin(__fs) ((__fs)->wmargin)
|
||||
#define __argp_fmtstream_lmargin argp_fmtstream_lmargin
|
||||
#define __argp_fmtstream_rmargin argp_fmtstream_rmargin
|
||||
#define __argp_fmtstream_wmargin argp_fmtstream_wmargin
|
||||
|
||||
/* Set __FS's left margin to LMARGIN and return the old value. */
|
||||
extern size_t argp_fmtstream_set_lmargin (argp_fmtstream_t __fs,
|
||||
size_t __lmargin);
|
||||
extern size_t __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs,
|
||||
size_t __lmargin);
|
||||
|
||||
/* Set __FS's right margin to __RMARGIN and return the old value. */
|
||||
extern size_t argp_fmtstream_set_rmargin (argp_fmtstream_t __fs,
|
||||
size_t __rmargin);
|
||||
extern size_t __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs,
|
||||
size_t __rmargin);
|
||||
|
||||
/* Set __FS's wrap margin to __WMARGIN and return the old value. */
|
||||
extern size_t argp_fmtstream_set_wmargin (argp_fmtstream_t __fs,
|
||||
size_t __wmargin);
|
||||
extern size_t __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs,
|
||||
size_t __wmargin);
|
||||
|
||||
/* Return the column number of the current output point in __FS. */
|
||||
extern size_t argp_fmtstream_point (argp_fmtstream_t __fs);
|
||||
extern size_t __argp_fmtstream_point (argp_fmtstream_t __fs);
|
||||
|
||||
/* Internal routines. */
|
||||
extern void _argp_fmtstream_update (argp_fmtstream_t __fs);
|
||||
extern void __argp_fmtstream_update (argp_fmtstream_t __fs);
|
||||
extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
|
||||
extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
/* Inline versions of above routines. */
|
||||
|
||||
#if !_LIBC
|
||||
#define __argp_fmtstream_putc argp_fmtstream_putc
|
||||
#define __argp_fmtstream_puts argp_fmtstream_puts
|
||||
#define __argp_fmtstream_write argp_fmtstream_write
|
||||
#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin
|
||||
#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin
|
||||
#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin
|
||||
#define __argp_fmtstream_point argp_fmtstream_point
|
||||
#define __argp_fmtstream_update _argp_fmtstream_update
|
||||
#define __argp_fmtstream_ensure _argp_fmtstream_ensure
|
||||
#endif
|
||||
|
||||
#ifndef ARGP_FS_EI
|
||||
#define ARGP_FS_EI extern inline
|
||||
#endif
|
||||
|
||||
ARGP_FS_EI size_t
|
||||
__argp_fmtstream_write (argp_fmtstream_t __fs,
|
||||
__const char *__str, size_t __len)
|
||||
{
|
||||
if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len))
|
||||
{
|
||||
memcpy (__fs->p, __str, __len);
|
||||
__fs->p += __len;
|
||||
return __len;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
ARGP_FS_EI int
|
||||
__argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str)
|
||||
{
|
||||
size_t __len = strlen (__str);
|
||||
if (__len)
|
||||
{
|
||||
size_t __wrote = __argp_fmtstream_write (__fs, __str, __len);
|
||||
return __wrote == __len ? 0 : -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
ARGP_FS_EI int
|
||||
__argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch)
|
||||
{
|
||||
if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1))
|
||||
return *__fs->p++ = __ch;
|
||||
else
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/* Set __FS's left margin to __LMARGIN and return the old value. */
|
||||
ARGP_FS_EI size_t
|
||||
__argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin)
|
||||
{
|
||||
size_t __old;
|
||||
if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
|
||||
__argp_fmtstream_update (__fs);
|
||||
__old = __fs->lmargin;
|
||||
__fs->lmargin = __lmargin;
|
||||
return __old;
|
||||
}
|
||||
|
||||
/* Set __FS's right margin to __RMARGIN and return the old value. */
|
||||
ARGP_FS_EI size_t
|
||||
__argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin)
|
||||
{
|
||||
size_t __old;
|
||||
if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
|
||||
__argp_fmtstream_update (__fs);
|
||||
__old = __fs->rmargin;
|
||||
__fs->rmargin = __rmargin;
|
||||
return __old;
|
||||
}
|
||||
|
||||
/* Set FS's wrap margin to __WMARGIN and return the old value. */
|
||||
ARGP_FS_EI size_t
|
||||
__argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin)
|
||||
{
|
||||
size_t __old;
|
||||
if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
|
||||
__argp_fmtstream_update (__fs);
|
||||
__old = __fs->wmargin;
|
||||
__fs->wmargin = __wmargin;
|
||||
return __old;
|
||||
}
|
||||
|
||||
/* Return the column number of the current output point in __FS. */
|
||||
ARGP_FS_EI size_t
|
||||
__argp_fmtstream_point (argp_fmtstream_t __fs)
|
||||
{
|
||||
if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
|
||||
__argp_fmtstream_update (__fs);
|
||||
return __fs->point_col >= 0 ? __fs->point_col : 0;
|
||||
}
|
||||
|
||||
#if !_LIBC
|
||||
#undef __argp_fmtstream_putc
|
||||
#undef __argp_fmtstream_puts
|
||||
#undef __argp_fmtstream_write
|
||||
#undef __argp_fmtstream_set_lmargin
|
||||
#undef __argp_fmtstream_set_rmargin
|
||||
#undef __argp_fmtstream_set_wmargin
|
||||
#undef __argp_fmtstream_point
|
||||
#undef __argp_fmtstream_update
|
||||
#undef __argp_fmtstream_ensure
|
||||
#endif
|
||||
|
||||
#endif /* __OPTIMIZE__ */
|
||||
|
||||
#endif /* ARGP_FMTSTREAM_USE_LINEWRAP */
|
||||
|
||||
#endif /* argp-fmtstream.h */
|
||||
@@ -1,43 +0,0 @@
|
||||
/* Real definitions for extern inline functions in argp-fmtstream.h
|
||||
Copyright (C) 1997, 2003, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#define ARGP_FS_EI
|
||||
#undef __OPTIMIZE__
|
||||
#define __OPTIMIZE__ 1
|
||||
#include "argp-fmtstream.h"
|
||||
|
||||
#if 0
|
||||
/* Not exported. */
|
||||
/* Add weak aliases. */
|
||||
#if _LIBC - 0 && !defined (ARGP_FMTSTREAM_USE_LINEWRAP) && defined (weak_alias)
|
||||
|
||||
weak_alias (__argp_fmtstream_putc, argp_fmtstream_putc)
|
||||
weak_alias (__argp_fmtstream_puts, argp_fmtstream_puts)
|
||||
weak_alias (__argp_fmtstream_write, argp_fmtstream_write)
|
||||
weak_alias (__argp_fmtstream_set_lmargin, argp_fmtstream_set_lmargin)
|
||||
weak_alias (__argp_fmtstream_set_rmargin, argp_fmtstream_set_rmargin)
|
||||
weak_alias (__argp_fmtstream_set_wmargin, argp_fmtstream_set_wmargin)
|
||||
weak_alias (__argp_fmtstream_point, argp_fmtstream_point)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,156 +0,0 @@
|
||||
/* Name frobnication for compiling argp outside of glibc
|
||||
Copyright (C) 1997, 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if !_LIBC
|
||||
/* This code is written for inclusion in gnu-libc, and uses names in the
|
||||
namespace reserved for libc. If we're not compiling in libc, define those
|
||||
names to be the normal ones instead. */
|
||||
|
||||
/* argp-parse functions */
|
||||
#undef __argp_parse
|
||||
#define __argp_parse argp_parse
|
||||
#undef __option_is_end
|
||||
#define __option_is_end _option_is_end
|
||||
#undef __option_is_short
|
||||
#define __option_is_short _option_is_short
|
||||
#undef __argp_input
|
||||
#define __argp_input _argp_input
|
||||
|
||||
/* argp-help functions */
|
||||
#undef __argp_help
|
||||
#define __argp_help argp_help
|
||||
#undef __argp_error
|
||||
#define __argp_error argp_error
|
||||
#undef __argp_failure
|
||||
#define __argp_failure argp_failure
|
||||
#undef __argp_state_help
|
||||
#define __argp_state_help argp_state_help
|
||||
#undef __argp_usage
|
||||
#define __argp_usage argp_usage
|
||||
|
||||
/* argp-fmtstream functions */
|
||||
#undef __argp_make_fmtstream
|
||||
#define __argp_make_fmtstream argp_make_fmtstream
|
||||
#undef __argp_fmtstream_free
|
||||
#define __argp_fmtstream_free argp_fmtstream_free
|
||||
#undef __argp_fmtstream_putc
|
||||
#define __argp_fmtstream_putc argp_fmtstream_putc
|
||||
#undef __argp_fmtstream_puts
|
||||
#define __argp_fmtstream_puts argp_fmtstream_puts
|
||||
#undef __argp_fmtstream_write
|
||||
#define __argp_fmtstream_write argp_fmtstream_write
|
||||
#undef __argp_fmtstream_printf
|
||||
#define __argp_fmtstream_printf argp_fmtstream_printf
|
||||
#undef __argp_fmtstream_set_lmargin
|
||||
#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin
|
||||
#undef __argp_fmtstream_set_rmargin
|
||||
#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin
|
||||
#undef __argp_fmtstream_set_wmargin
|
||||
#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin
|
||||
#undef __argp_fmtstream_point
|
||||
#define __argp_fmtstream_point argp_fmtstream_point
|
||||
#undef __argp_fmtstream_update
|
||||
#define __argp_fmtstream_update _argp_fmtstream_update
|
||||
#undef __argp_fmtstream_ensure
|
||||
#define __argp_fmtstream_ensure _argp_fmtstream_ensure
|
||||
#undef __argp_fmtstream_lmargin
|
||||
#define __argp_fmtstream_lmargin argp_fmtstream_lmargin
|
||||
#undef __argp_fmtstream_rmargin
|
||||
#define __argp_fmtstream_rmargin argp_fmtstream_rmargin
|
||||
#undef __argp_fmtstream_wmargin
|
||||
#define __argp_fmtstream_wmargin argp_fmtstream_wmargin
|
||||
|
||||
#include "mempcpy.h"
|
||||
#include "strcase.h"
|
||||
#include "strchrnul.h"
|
||||
#include "strndup.h"
|
||||
|
||||
/* normal libc functions we call */
|
||||
#undef __flockfile
|
||||
#define __flockfile flockfile
|
||||
#undef __funlockfile
|
||||
#define __funlockfile funlockfile
|
||||
#undef __mempcpy
|
||||
#define __mempcpy mempcpy
|
||||
#undef __sleep
|
||||
#define __sleep sleep
|
||||
#undef __strcasecmp
|
||||
#define __strcasecmp strcasecmp
|
||||
#undef __strchrnul
|
||||
#define __strchrnul strchrnul
|
||||
#undef __strerror_r
|
||||
#define __strerror_r strerror_r
|
||||
#undef __strndup
|
||||
#define __strndup strndup
|
||||
#undef __vsnprintf
|
||||
#define __vsnprintf vsnprintf
|
||||
|
||||
#if defined(HAVE_DECL_CLEARERR_UNLOCKED) && !HAVE_DECL_CLEARERR_UNLOCKED
|
||||
# define clearerr_unlocked(x) clearerr (x)
|
||||
#endif
|
||||
#if defined(HAVE_DECL_FEOF_UNLOCKED) && !HAVE_DECL_FEOF_UNLOCKED
|
||||
# define feof_unlocked(x) feof (x)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_FERROR_UNLOCKED) && !HAVE_DECL_FERROR_UNLOCKED
|
||||
# define ferror_unlocked(x) ferror (x)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_FFLUSH_UNLOCKED) && !HAVE_DECL_FFLUSH_UNLOCKED
|
||||
# define fflush_unlocked(x) fflush (x)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_FGETS_UNLOCKED) && !HAVE_DECL_FGETS_UNLOCKED
|
||||
# define fgets_unlocked(x,y,z) fgets (x,y,z)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_FPUTC_UNLOCKED) && !HAVE_DECL_FPUTC_UNLOCKED
|
||||
# define fputc_unlocked(x,y) fputc (x,y)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED
|
||||
# define fputs_unlocked(x,y) fputs (x,y)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_FREAD_UNLOCKED) && !HAVE_DECL_FREAD_UNLOCKED
|
||||
# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED
|
||||
# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_GETC_UNLOCKED) && !HAVE_DECL_GETC_UNLOCKED
|
||||
# define getc_unlocked(x) getc (x)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_GETCHAR_UNLOCKED) && !HAVE_DECL_GETCHAR_UNLOCKED
|
||||
# define getchar_unlocked() getchar ()
|
||||
# endif
|
||||
#if defined(HAVE_DECL_PUTC_UNLOCKED) && !HAVE_DECL_PUTC_UNLOCKED
|
||||
# define putc_unlocked(x,y) putc (x,y)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_PUTCHAR_UNLOCKED) && !HAVE_DECL_PUTCHAR_UNLOCKED
|
||||
# define putchar_unlocked(x) putchar (x)
|
||||
# endif
|
||||
|
||||
extern char *__argp_basename (char *name);
|
||||
|
||||
#endif /* !_LIBC */
|
||||
|
||||
#ifndef __set_errno
|
||||
#define __set_errno(e) (errno = (e))
|
||||
#endif
|
||||
|
||||
#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
|
||||
# define __argp_short_program_name() (program_invocation_short_name)
|
||||
#else
|
||||
extern char *__argp_short_program_name (void);
|
||||
#endif
|
||||
@@ -1,926 +0,0 @@
|
||||
/* Hierarchial argument parsing, layered over getopt
|
||||
Copyright (C) 1995-2000, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <alloca.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <getopt.h>
|
||||
#include <getopt_int.h>
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <libintl.h>
|
||||
# undef dgettext
|
||||
# define dgettext(domain, msgid) \
|
||||
INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES)
|
||||
#else
|
||||
# include "gettext.h"
|
||||
#endif
|
||||
#define N_(msgid) (msgid)
|
||||
|
||||
#include "argp.h"
|
||||
#include "argp-namefrob.h"
|
||||
|
||||
/* Getopt return values. */
|
||||
#define KEY_END (-1) /* The end of the options. */
|
||||
#define KEY_ARG 1 /* A non-option argument. */
|
||||
#define KEY_ERR '?' /* An error parsing the options. */
|
||||
|
||||
/* The meta-argument used to prevent any further arguments being interpreted
|
||||
as options. */
|
||||
#define QUOTE "--"
|
||||
|
||||
/* The number of bits we steal in a long-option value for our own use. */
|
||||
#define GROUP_BITS CHAR_BIT
|
||||
|
||||
/* The number of bits available for the user value. */
|
||||
#define USER_BITS ((sizeof ((struct option *)0)->val * CHAR_BIT) - GROUP_BITS)
|
||||
#define USER_MASK ((1 << USER_BITS) - 1)
|
||||
|
||||
/* EZ alias for ARGP_ERR_UNKNOWN. */
|
||||
#define EBADKEY ARGP_ERR_UNKNOWN
|
||||
|
||||
/* Default options. */
|
||||
|
||||
/* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep
|
||||
for one second intervals, decrementing _ARGP_HANG until it's zero. Thus
|
||||
you can force the program to continue by attaching a debugger and setting
|
||||
it to 0 yourself. */
|
||||
static volatile int _argp_hang;
|
||||
|
||||
#define OPT_PROGNAME -2
|
||||
#define OPT_USAGE -3
|
||||
#define OPT_HANG -4
|
||||
|
||||
static const struct argp_option argp_default_options[] =
|
||||
{
|
||||
{"help", '?', 0, 0, N_("Give this help list"), -1},
|
||||
{"usage", OPT_USAGE, 0, 0, N_("Give a short usage message"), 0},
|
||||
{"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, N_("Set the program name"), 0},
|
||||
{"HANG", OPT_HANG, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
|
||||
N_("Hang for SECS seconds (default 3600)"), 0},
|
||||
{NULL, 0, 0, 0, NULL, 0}
|
||||
};
|
||||
|
||||
static error_t
|
||||
argp_default_parser (int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case '?':
|
||||
__argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
|
||||
break;
|
||||
case OPT_USAGE:
|
||||
__argp_state_help (state, state->out_stream,
|
||||
ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
|
||||
break;
|
||||
|
||||
case OPT_PROGNAME: /* Set the program name. */
|
||||
#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_NAME
|
||||
program_invocation_name = arg;
|
||||
#endif
|
||||
/* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka
|
||||
__PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined
|
||||
to be that, so we have to be a bit careful here.] */
|
||||
|
||||
/* Update what we use for messages. */
|
||||
state->name = strrchr (arg, '/');
|
||||
if (state->name)
|
||||
state->name++;
|
||||
else
|
||||
state->name = arg;
|
||||
|
||||
#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
|
||||
program_invocation_short_name = state->name;
|
||||
#endif
|
||||
|
||||
if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS))
|
||||
== ARGP_PARSE_ARGV0)
|
||||
/* Update what getopt uses too. */
|
||||
state->argv[0] = arg;
|
||||
|
||||
break;
|
||||
|
||||
case OPT_HANG:
|
||||
_argp_hang = atoi (arg ? arg : "3600");
|
||||
while (_argp_hang-- > 0)
|
||||
__sleep (1);
|
||||
break;
|
||||
|
||||
default:
|
||||
return EBADKEY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct argp argp_default_argp =
|
||||
{argp_default_options, &argp_default_parser, NULL, NULL, NULL, NULL, "libc"};
|
||||
|
||||
|
||||
static const struct argp_option argp_version_options[] =
|
||||
{
|
||||
{"version", 'V', 0, 0, N_("Print program version"), -1},
|
||||
{NULL, 0, 0, 0, NULL, 0}
|
||||
};
|
||||
|
||||
static error_t
|
||||
argp_version_parser (int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case 'V':
|
||||
if (argp_program_version_hook)
|
||||
(*argp_program_version_hook) (state->out_stream, state);
|
||||
else if (argp_program_version)
|
||||
fprintf (state->out_stream, "%s\n", argp_program_version);
|
||||
else
|
||||
__argp_error (state, dgettext (state->root_argp->argp_domain,
|
||||
"(PROGRAM ERROR) No version known!?"));
|
||||
if (! (state->flags & ARGP_NO_EXIT))
|
||||
exit (0);
|
||||
break;
|
||||
default:
|
||||
return EBADKEY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct argp argp_version_argp =
|
||||
{argp_version_options, &argp_version_parser, NULL, NULL, NULL, NULL, "libc"};
|
||||
|
||||
/* Returns the offset into the getopt long options array LONG_OPTIONS of a
|
||||
long option with called NAME, or -1 if none is found. Passing NULL as
|
||||
NAME will return the number of options. */
|
||||
static int
|
||||
find_long_option (struct option *long_options, const char *name)
|
||||
{
|
||||
struct option *l = long_options;
|
||||
while (l->name != NULL)
|
||||
if (name != NULL && strcmp (l->name, name) == 0)
|
||||
return l - long_options;
|
||||
else
|
||||
l++;
|
||||
if (name == NULL)
|
||||
return l - long_options;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* The state of a `group' during parsing. Each group corresponds to a
|
||||
particular argp structure from the tree of such descending from the top
|
||||
level argp passed to argp_parse. */
|
||||
struct group
|
||||
{
|
||||
/* This group's parsing function. */
|
||||
argp_parser_t parser;
|
||||
|
||||
/* Which argp this group is from. */
|
||||
const struct argp *argp;
|
||||
|
||||
/* Points to the point in SHORT_OPTS corresponding to the end of the short
|
||||
options for this group. We use it to determine from which group a
|
||||
particular short options is from. */
|
||||
char *short_end;
|
||||
|
||||
/* The number of non-option args sucessfully handled by this parser. */
|
||||
unsigned args_processed;
|
||||
|
||||
/* This group's parser's parent's group. */
|
||||
struct group *parent;
|
||||
unsigned parent_index; /* And the our position in the parent. */
|
||||
|
||||
/* These fields are swapped into and out of the state structure when
|
||||
calling this group's parser. */
|
||||
void *input, **child_inputs;
|
||||
void *hook;
|
||||
};
|
||||
|
||||
/* Call GROUP's parser with KEY and ARG, swapping any group-specific info
|
||||
from STATE before calling, and back into state afterwards. If GROUP has
|
||||
no parser, EBADKEY is returned. */
|
||||
static error_t
|
||||
group_parse (struct group *group, struct argp_state *state, int key, char *arg)
|
||||
{
|
||||
if (group->parser)
|
||||
{
|
||||
error_t err;
|
||||
state->hook = group->hook;
|
||||
state->input = group->input;
|
||||
state->child_inputs = group->child_inputs;
|
||||
state->arg_num = group->args_processed;
|
||||
err = (*group->parser)(key, arg, state);
|
||||
group->hook = state->hook;
|
||||
return err;
|
||||
}
|
||||
else
|
||||
return EBADKEY;
|
||||
}
|
||||
|
||||
struct parser
|
||||
{
|
||||
const struct argp *argp;
|
||||
|
||||
/* SHORT_OPTS is the getopt short options string for the union of all the
|
||||
groups of options. */
|
||||
char *short_opts;
|
||||
/* LONG_OPTS is the array of getop long option structures for the union of
|
||||
all the groups of options. */
|
||||
struct option *long_opts;
|
||||
/* OPT_DATA is the getopt data used for the re-entrant getopt. */
|
||||
struct _getopt_data opt_data;
|
||||
|
||||
/* States of the various parsing groups. */
|
||||
struct group *groups;
|
||||
/* The end of the GROUPS array. */
|
||||
struct group *egroup;
|
||||
/* An vector containing storage for the CHILD_INPUTS field in all groups. */
|
||||
void **child_inputs;
|
||||
|
||||
/* True if we think using getopt is still useful; if false, then
|
||||
remaining arguments are just passed verbatim with ARGP_KEY_ARG. This is
|
||||
cleared whenever getopt returns KEY_END, but may be set again if the user
|
||||
moves the next argument pointer backwards. */
|
||||
int try_getopt;
|
||||
|
||||
/* State block supplied to parsing routines. */
|
||||
struct argp_state state;
|
||||
|
||||
/* Memory used by this parser. */
|
||||
void *storage;
|
||||
};
|
||||
|
||||
/* The next usable entries in the various parser tables being filled in by
|
||||
convert_options. */
|
||||
struct parser_convert_state
|
||||
{
|
||||
struct parser *parser;
|
||||
char *short_end;
|
||||
struct option *long_end;
|
||||
void **child_inputs_end;
|
||||
};
|
||||
|
||||
/* Converts all options in ARGP (which is put in GROUP) and ancestors
|
||||
into getopt options stored in SHORT_OPTS and LONG_OPTS; SHORT_END and
|
||||
CVT->LONG_END are the points at which new options are added. Returns the
|
||||
next unused group entry. CVT holds state used during the conversion. */
|
||||
static struct group *
|
||||
convert_options (const struct argp *argp,
|
||||
struct group *parent, unsigned parent_index,
|
||||
struct group *group, struct parser_convert_state *cvt)
|
||||
{
|
||||
/* REAL is the most recent non-alias value of OPT. */
|
||||
const struct argp_option *real = argp->options;
|
||||
const struct argp_child *children = argp->children;
|
||||
|
||||
if (real || argp->parser)
|
||||
{
|
||||
const struct argp_option *opt;
|
||||
|
||||
if (real)
|
||||
for (opt = real; !__option_is_end (opt); opt++)
|
||||
{
|
||||
if (! (opt->flags & OPTION_ALIAS))
|
||||
/* OPT isn't an alias, so we can use values from it. */
|
||||
real = opt;
|
||||
|
||||
if (! (real->flags & OPTION_DOC))
|
||||
/* A real option (not just documentation). */
|
||||
{
|
||||
if (__option_is_short (opt))
|
||||
/* OPT can be used as a short option. */
|
||||
{
|
||||
*cvt->short_end++ = opt->key;
|
||||
if (real->arg)
|
||||
{
|
||||
*cvt->short_end++ = ':';
|
||||
if (real->flags & OPTION_ARG_OPTIONAL)
|
||||
*cvt->short_end++ = ':';
|
||||
}
|
||||
*cvt->short_end = '\0'; /* keep 0 terminated */
|
||||
}
|
||||
|
||||
if (opt->name
|
||||
&& find_long_option (cvt->parser->long_opts, opt->name) < 0)
|
||||
/* OPT can be used as a long option. */
|
||||
{
|
||||
cvt->long_end->name = opt->name;
|
||||
cvt->long_end->has_arg =
|
||||
(real->arg
|
||||
? (real->flags & OPTION_ARG_OPTIONAL
|
||||
? optional_argument
|
||||
: required_argument)
|
||||
: no_argument);
|
||||
cvt->long_end->flag = 0;
|
||||
/* we add a disambiguating code to all the user's
|
||||
values (which is removed before we actually call
|
||||
the function to parse the value); this means that
|
||||
the user loses use of the high 8 bits in all his
|
||||
values (the sign of the lower bits is preserved
|
||||
however)... */
|
||||
cvt->long_end->val =
|
||||
((opt->key | real->key) & USER_MASK)
|
||||
+ (((group - cvt->parser->groups) + 1) << USER_BITS);
|
||||
|
||||
/* Keep the LONG_OPTS list terminated. */
|
||||
(++cvt->long_end)->name = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group->parser = argp->parser;
|
||||
group->argp = argp;
|
||||
group->short_end = cvt->short_end;
|
||||
group->args_processed = 0;
|
||||
group->parent = parent;
|
||||
group->parent_index = parent_index;
|
||||
group->input = 0;
|
||||
group->hook = 0;
|
||||
group->child_inputs = 0;
|
||||
|
||||
if (children)
|
||||
/* Assign GROUP's CHILD_INPUTS field some space from
|
||||
CVT->child_inputs_end.*/
|
||||
{
|
||||
unsigned num_children = 0;
|
||||
while (children[num_children].argp)
|
||||
num_children++;
|
||||
group->child_inputs = cvt->child_inputs_end;
|
||||
cvt->child_inputs_end += num_children;
|
||||
}
|
||||
|
||||
parent = group++;
|
||||
}
|
||||
else
|
||||
parent = 0;
|
||||
|
||||
if (children)
|
||||
{
|
||||
unsigned index = 0;
|
||||
while (children->argp)
|
||||
group =
|
||||
convert_options (children++->argp, parent, index++, group, cvt);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Find the merged set of getopt options, with keys appropiately prefixed. */
|
||||
static void
|
||||
parser_convert (struct parser *parser, const struct argp *argp, int flags)
|
||||
{
|
||||
struct parser_convert_state cvt;
|
||||
|
||||
cvt.parser = parser;
|
||||
cvt.short_end = parser->short_opts;
|
||||
cvt.long_end = parser->long_opts;
|
||||
cvt.child_inputs_end = parser->child_inputs;
|
||||
|
||||
if (flags & ARGP_IN_ORDER)
|
||||
*cvt.short_end++ = '-';
|
||||
else if (flags & ARGP_NO_ARGS)
|
||||
*cvt.short_end++ = '+';
|
||||
*cvt.short_end = '\0';
|
||||
|
||||
cvt.long_end->name = NULL;
|
||||
|
||||
parser->argp = argp;
|
||||
|
||||
if (argp)
|
||||
parser->egroup = convert_options (argp, 0, 0, parser->groups, &cvt);
|
||||
else
|
||||
parser->egroup = parser->groups; /* No parsers at all! */
|
||||
}
|
||||
|
||||
/* Lengths of various parser fields which we will allocated. */
|
||||
struct parser_sizes
|
||||
{
|
||||
size_t short_len; /* Getopt short options string. */
|
||||
size_t long_len; /* Getopt long options vector. */
|
||||
size_t num_groups; /* Group structures we allocate. */
|
||||
size_t num_child_inputs; /* Child input slots. */
|
||||
};
|
||||
|
||||
/* For ARGP, increments the NUM_GROUPS field in SZS by the total number of
|
||||
argp structures descended from it, and the SHORT_LEN & LONG_LEN fields by
|
||||
the maximum lengths of the resulting merged getopt short options string and
|
||||
long-options array, respectively. */
|
||||
static void
|
||||
calc_sizes (const struct argp *argp, struct parser_sizes *szs)
|
||||
{
|
||||
const struct argp_child *child = argp->children;
|
||||
const struct argp_option *opt = argp->options;
|
||||
|
||||
if (opt || argp->parser)
|
||||
{
|
||||
szs->num_groups++;
|
||||
if (opt)
|
||||
{
|
||||
int num_opts = 0;
|
||||
while (!__option_is_end (opt++))
|
||||
num_opts++;
|
||||
szs->short_len += num_opts * 3; /* opt + up to 2 `:'s */
|
||||
szs->long_len += num_opts;
|
||||
}
|
||||
}
|
||||
|
||||
if (child)
|
||||
while (child->argp)
|
||||
{
|
||||
calc_sizes ((child++)->argp, szs);
|
||||
szs->num_child_inputs++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initializes PARSER to parse ARGP in a manner described by FLAGS. */
|
||||
static error_t
|
||||
parser_init (struct parser *parser, const struct argp *argp,
|
||||
int argc, char **argv, int flags, void *input)
|
||||
{
|
||||
error_t err = 0;
|
||||
struct group *group;
|
||||
struct parser_sizes szs;
|
||||
struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER;
|
||||
|
||||
szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1;
|
||||
szs.long_len = 0;
|
||||
szs.num_groups = 0;
|
||||
szs.num_child_inputs = 0;
|
||||
|
||||
if (argp)
|
||||
calc_sizes (argp, &szs);
|
||||
|
||||
/* Lengths of the various bits of storage used by PARSER. */
|
||||
#define GLEN (szs.num_groups + 1) * sizeof (struct group)
|
||||
#define CLEN (szs.num_child_inputs * sizeof (void *))
|
||||
#define LLEN ((szs.long_len + 1) * sizeof (struct option))
|
||||
#define SLEN (szs.short_len + 1)
|
||||
|
||||
parser->storage = malloc (GLEN + CLEN + LLEN + SLEN);
|
||||
if (! parser->storage)
|
||||
return ENOMEM;
|
||||
|
||||
parser->groups = parser->storage;
|
||||
parser->child_inputs = parser->storage + GLEN;
|
||||
parser->long_opts = parser->storage + GLEN + CLEN;
|
||||
parser->short_opts = parser->storage + GLEN + CLEN + LLEN;
|
||||
parser->opt_data = opt_data;
|
||||
|
||||
memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *));
|
||||
parser_convert (parser, argp, flags);
|
||||
|
||||
memset (&parser->state, 0, sizeof (struct argp_state));
|
||||
parser->state.root_argp = parser->argp;
|
||||
parser->state.argc = argc;
|
||||
parser->state.argv = argv;
|
||||
parser->state.flags = flags;
|
||||
parser->state.err_stream = stderr;
|
||||
parser->state.out_stream = stdout;
|
||||
parser->state.next = 0; /* Tell getopt to initialize. */
|
||||
parser->state.pstate = parser;
|
||||
|
||||
parser->try_getopt = 1;
|
||||
|
||||
/* Call each parser for the first time, giving it a chance to propagate
|
||||
values to child parsers. */
|
||||
if (parser->groups < parser->egroup)
|
||||
parser->groups->input = input;
|
||||
for (group = parser->groups;
|
||||
group < parser->egroup && (!err || err == EBADKEY);
|
||||
group++)
|
||||
{
|
||||
if (group->parent)
|
||||
/* If a child parser, get the initial input value from the parent. */
|
||||
group->input = group->parent->child_inputs[group->parent_index];
|
||||
|
||||
if (!group->parser
|
||||
&& group->argp->children && group->argp->children->argp)
|
||||
/* For the special case where no parsing function is supplied for an
|
||||
argp, propagate its input to its first child, if any (this just
|
||||
makes very simple wrapper argps more convenient). */
|
||||
group->child_inputs[0] = group->input;
|
||||
|
||||
err = group_parse (group, &parser->state, ARGP_KEY_INIT, 0);
|
||||
}
|
||||
if (err == EBADKEY)
|
||||
err = 0; /* Some parser didn't understand. */
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (parser->state.flags & ARGP_NO_ERRS)
|
||||
{
|
||||
parser->opt_data.opterr = 0;
|
||||
if (parser->state.flags & ARGP_PARSE_ARGV0)
|
||||
/* getopt always skips ARGV[0], so we have to fake it out. As long
|
||||
as OPTERR is 0, then it shouldn't actually try to access it. */
|
||||
parser->state.argv--, parser->state.argc++;
|
||||
}
|
||||
else
|
||||
parser->opt_data.opterr = 1; /* Print error messages. */
|
||||
|
||||
if (parser->state.argv == argv && argv[0])
|
||||
/* There's an argv[0]; use it for messages. */
|
||||
{
|
||||
char *short_name = strrchr (argv[0], '/');
|
||||
parser->state.name = short_name ? short_name + 1 : argv[0];
|
||||
}
|
||||
else
|
||||
parser->state.name = __argp_short_program_name ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Free any storage consumed by PARSER (but not PARSER itself). */
|
||||
static error_t
|
||||
parser_finalize (struct parser *parser,
|
||||
error_t err, int arg_ebadkey, int *end_index)
|
||||
{
|
||||
struct group *group;
|
||||
|
||||
if (err == EBADKEY && arg_ebadkey)
|
||||
/* Suppress errors generated by unparsed arguments. */
|
||||
err = 0;
|
||||
|
||||
if (! err)
|
||||
{
|
||||
if (parser->state.next == parser->state.argc)
|
||||
/* We successfully parsed all arguments! Call all the parsers again,
|
||||
just a few more times... */
|
||||
{
|
||||
for (group = parser->groups;
|
||||
group < parser->egroup && (!err || err==EBADKEY);
|
||||
group++)
|
||||
if (group->args_processed == 0)
|
||||
err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0);
|
||||
for (group = parser->egroup - 1;
|
||||
group >= parser->groups && (!err || err==EBADKEY);
|
||||
group--)
|
||||
err = group_parse (group, &parser->state, ARGP_KEY_END, 0);
|
||||
|
||||
if (err == EBADKEY)
|
||||
err = 0; /* Some parser didn't understand. */
|
||||
|
||||
/* Tell the user that all arguments are parsed. */
|
||||
if (end_index)
|
||||
*end_index = parser->state.next;
|
||||
}
|
||||
else if (end_index)
|
||||
/* Return any remaining arguments to the user. */
|
||||
*end_index = parser->state.next;
|
||||
else
|
||||
/* No way to return the remaining arguments, they must be bogus. */
|
||||
{
|
||||
if (!(parser->state.flags & ARGP_NO_ERRS)
|
||||
&& parser->state.err_stream)
|
||||
fprintf (parser->state.err_stream,
|
||||
dgettext (parser->argp->argp_domain,
|
||||
"%s: Too many arguments\n"),
|
||||
parser->state.name);
|
||||
err = EBADKEY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Okay, we're all done, with either an error or success; call the parsers
|
||||
to indicate which one. */
|
||||
|
||||
if (err)
|
||||
{
|
||||
/* Maybe print an error message. */
|
||||
if (err == EBADKEY)
|
||||
/* An appropriate message describing what the error was should have
|
||||
been printed earlier. */
|
||||
__argp_state_help (&parser->state, parser->state.err_stream,
|
||||
ARGP_HELP_STD_ERR);
|
||||
|
||||
/* Since we didn't exit, give each parser an error indication. */
|
||||
for (group = parser->groups; group < parser->egroup; group++)
|
||||
group_parse (group, &parser->state, ARGP_KEY_ERROR, 0);
|
||||
}
|
||||
else
|
||||
/* Notify parsers of success, and propagate back values from parsers. */
|
||||
{
|
||||
/* We pass over the groups in reverse order so that child groups are
|
||||
given a chance to do there processing before passing back a value to
|
||||
the parent. */
|
||||
for (group = parser->egroup - 1
|
||||
; group >= parser->groups && (!err || err == EBADKEY)
|
||||
; group--)
|
||||
err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0);
|
||||
if (err == EBADKEY)
|
||||
err = 0; /* Some parser didn't understand. */
|
||||
}
|
||||
|
||||
/* Call parsers once more, to do any final cleanup. Errors are ignored. */
|
||||
for (group = parser->egroup - 1; group >= parser->groups; group--)
|
||||
group_parse (group, &parser->state, ARGP_KEY_FINI, 0);
|
||||
|
||||
if (err == EBADKEY)
|
||||
err = EINVAL;
|
||||
|
||||
free (parser->storage);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Call the user parsers to parse the non-option argument VAL, at the current
|
||||
position, returning any error. The state NEXT pointer is assumed to have
|
||||
been adjusted (by getopt) to point after this argument; this function will
|
||||
adjust it correctly to reflect however many args actually end up being
|
||||
consumed. */
|
||||
static error_t
|
||||
parser_parse_arg (struct parser *parser, char *val)
|
||||
{
|
||||
/* Save the starting value of NEXT, first adjusting it so that the arg
|
||||
we're parsing is again the front of the arg vector. */
|
||||
int index = --parser->state.next;
|
||||
error_t err = EBADKEY;
|
||||
struct group *group;
|
||||
int key = 0; /* Which of ARGP_KEY_ARG[S] we used. */
|
||||
|
||||
/* Try to parse the argument in each parser. */
|
||||
for (group = parser->groups
|
||||
; group < parser->egroup && err == EBADKEY
|
||||
; group++)
|
||||
{
|
||||
parser->state.next++; /* For ARGP_KEY_ARG, consume the arg. */
|
||||
key = ARGP_KEY_ARG;
|
||||
err = group_parse (group, &parser->state, key, val);
|
||||
|
||||
if (err == EBADKEY)
|
||||
/* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */
|
||||
{
|
||||
parser->state.next--; /* For ARGP_KEY_ARGS, put back the arg. */
|
||||
key = ARGP_KEY_ARGS;
|
||||
err = group_parse (group, &parser->state, key, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (! err)
|
||||
{
|
||||
if (key == ARGP_KEY_ARGS)
|
||||
/* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't
|
||||
changed by the user, *all* arguments should be considered
|
||||
consumed. */
|
||||
parser->state.next = parser->state.argc;
|
||||
|
||||
if (parser->state.next > index)
|
||||
/* Remember that we successfully processed a non-option
|
||||
argument -- but only if the user hasn't gotten tricky and set
|
||||
the clock back. */
|
||||
(--group)->args_processed += (parser->state.next - index);
|
||||
else
|
||||
/* The user wants to reparse some args, give getopt another try. */
|
||||
parser->try_getopt = 1;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Call the user parsers to parse the option OPT, with argument VAL, at the
|
||||
current position, returning any error. */
|
||||
static error_t
|
||||
parser_parse_opt (struct parser *parser, int opt, char *val)
|
||||
{
|
||||
/* The group key encoded in the high bits; 0 for short opts or
|
||||
group_number + 1 for long opts. */
|
||||
int group_key = opt >> USER_BITS;
|
||||
error_t err = EBADKEY;
|
||||
|
||||
if (group_key == 0)
|
||||
/* A short option. By comparing OPT's position in SHORT_OPTS to the
|
||||
various starting positions in each group's SHORT_END field, we can
|
||||
determine which group OPT came from. */
|
||||
{
|
||||
struct group *group;
|
||||
char *short_index = strchr (parser->short_opts, opt);
|
||||
|
||||
if (short_index)
|
||||
for (group = parser->groups; group < parser->egroup; group++)
|
||||
if (group->short_end > short_index)
|
||||
{
|
||||
err = group_parse (group, &parser->state, opt,
|
||||
parser->opt_data.optarg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* A long option. We use shifts instead of masking for extracting
|
||||
the user value in order to preserve the sign. */
|
||||
err =
|
||||
group_parse (&parser->groups[group_key - 1], &parser->state,
|
||||
(opt << GROUP_BITS) >> GROUP_BITS,
|
||||
parser->opt_data.optarg);
|
||||
|
||||
if (err == EBADKEY)
|
||||
/* At least currently, an option not recognized is an error in the
|
||||
parser, because we pre-compute which parser is supposed to deal
|
||||
with each option. */
|
||||
{
|
||||
static const char bad_key_err[] =
|
||||
N_("(PROGRAM ERROR) Option should have been recognized!?");
|
||||
if (group_key == 0)
|
||||
__argp_error (&parser->state, "-%c: %s", opt,
|
||||
dgettext (parser->argp->argp_domain, bad_key_err));
|
||||
else
|
||||
{
|
||||
struct option *long_opt = parser->long_opts;
|
||||
while (long_opt->val != opt && long_opt->name)
|
||||
long_opt++;
|
||||
__argp_error (&parser->state, "--%s: %s",
|
||||
long_opt->name ? long_opt->name : "???",
|
||||
dgettext (parser->argp->argp_domain, bad_key_err));
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Parse the next argument in PARSER (as indicated by PARSER->state.next).
|
||||
Any error from the parsers is returned, and *ARGP_EBADKEY indicates
|
||||
whether a value of EBADKEY is due to an unrecognized argument (which is
|
||||
generally not fatal). */
|
||||
static error_t
|
||||
parser_parse_next (struct parser *parser, int *arg_ebadkey)
|
||||
{
|
||||
int opt;
|
||||
error_t err = 0;
|
||||
|
||||
if (parser->state.quoted && parser->state.next < parser->state.quoted)
|
||||
/* The next argument pointer has been moved to before the quoted
|
||||
region, so pretend we never saw the quoting `--', and give getopt
|
||||
another chance. If the user hasn't removed it, getopt will just
|
||||
process it again. */
|
||||
parser->state.quoted = 0;
|
||||
|
||||
if (parser->try_getopt && !parser->state.quoted)
|
||||
/* Give getopt a chance to parse this. */
|
||||
{
|
||||
/* Put it back in OPTIND for getopt. */
|
||||
parser->opt_data.optind = parser->state.next;
|
||||
/* Distinguish KEY_ERR from a real option. */
|
||||
parser->opt_data.optopt = KEY_END;
|
||||
if (parser->state.flags & ARGP_LONG_ONLY)
|
||||
opt = _getopt_long_only_r (parser->state.argc, parser->state.argv,
|
||||
parser->short_opts, parser->long_opts, 0,
|
||||
&parser->opt_data);
|
||||
else
|
||||
opt = _getopt_long_r (parser->state.argc, parser->state.argv,
|
||||
parser->short_opts, parser->long_opts, 0,
|
||||
&parser->opt_data);
|
||||
/* And see what getopt did. */
|
||||
parser->state.next = parser->opt_data.optind;
|
||||
|
||||
if (opt == KEY_END)
|
||||
/* Getopt says there are no more options, so stop using
|
||||
getopt; we'll continue if necessary on our own. */
|
||||
{
|
||||
parser->try_getopt = 0;
|
||||
if (parser->state.next > 1
|
||||
&& strcmp (parser->state.argv[parser->state.next - 1], QUOTE)
|
||||
== 0)
|
||||
/* Not only is this the end of the options, but it's a
|
||||
`quoted' region, which may have args that *look* like
|
||||
options, so we definitely shouldn't try to use getopt past
|
||||
here, whatever happens. */
|
||||
parser->state.quoted = parser->state.next;
|
||||
}
|
||||
else if (opt == KEY_ERR && parser->opt_data.optopt != KEY_END)
|
||||
/* KEY_ERR can have the same value as a valid user short
|
||||
option, but in the case of a real error, getopt sets OPTOPT
|
||||
to the offending character, which can never be KEY_END. */
|
||||
{
|
||||
*arg_ebadkey = 0;
|
||||
return EBADKEY;
|
||||
}
|
||||
}
|
||||
else
|
||||
opt = KEY_END;
|
||||
|
||||
if (opt == KEY_END)
|
||||
{
|
||||
/* We're past what getopt considers the options. */
|
||||
if (parser->state.next >= parser->state.argc
|
||||
|| (parser->state.flags & ARGP_NO_ARGS))
|
||||
/* Indicate that we're done. */
|
||||
{
|
||||
*arg_ebadkey = 1;
|
||||
return EBADKEY;
|
||||
}
|
||||
else
|
||||
/* A non-option arg; simulate what getopt might have done. */
|
||||
{
|
||||
opt = KEY_ARG;
|
||||
parser->opt_data.optarg = parser->state.argv[parser->state.next++];
|
||||
}
|
||||
}
|
||||
|
||||
if (opt == KEY_ARG)
|
||||
/* A non-option argument; try each parser in turn. */
|
||||
err = parser_parse_arg (parser, parser->opt_data.optarg);
|
||||
else
|
||||
err = parser_parse_opt (parser, opt, parser->opt_data.optarg);
|
||||
|
||||
if (err == EBADKEY)
|
||||
*arg_ebadkey = (opt == KEY_END || opt == KEY_ARG);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Parse the options strings in ARGC & ARGV according to the argp in ARGP.
|
||||
FLAGS is one of the ARGP_ flags above. If END_INDEX is non-NULL, the
|
||||
index in ARGV of the first unparsed option is returned in it. If an
|
||||
unknown option is present, EINVAL is returned; if some parser routine
|
||||
returned a non-zero value, it is returned; otherwise 0 is returned. */
|
||||
error_t
|
||||
__argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags,
|
||||
int *end_index, void *input)
|
||||
{
|
||||
error_t err;
|
||||
struct parser parser;
|
||||
|
||||
/* If true, then err == EBADKEY is a result of a non-option argument failing
|
||||
to be parsed (which in some cases isn't actually an error). */
|
||||
int arg_ebadkey = 0;
|
||||
|
||||
if (! (flags & ARGP_NO_HELP))
|
||||
/* Add our own options. */
|
||||
{
|
||||
struct argp_child *child = alloca (4 * sizeof (struct argp_child));
|
||||
struct argp *top_argp = alloca (sizeof (struct argp));
|
||||
|
||||
/* TOP_ARGP has no options, it just serves to group the user & default
|
||||
argps. */
|
||||
memset (top_argp, 0, sizeof (*top_argp));
|
||||
top_argp->children = child;
|
||||
|
||||
memset (child, 0, 4 * sizeof (struct argp_child));
|
||||
|
||||
if (argp)
|
||||
(child++)->argp = argp;
|
||||
(child++)->argp = &argp_default_argp;
|
||||
if (argp_program_version || argp_program_version_hook)
|
||||
(child++)->argp = &argp_version_argp;
|
||||
child->argp = 0;
|
||||
|
||||
argp = top_argp;
|
||||
}
|
||||
|
||||
/* Construct a parser for these arguments. */
|
||||
err = parser_init (&parser, argp, argc, argv, flags, input);
|
||||
|
||||
if (! err)
|
||||
/* Parse! */
|
||||
{
|
||||
while (! err)
|
||||
err = parser_parse_next (&parser, &arg_ebadkey);
|
||||
err = parser_finalize (&parser, err, arg_ebadkey, end_index);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
#ifdef weak_alias
|
||||
weak_alias (__argp_parse, argp_parse)
|
||||
#endif
|
||||
|
||||
/* Return the input field for ARGP in the parser corresponding to STATE; used
|
||||
by the help routines. */
|
||||
void *
|
||||
__argp_input (const struct argp *argp, const struct argp_state *state)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
struct group *group;
|
||||
struct parser *parser = state->pstate;
|
||||
|
||||
for (group = parser->groups; group < parser->egroup; group++)
|
||||
if (group->argp == argp)
|
||||
return group->input;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#ifdef weak_alias
|
||||
weak_alias (__argp_input, _argp_input)
|
||||
#endif
|
||||
@@ -1,24 +0,0 @@
|
||||
/* Default definition for ARGP_PROGRAM_VERSION.
|
||||
Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* If set by the user program to a non-zero value, then a default option
|
||||
--version is added (unless the ARGP_NO_HELP flag is used), which will
|
||||
print this this string followed by a newline and exit (unless the
|
||||
ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */
|
||||
const char *argp_program_version;
|
||||
@@ -1,31 +0,0 @@
|
||||
/* Default definition for ARGP_PROGRAM_VERSION_HOOK.
|
||||
Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "argp.h"
|
||||
|
||||
/* If set by the user program to a non-zero value, then a default option
|
||||
--version is added (unless the ARGP_NO_HELP flag is used), which calls
|
||||
this function with a stream to print the version to and a pointer to the
|
||||
current parsing state, and then exits (unless the ARGP_NO_EXIT flag is
|
||||
used). This variable takes precedent over ARGP_PROGRAM_VERSION. */
|
||||
void (*argp_program_version_hook) (FILE *stream, struct argp_state *state) = NULL;
|
||||
@@ -1,43 +0,0 @@
|
||||
/* Real definitions for extern inline functions in argp.h
|
||||
Copyright (C) 1997, 1998, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined _LIBC || defined HAVE_FEATURES_H
|
||||
# include <features.h>
|
||||
#endif
|
||||
|
||||
#ifndef __USE_EXTERN_INLINES
|
||||
# define __USE_EXTERN_INLINES 1
|
||||
#endif
|
||||
#define ARGP_EI
|
||||
#undef __OPTIMIZE__
|
||||
#define __OPTIMIZE__ 1
|
||||
#include "argp.h"
|
||||
|
||||
/* Add weak aliases. */
|
||||
#if _LIBC - 0 && defined (weak_alias)
|
||||
|
||||
weak_alias (__argp_usage, argp_usage)
|
||||
weak_alias (__option_is_short, _option_is_short)
|
||||
weak_alias (__option_is_end, _option_is_end)
|
||||
|
||||
#endif
|
||||
@@ -1,79 +0,0 @@
|
||||
/* basename.c -- return the last element in a path
|
||||
|
||||
Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "dirname.h"
|
||||
#include <string.h>
|
||||
|
||||
/* In general, we can't use the builtin `basename' function if available,
|
||||
since it has different meanings in different environments.
|
||||
In some environments the builtin `basename' modifies its argument.
|
||||
|
||||
Return the address of the last file name component of NAME. If
|
||||
NAME has no file name components because it is all slashes, return
|
||||
NAME if it is empty, the address of its last slash otherwise. */
|
||||
|
||||
char *
|
||||
base_name (char const *name)
|
||||
{
|
||||
char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
|
||||
char const *p;
|
||||
|
||||
for (p = base; *p; p++)
|
||||
{
|
||||
if (ISSLASH (*p))
|
||||
{
|
||||
/* Treat multiple adjacent slashes like a single slash. */
|
||||
do p++;
|
||||
while (ISSLASH (*p));
|
||||
|
||||
/* If the file name ends in slash, use the trailing slash as
|
||||
the basename if no non-slashes have been found. */
|
||||
if (! *p)
|
||||
{
|
||||
if (ISSLASH (*base))
|
||||
base = p - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* *P is a non-slash preceded by a slash. */
|
||||
base = p;
|
||||
}
|
||||
}
|
||||
|
||||
return (char *) base;
|
||||
}
|
||||
|
||||
/* Return the length of of the basename NAME. Typically NAME is the
|
||||
value returned by base_name. Act like strlen (NAME), except omit
|
||||
redundant trailing slashes. */
|
||||
|
||||
size_t
|
||||
base_len (char const *name)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--)
|
||||
continue;
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
/* dirname.c -- return all but the last element in a path
|
||||
|
||||
Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "dirname.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "xalloc.h"
|
||||
|
||||
/* Return the length of `dirname (PATH)', or zero if PATH is
|
||||
in the working directory. Works properly even if
|
||||
there are trailing slashes (by effectively ignoring them). */
|
||||
size_t
|
||||
dir_len (char const *path)
|
||||
{
|
||||
size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (path);
|
||||
size_t length;
|
||||
|
||||
/* Strip the basename and any redundant slashes before it. */
|
||||
for (length = base_name (path) - path; prefix_length < length; length--)
|
||||
if (! ISSLASH (path[length - 1]))
|
||||
return length;
|
||||
|
||||
/* But don't strip the only slash from "/". */
|
||||
return prefix_length + ISSLASH (path[prefix_length]);
|
||||
}
|
||||
|
||||
/* Return the leading directories part of PATH,
|
||||
allocated with xmalloc.
|
||||
Works properly even if there are trailing slashes
|
||||
(by effectively ignoring them). */
|
||||
|
||||
char *
|
||||
dir_name (char const *path)
|
||||
{
|
||||
size_t length = dir_len (path);
|
||||
bool append_dot = (length == FILE_SYSTEM_PREFIX_LEN (path));
|
||||
char *newpath = xmalloc (length + append_dot + 1);
|
||||
memcpy (newpath, path, length);
|
||||
if (append_dot)
|
||||
newpath[length++] = '.';
|
||||
newpath[length] = 0;
|
||||
return newpath;
|
||||
}
|
||||
|
||||
#ifdef TEST_DIRNAME
|
||||
/*
|
||||
|
||||
Run the test like this (expect no output):
|
||||
gcc -DHAVE_CONFIG_H -DTEST_DIRNAME -I.. -O -Wall \
|
||||
basename.c dirname.c xmalloc.c error.c
|
||||
sed -n '/^BEGIN-DATA$/,/^END-DATA$/p' dirname.c|grep -v DATA|./a.out
|
||||
|
||||
If it's been built on a DOS or Windows platforms, run another test like
|
||||
this (again, expect no output):
|
||||
sed -n '/^BEGIN-DOS-DATA$/,/^END-DOS-DATA$/p' dirname.c|grep -v DATA|./a.out
|
||||
|
||||
BEGIN-DATA
|
||||
foo//// .
|
||||
bar/foo//// bar
|
||||
foo/ .
|
||||
/ /
|
||||
. .
|
||||
a .
|
||||
END-DATA
|
||||
|
||||
BEGIN-DOS-DATA
|
||||
c:///// c:/
|
||||
c:/ c:/
|
||||
c:/. c:/
|
||||
c:foo c:.
|
||||
c:foo/bar c:foo
|
||||
END-DOS-DATA
|
||||
|
||||
*/
|
||||
|
||||
# define MAX_BUFF_LEN 1024
|
||||
# include <stdio.h>
|
||||
|
||||
char *program_name;
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
char buff[MAX_BUFF_LEN + 1];
|
||||
|
||||
program_name = argv[0];
|
||||
|
||||
buff[MAX_BUFF_LEN] = 0;
|
||||
while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
|
||||
{
|
||||
char path[MAX_BUFF_LEN];
|
||||
char expected_result[MAX_BUFF_LEN];
|
||||
char const *result;
|
||||
sscanf (buff, "%s %s", path, expected_result);
|
||||
result = dir_name (path);
|
||||
if (strcmp (result, expected_result))
|
||||
printf ("%s: got %s, expected %s\n", path, result, expected_result);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -1,47 +0,0 @@
|
||||
/* Take file names apart into directory and base names.
|
||||
|
||||
Copyright (C) 1998, 2001, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef DIRNAME_H_
|
||||
# define DIRNAME_H_ 1
|
||||
|
||||
# include <stdbool.h>
|
||||
# include <stddef.h>
|
||||
|
||||
# ifndef DIRECTORY_SEPARATOR
|
||||
# define DIRECTORY_SEPARATOR '/'
|
||||
# endif
|
||||
|
||||
# ifndef ISSLASH
|
||||
# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
|
||||
# endif
|
||||
|
||||
# ifndef FILE_SYSTEM_PREFIX_LEN
|
||||
# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
|
||||
# endif
|
||||
|
||||
# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
|
||||
# define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
|
||||
|
||||
char *base_name (char const *path);
|
||||
char *dir_name (char const *path);
|
||||
size_t base_len (char const *path);
|
||||
size_t dir_len (char const *path);
|
||||
|
||||
bool strip_trailing_slashes (char *path);
|
||||
|
||||
#endif /* not DIRNAME_H_ */
|
||||
@@ -1,306 +0,0 @@
|
||||
/* Error handler for noninteractive utilities
|
||||
Copyright (C) 1990-1998, 2000-2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by David MacKenzie <[email protected]>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "error.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <libintl.h>
|
||||
#else
|
||||
# include "gettext.h"
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <wchar.h>
|
||||
# define mbsrtowcs __mbsrtowcs
|
||||
#endif
|
||||
|
||||
#if USE_UNLOCKED_IO
|
||||
# include "unlocked-io.h"
|
||||
#endif
|
||||
|
||||
#ifndef _
|
||||
# define _(String) String
|
||||
#endif
|
||||
|
||||
/* If NULL, error will flush stdout, then print on stderr the program
|
||||
name, a colon and a space. Otherwise, error will call this
|
||||
function without parameters instead. */
|
||||
void (*error_print_progname) (void);
|
||||
|
||||
/* This variable is incremented each time `error' is called. */
|
||||
unsigned int error_message_count;
|
||||
|
||||
#ifdef _LIBC
|
||||
/* In the GNU C library, there is a predefined variable for this. */
|
||||
|
||||
# define program_name program_invocation_name
|
||||
# include <errno.h>
|
||||
# include <libio/libioP.h>
|
||||
|
||||
/* In GNU libc we want do not want to use the common name `error' directly.
|
||||
Instead make it a weak alias. */
|
||||
extern void __error (int status, int errnum, const char *message, ...)
|
||||
__attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
extern void __error_at_line (int status, int errnum, const char *file_name,
|
||||
unsigned int line_number, const char *message,
|
||||
...)
|
||||
__attribute__ ((__format__ (__printf__, 5, 6)));;
|
||||
# define error __error
|
||||
# define error_at_line __error_at_line
|
||||
|
||||
# include <libio/iolibio.h>
|
||||
# define fflush(s) INTUSE(_IO_fflush) (s)
|
||||
# undef putc
|
||||
# define putc(c, fp) INTUSE(_IO_putc) (c, fp)
|
||||
|
||||
# include <bits/libc-lock.h>
|
||||
|
||||
#else /* not _LIBC */
|
||||
|
||||
# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
|
||||
# ifndef HAVE_DECL_STRERROR_R
|
||||
"this configure-time declaration test was not run"
|
||||
# endif
|
||||
char *strerror_r ();
|
||||
# endif
|
||||
|
||||
# ifndef SIZE_MAX
|
||||
# define SIZE_MAX ((size_t) -1)
|
||||
# endif
|
||||
|
||||
/* The calling program should define program_name and set it to the
|
||||
name of the executing program. */
|
||||
extern char *program_name;
|
||||
|
||||
# if HAVE_STRERROR_R || defined strerror_r
|
||||
# define __strerror_r strerror_r
|
||||
# endif
|
||||
#endif /* not _LIBC */
|
||||
|
||||
static void
|
||||
print_errno_message (int errnum)
|
||||
{
|
||||
char const *s = NULL;
|
||||
|
||||
#if defined HAVE_STRERROR_R || _LIBC
|
||||
char errbuf[1024];
|
||||
# if STRERROR_R_CHAR_P || _LIBC
|
||||
s = __strerror_r (errnum, errbuf, sizeof errbuf);
|
||||
# else
|
||||
if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
|
||||
s = errbuf;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !_LIBC
|
||||
if (! s && ! (s = strerror (errnum)))
|
||||
s = _("Unknown system error");
|
||||
#endif
|
||||
|
||||
#if _LIBC
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
{
|
||||
__fwprintf (stderr, L": %s", s);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
fprintf (stderr, ": %s", s);
|
||||
}
|
||||
|
||||
static void
|
||||
error_tail (int status, int errnum, const char *message, va_list args)
|
||||
{
|
||||
#if _LIBC
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
{
|
||||
# define ALLOCA_LIMIT 2000
|
||||
size_t len = strlen (message) + 1;
|
||||
const wchar_t *wmessage = L"out of memory";
|
||||
wchar_t *wbuf = (len < ALLOCA_LIMIT
|
||||
? alloca (len * sizeof *wbuf)
|
||||
: len <= SIZE_MAX / sizeof *wbuf
|
||||
? malloc (len * sizeof *wbuf)
|
||||
: NULL);
|
||||
|
||||
if (wbuf)
|
||||
{
|
||||
size_t res;
|
||||
mbstate_t st;
|
||||
const char *tmp = message;
|
||||
memset (&st, '\0', sizeof (st));
|
||||
res = mbsrtowcs (wbuf, &tmp, len, &st);
|
||||
wmessage = res == (size_t) -1 ? L"???" : wbuf;
|
||||
}
|
||||
|
||||
__vfwprintf (stderr, wmessage, args);
|
||||
if (! (len < ALLOCA_LIMIT))
|
||||
free (wbuf);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
vfprintf (stderr, message, args);
|
||||
va_end (args);
|
||||
|
||||
++error_message_count;
|
||||
if (errnum)
|
||||
print_errno_message (errnum);
|
||||
#if _LIBC
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
putwc (L'\n', stderr);
|
||||
else
|
||||
#endif
|
||||
putc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
if (status)
|
||||
exit (status);
|
||||
}
|
||||
|
||||
|
||||
/* Print the program name and error message MESSAGE, which is a printf-style
|
||||
format string with optional args.
|
||||
If ERRNUM is nonzero, print its corresponding system error message.
|
||||
Exit with status STATUS if it is nonzero. */
|
||||
void
|
||||
error (int status, int errnum, const char *message, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
#if defined _LIBC && defined __libc_ptf_call
|
||||
/* We do not want this call to be cut short by a thread
|
||||
cancellation. Therefore disable cancellation for now. */
|
||||
int state = PTHREAD_CANCEL_ENABLE;
|
||||
__libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
|
||||
0);
|
||||
#endif
|
||||
|
||||
fflush (stdout);
|
||||
#ifdef _LIBC
|
||||
_IO_flockfile (stderr);
|
||||
#endif
|
||||
if (error_print_progname)
|
||||
(*error_print_progname) ();
|
||||
else
|
||||
{
|
||||
#if _LIBC
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s: ", program_name);
|
||||
else
|
||||
#endif
|
||||
fprintf (stderr, "%s: ", program_name);
|
||||
}
|
||||
|
||||
va_start (args, message);
|
||||
error_tail (status, errnum, message, args);
|
||||
|
||||
#ifdef _LIBC
|
||||
_IO_funlockfile (stderr);
|
||||
# ifdef __libc_ptf_call
|
||||
__libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Sometimes we want to have at most one error per line. This
|
||||
variable controls whether this mode is selected or not. */
|
||||
int error_one_per_line;
|
||||
|
||||
void
|
||||
error_at_line (int status, int errnum, const char *file_name,
|
||||
unsigned int line_number, const char *message, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (error_one_per_line)
|
||||
{
|
||||
static const char *old_file_name;
|
||||
static unsigned int old_line_number;
|
||||
|
||||
if (old_line_number == line_number
|
||||
&& (file_name == old_file_name
|
||||
|| strcmp (old_file_name, file_name) == 0))
|
||||
/* Simply return and print nothing. */
|
||||
return;
|
||||
|
||||
old_file_name = file_name;
|
||||
old_line_number = line_number;
|
||||
}
|
||||
|
||||
#if defined _LIBC && defined __libc_ptf_call
|
||||
/* We do not want this call to be cut short by a thread
|
||||
cancellation. Therefore disable cancellation for now. */
|
||||
int state = PTHREAD_CANCEL_ENABLE;
|
||||
__libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
|
||||
0);
|
||||
#endif
|
||||
|
||||
fflush (stdout);
|
||||
#ifdef _LIBC
|
||||
_IO_flockfile (stderr);
|
||||
#endif
|
||||
if (error_print_progname)
|
||||
(*error_print_progname) ();
|
||||
else
|
||||
{
|
||||
#if _LIBC
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s: ", program_name);
|
||||
else
|
||||
#endif
|
||||
fprintf (stderr, "%s:", program_name);
|
||||
}
|
||||
|
||||
if (file_name != NULL)
|
||||
{
|
||||
#if _LIBC
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s:%d: ", file_name, line_number);
|
||||
else
|
||||
#endif
|
||||
fprintf (stderr, "%s:%d: ", file_name, line_number);
|
||||
}
|
||||
|
||||
va_start (args, message);
|
||||
error_tail (status, errnum, message, args);
|
||||
|
||||
#ifdef _LIBC
|
||||
_IO_funlockfile (stderr);
|
||||
# ifdef __libc_ptf_call
|
||||
__libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _LIBC
|
||||
/* Make the weak alias. */
|
||||
# undef error
|
||||
# undef error_at_line
|
||||
weak_alias (__error, error)
|
||||
weak_alias (__error_at_line, error_at_line)
|
||||
#endif
|
||||
@@ -1,66 +0,0 @@
|
||||
/* Declaration for error-reporting function
|
||||
Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _ERROR_H
|
||||
#define _ERROR_H 1
|
||||
|
||||
#ifndef __attribute__
|
||||
/* This feature is available in gcc versions 2.5 and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
|
||||
# define __attribute__(Spec) /* empty */
|
||||
# endif
|
||||
/* The __-protected variants of `format' and `printf' attributes
|
||||
are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
|
||||
# define __format__ format
|
||||
# define __printf__ printf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Print a message with `fprintf (stderr, FORMAT, ...)';
|
||||
if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
|
||||
If STATUS is nonzero, terminate the program with `exit (STATUS)'. */
|
||||
|
||||
extern void error (int __status, int __errnum, const char *__format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
|
||||
extern void error_at_line (int __status, int __errnum, const char *__fname,
|
||||
unsigned int __lineno, const char *__format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 5, 6)));
|
||||
|
||||
/* If NULL, error will flush stdout, then print on stderr the program
|
||||
name, a colon and a space. Otherwise, error will call this
|
||||
function without parameters instead. */
|
||||
extern void (*error_print_progname) (void);
|
||||
|
||||
/* This variable is incremented each time `error' is called. */
|
||||
extern unsigned int error_message_count;
|
||||
|
||||
/* Sometimes we want to have at most one error per line. This
|
||||
variable controls whether this mode is selected or not. */
|
||||
extern int error_one_per_line;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* error.h */
|
||||
@@ -1,32 +0,0 @@
|
||||
/* exit() function.
|
||||
Copyright (C) 1995, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _EXIT_H
|
||||
#define _EXIT_H
|
||||
|
||||
/* Get exit() declaration. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Some systems do not define EXIT_*, even with STDC_HEADERS. */
|
||||
#ifndef EXIT_SUCCESS
|
||||
# define EXIT_SUCCESS 0
|
||||
#endif
|
||||
#ifndef EXIT_FAILURE
|
||||
# define EXIT_FAILURE 1
|
||||
#endif
|
||||
|
||||
#endif /* _EXIT_H */
|
||||
@@ -1,27 +0,0 @@
|
||||
/* Failure exit status
|
||||
|
||||
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "exitfail.h"
|
||||
#include "exit.h"
|
||||
|
||||
int volatile exit_failure = EXIT_FAILURE;
|
||||
@@ -1,20 +0,0 @@
|
||||
/* Failure exit status
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
extern int volatile exit_failure;
|
||||
@@ -1,83 +0,0 @@
|
||||
/* An interface to read and write that retries (if necessary) until complete.
|
||||
|
||||
Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
|
||||
2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
/* Specification. */
|
||||
#ifdef FULL_READ
|
||||
# include "full-read.h"
|
||||
#else
|
||||
# include "full-write.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef FULL_READ
|
||||
# include "safe-read.h"
|
||||
# define safe_rw safe_read
|
||||
# define full_rw full_read
|
||||
# undef const
|
||||
# define const /* empty */
|
||||
#else
|
||||
# include "safe-write.h"
|
||||
# define safe_rw safe_write
|
||||
# define full_rw full_write
|
||||
#endif
|
||||
|
||||
#ifdef FULL_READ
|
||||
/* Set errno to zero upon EOF. */
|
||||
# define ZERO_BYTE_TRANSFER_ERRNO 0
|
||||
#else
|
||||
/* Some buggy drivers return 0 when one tries to write beyond
|
||||
a device's end. (Example: Linux 1.2.13 on /dev/fd0.)
|
||||
Set errno to ENOSPC so they get a sensible diagnostic. */
|
||||
# define ZERO_BYTE_TRANSFER_ERRNO ENOSPC
|
||||
#endif
|
||||
|
||||
/* Write(read) COUNT bytes at BUF to(from) descriptor FD, retrying if
|
||||
interrupted or if a partial write(read) occurs. Return the number
|
||||
of bytes transferred.
|
||||
When writing, set errno if fewer than COUNT bytes are written.
|
||||
When reading, if fewer than COUNT bytes are read, you must examine
|
||||
errno to distinguish failure from EOF (errno == 0). */
|
||||
size_t
|
||||
full_rw (int fd, const void *buf, size_t count)
|
||||
{
|
||||
size_t total = 0;
|
||||
const char *ptr = buf;
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
size_t n_rw = safe_rw (fd, ptr, count);
|
||||
if (n_rw == (size_t) -1)
|
||||
break;
|
||||
if (n_rw == 0)
|
||||
{
|
||||
errno = ZERO_BYTE_TRANSFER_ERRNO;
|
||||
break;
|
||||
}
|
||||
total += n_rw;
|
||||
ptr += n_rw;
|
||||
count -= n_rw;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/* An interface to write() that writes all it is asked to write.
|
||||
|
||||
Copyright (C) 2002-2003 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Write COUNT bytes at BUF to descriptor FD, retrying if interrupted
|
||||
or if partial writes occur. Return the number of bytes successfully
|
||||
written, setting errno if that is less than COUNT. */
|
||||
extern size_t full_write (int fd, const void *buf, size_t count);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,174 +0,0 @@
|
||||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <getopt.h>
|
||||
#else
|
||||
# include "getopt.h"
|
||||
#endif
|
||||
#include "getopt_int.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#ifdef __GNU_LIBRARY__
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
int
|
||||
getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,
|
||||
const struct option *long_options, int *opt_index)
|
||||
{
|
||||
return _getopt_internal (argc, (char **) argv, options, long_options,
|
||||
opt_index, 0, 0);
|
||||
}
|
||||
|
||||
int
|
||||
_getopt_long_r (int argc, char **argv, const char *options,
|
||||
const struct option *long_options, int *opt_index,
|
||||
struct _getopt_data *d)
|
||||
{
|
||||
return _getopt_internal_r (argc, argv, options, long_options, opt_index,
|
||||
0, 0, d);
|
||||
}
|
||||
|
||||
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
|
||||
If an option that starts with '-' (not '--') doesn't match a long option,
|
||||
but does match a short option, it is parsed as a short option
|
||||
instead. */
|
||||
|
||||
int
|
||||
getopt_long_only (int argc, char *__getopt_argv_const *argv,
|
||||
const char *options,
|
||||
const struct option *long_options, int *opt_index)
|
||||
{
|
||||
return _getopt_internal (argc, (char **) argv, options, long_options,
|
||||
opt_index, 1, 0);
|
||||
}
|
||||
|
||||
int
|
||||
_getopt_long_only_r (int argc, char **argv, const char *options,
|
||||
const struct option *long_options, int *opt_index,
|
||||
struct _getopt_data *d)
|
||||
{
|
||||
return _getopt_internal_r (argc, argv, options, long_options, opt_index,
|
||||
1, 0, d);
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
int digit_optind = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int this_option_optind = optind ? optind : 1;
|
||||
int option_index = 0;
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"add", 1, 0, 0},
|
||||
{"append", 0, 0, 0},
|
||||
{"delete", 1, 0, 0},
|
||||
{"verbose", 0, 0, 0},
|
||||
{"create", 0, 0, 0},
|
||||
{"file", 1, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long (argc, argv, "abc:d:0123456789",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 0:
|
||||
printf ("option %s", long_options[option_index].name);
|
||||
if (optarg)
|
||||
printf (" with arg %s", optarg);
|
||||
printf ("\n");
|
||||
break;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (digit_optind != 0 && digit_optind != this_option_optind)
|
||||
printf ("digits occur in two different argv-elements.\n");
|
||||
digit_optind = this_option_optind;
|
||||
printf ("option %c\n", c);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
printf ("option a\n");
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
printf ("option b\n");
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
printf ("option c with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
printf ("option d with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("?? getopt returned character code 0%o ??\n", c);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
printf ("non-option ARGV-elements: ");
|
||||
while (optind < argc)
|
||||
printf ("%s ", argv[optind++]);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#endif /* TEST */
|
||||
@@ -1,227 +0,0 @@
|
||||
/* Declarations for getopt.
|
||||
Copyright (C) 1989-1994,1996-1999,2001,2003,2004
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _GETOPT_H
|
||||
|
||||
#ifndef __need_getopt
|
||||
# define _GETOPT_H 1
|
||||
#endif
|
||||
|
||||
/* Standalone applications should #define __GETOPT_PREFIX to an
|
||||
identifier that prefixes the external functions and variables
|
||||
defined in this header. When this happens, include the
|
||||
headers that might declare getopt so that they will not cause
|
||||
confusion if included after this file. Then systematically rename
|
||||
identifiers so that they do not collide with the system functions
|
||||
and variables. Renaming avoids problems with some compilers and
|
||||
linkers. */
|
||||
#if defined __GETOPT_PREFIX && !defined __need_getopt
|
||||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
# if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
# undef __need_getopt
|
||||
# undef getopt
|
||||
# undef getopt_long
|
||||
# undef getopt_long_only
|
||||
# undef optarg
|
||||
# undef opterr
|
||||
# undef optind
|
||||
# undef optopt
|
||||
# define __GETOPT_CONCAT(x, y) x ## y
|
||||
# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y)
|
||||
# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y)
|
||||
# define getopt __GETOPT_ID (getopt)
|
||||
# define getopt_long __GETOPT_ID (getopt_long)
|
||||
# define getopt_long_only __GETOPT_ID (getopt_long_only)
|
||||
# define optarg __GETOPT_ID (optarg)
|
||||
# define opterr __GETOPT_ID (opterr)
|
||||
# define optind __GETOPT_ID (optind)
|
||||
# define optopt __GETOPT_ID (optopt)
|
||||
#endif
|
||||
|
||||
/* Standalone applications get correct prototypes for getopt_long and
|
||||
getopt_long_only; they declare "char **argv". libc uses prototypes
|
||||
with "char *const *argv" that are incorrect because getopt_long and
|
||||
getopt_long_only can permute argv; this is required for backward
|
||||
compatibility (e.g., for LSB 2.0.1).
|
||||
|
||||
This used to be `#if defined __GETOPT_PREFIX && !defined __need_getopt',
|
||||
but it caused redefinition warnings if both unistd.h and getopt.h were
|
||||
included, since unistd.h includes getopt.h having previously defined
|
||||
__need_getopt.
|
||||
|
||||
The only place where __getopt_argv_const is used is in definitions
|
||||
of getopt_long and getopt_long_only below, but these are visible
|
||||
only if __need_getopt is not defined, so it is quite safe to rewrite
|
||||
the conditional as follows:
|
||||
*/
|
||||
#if !defined __need_getopt
|
||||
# if defined __GETOPT_PREFIX
|
||||
# define __getopt_argv_const /* empty */
|
||||
# else
|
||||
# define __getopt_argv_const const
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* If __GNU_LIBRARY__ is not already defined, either we are being used
|
||||
standalone, or this is the first header included in the source file.
|
||||
If we are being used with glibc, we need to include <features.h>, but
|
||||
that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
|
||||
not defined, include <ctype.h>, which will pull in <features.h> for us
|
||||
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
|
||||
doesn't flood the namespace with stuff the way some other headers do.) */
|
||||
#if !defined __GNU_LIBRARY__
|
||||
# include <ctype.h>
|
||||
#endif
|
||||
|
||||
#ifndef __THROW
|
||||
# ifndef __GNUC_PREREQ
|
||||
# define __GNUC_PREREQ(maj, min) (0)
|
||||
# endif
|
||||
# if defined __cplusplus && __GNUC_PREREQ (2,8)
|
||||
# define __THROW throw ()
|
||||
# else
|
||||
# define __THROW
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
When `getopt' finds an option that takes an argument,
|
||||
the argument value is returned here.
|
||||
Also, when `ordering' is RETURN_IN_ORDER,
|
||||
each non-option ARGV-element is returned here. */
|
||||
|
||||
extern char *optarg;
|
||||
|
||||
/* Index in ARGV of the next element to be scanned.
|
||||
This is used for communication to and from the caller
|
||||
and for communication between successive calls to `getopt'.
|
||||
|
||||
On entry to `getopt', zero means this is the first call; initialize.
|
||||
|
||||
When `getopt' returns -1, this is the index of the first of the
|
||||
non-option elements that the caller should itself scan.
|
||||
|
||||
Otherwise, `optind' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far. */
|
||||
|
||||
extern int optind;
|
||||
|
||||
/* Callers store zero here to inhibit the error message `getopt' prints
|
||||
for unrecognized options. */
|
||||
|
||||
extern int opterr;
|
||||
|
||||
/* Set to an option character which was unrecognized. */
|
||||
|
||||
extern int optopt;
|
||||
|
||||
#ifndef __need_getopt
|
||||
/* Describe the long-named options requested by the application.
|
||||
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
|
||||
of `struct option' terminated by an element containing a name which is
|
||||
zero.
|
||||
|
||||
The field `has_arg' is:
|
||||
no_argument (or 0) if the option does not take an argument,
|
||||
required_argument (or 1) if the option requires an argument,
|
||||
optional_argument (or 2) if the option takes an optional argument.
|
||||
|
||||
If the field `flag' is not NULL, it points to a variable that is set
|
||||
to the value given in the field `val' when the option is found, but
|
||||
left unchanged if the option is not found.
|
||||
|
||||
To have a long-named option do something other than set an `int' to
|
||||
a compiled-in constant, such as set a value from `optarg', set the
|
||||
option's `flag' field to zero and its `val' field to a nonzero
|
||||
value (the equivalent single-letter option character, if there is
|
||||
one). For long options that have a zero `flag' field, `getopt'
|
||||
returns the contents of the `val' field. */
|
||||
|
||||
struct option
|
||||
{
|
||||
const char *name;
|
||||
/* has_arg can't be an enum because some compilers complain about
|
||||
type mismatches in all the code that assumes it is an int. */
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
/* Names for the values of the `has_arg' field of `struct option'. */
|
||||
|
||||
# define no_argument 0
|
||||
# define required_argument 1
|
||||
# define optional_argument 2
|
||||
#endif /* need getopt */
|
||||
|
||||
|
||||
/* Get definitions and prototypes for functions to process the
|
||||
arguments in ARGV (ARGC of them, minus the program name) for
|
||||
options given in OPTS.
|
||||
|
||||
Return the option character from OPTS just read. Return -1 when
|
||||
there are no more options. For unrecognized options, or options
|
||||
missing arguments, `optopt' is set to the option letter, and '?' is
|
||||
returned.
|
||||
|
||||
The OPTS string is a list of characters which are recognized option
|
||||
letters, optionally followed by colons, specifying that that letter
|
||||
takes an argument, to be placed in `optarg'.
|
||||
|
||||
If a letter in OPTS is followed by two colons, its argument is
|
||||
optional. This behavior is specific to the GNU `getopt'.
|
||||
|
||||
The argument `--' causes premature termination of argument
|
||||
scanning, explicitly telling `getopt' that there are no more
|
||||
options.
|
||||
|
||||
If OPTS begins with `--', then non-option arguments are treated as
|
||||
arguments to the option '\0'. This behavior is specific to the GNU
|
||||
`getopt'. */
|
||||
|
||||
extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
|
||||
__THROW;
|
||||
|
||||
#ifndef __need_getopt
|
||||
extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind)
|
||||
__THROW;
|
||||
extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind)
|
||||
__THROW;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Make sure we later can get all the definitions and declarations. */
|
||||
#undef __need_getopt
|
||||
|
||||
#endif /* getopt.h */
|
||||
@@ -1,131 +0,0 @@
|
||||
/* Internal declarations for getopt.
|
||||
Copyright (C) 1989-1994,1996-1999,2001,2003,2004
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _GETOPT_INT_H
|
||||
#define _GETOPT_INT_H 1
|
||||
|
||||
extern int _getopt_internal (int ___argc, char **___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind,
|
||||
int __long_only, int __posixly_correct);
|
||||
|
||||
|
||||
/* Reentrant versions which can handle parsing multiple argument
|
||||
vectors at the same time. */
|
||||
|
||||
/* Data type for reentrant functions. */
|
||||
struct _getopt_data
|
||||
{
|
||||
/* These have exactly the same meaning as the corresponding global
|
||||
variables, except that they are used for the reentrant
|
||||
versions of getopt. */
|
||||
int optind;
|
||||
int opterr;
|
||||
int optopt;
|
||||
char *optarg;
|
||||
|
||||
/* Internal members. */
|
||||
|
||||
/* True if the internal members have been initialized. */
|
||||
int __initialized;
|
||||
|
||||
/* The next char to be scanned in the option-element
|
||||
in which the last option character we returned was found.
|
||||
This allows us to pick up the scan where we left off.
|
||||
|
||||
If this is zero, or a null string, it means resume the scan
|
||||
by advancing to the next ARGV-element. */
|
||||
char *__nextchar;
|
||||
|
||||
/* Describe how to deal with options that follow non-option ARGV-elements.
|
||||
|
||||
If the caller did not specify anything,
|
||||
the default is REQUIRE_ORDER if the environment variable
|
||||
POSIXLY_CORRECT is defined, PERMUTE otherwise.
|
||||
|
||||
REQUIRE_ORDER means don't recognize them as options;
|
||||
stop option processing when the first non-option is seen.
|
||||
This is what Unix does.
|
||||
This mode of operation is selected by either setting the environment
|
||||
variable POSIXLY_CORRECT, or using `+' as the first character
|
||||
of the list of option characters, or by calling getopt.
|
||||
|
||||
PERMUTE is the default. We permute the contents of ARGV as we
|
||||
scan, so that eventually all the non-options are at the end.
|
||||
This allows options to be given in any order, even with programs
|
||||
that were not written to expect this.
|
||||
|
||||
RETURN_IN_ORDER is an option available to programs that were
|
||||
written to expect options and other ARGV-elements in any order
|
||||
and that care about the ordering of the two. We describe each
|
||||
non-option ARGV-element as if it were the argument of an option
|
||||
with character code 1. Using `-' as the first character of the
|
||||
list of option characters selects this mode of operation.
|
||||
|
||||
The special argument `--' forces an end of option-scanning regardless
|
||||
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
|
||||
`--' can cause `getopt' to return -1 with `optind' != ARGC. */
|
||||
|
||||
enum
|
||||
{
|
||||
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
|
||||
} __ordering;
|
||||
|
||||
/* If the POSIXLY_CORRECT environment variable is set
|
||||
or getopt was called. */
|
||||
int __posixly_correct;
|
||||
|
||||
|
||||
/* Handle permutation of arguments. */
|
||||
|
||||
/* Describe the part of ARGV that contains non-options that have
|
||||
been skipped. `first_nonopt' is the index in ARGV of the first
|
||||
of them; `last_nonopt' is the index after the last of them. */
|
||||
|
||||
int __first_nonopt;
|
||||
int __last_nonopt;
|
||||
|
||||
#if defined _LIBC && defined USE_NONOPTION_FLAGS
|
||||
int __nonoption_flags_max_len;
|
||||
int __nonoption_flags_len;
|
||||
# endif
|
||||
};
|
||||
|
||||
/* The initializer is necessary to set OPTIND and OPTERR to their
|
||||
default values and to clear the initialization flag. */
|
||||
#define _GETOPT_DATA_INITIALIZER { 1, 1 }
|
||||
|
||||
extern int _getopt_internal_r (int ___argc, char **___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind,
|
||||
int __long_only, int __posixly_correct,
|
||||
struct _getopt_data *__data);
|
||||
|
||||
extern int _getopt_long_r (int ___argc, char **___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind,
|
||||
struct _getopt_data *__data);
|
||||
|
||||
extern int _getopt_long_only_r (int ___argc, char **___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts,
|
||||
int *__longind,
|
||||
struct _getopt_data *__data);
|
||||
|
||||
#endif /* getopt_int.h */
|
||||
@@ -1,68 +0,0 @@
|
||||
/* Convenience header for conditional use of GNU <libintl.h>.
|
||||
Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _LIBGETTEXT_H
|
||||
#define _LIBGETTEXT_H 1
|
||||
|
||||
/* NLS can be disabled through the configure --disable-nls option. */
|
||||
#if ENABLE_NLS
|
||||
|
||||
/* Get declarations of GNU message catalog functions. */
|
||||
# include <libintl.h>
|
||||
|
||||
#else
|
||||
|
||||
/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
|
||||
chokes if dcgettext is defined as a macro. So include it now, to make
|
||||
later inclusions of <locale.h> a NOP. We don't include <libintl.h>
|
||||
as well because people using "gettext.h" will not include <libintl.h>,
|
||||
and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
|
||||
is OK. */
|
||||
#if defined(__sun)
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
/* Disabled NLS.
|
||||
The casts to 'const char *' serve the purpose of producing warnings
|
||||
for invalid uses of the value returned from these functions.
|
||||
On pre-ANSI systems without 'const', the config.h file is supposed to
|
||||
contain "#define const". */
|
||||
# define gettext(Msgid) ((const char *) (Msgid))
|
||||
# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
|
||||
# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
|
||||
# define ngettext(Msgid1, Msgid2, N) \
|
||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||
# define dngettext(Domainname, Msgid1, Msgid2, N) \
|
||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
|
||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||
# define textdomain(Domainname) ((const char *) (Domainname))
|
||||
# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
|
||||
# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
|
||||
|
||||
#endif
|
||||
|
||||
/* A pseudo function call that serves as a marker for the automated
|
||||
extraction of messages, but does not call gettext(). The run-time
|
||||
translation is done at a different place in the code.
|
||||
The argument, String, should be a literal string. Concatenated strings
|
||||
and other string expressions won't work.
|
||||
The macro's expansion is not parenthesized, so that it is suitable as
|
||||
initializer for static 'char[]' or 'const char[]' variables. */
|
||||
#define gettext_noop(String) String
|
||||
|
||||
#endif /* _LIBGETTEXT_H */
|
||||
@@ -1,4 +0,0 @@
|
||||
#define LOCALEDIR "/usr/local/share/locale"
|
||||
#ifndef DEFAULT_RMT_COMMAND
|
||||
# define DEFAULT_RMT_COMMAND "/usr/local/libexec/rmt"
|
||||
#endif
|
||||
@@ -1,29 +0,0 @@
|
||||
/* Copy memory area and return pointer after last written byte.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Specification. */
|
||||
#include "mempcpy.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Copy N bytes of SRC to DEST, return pointer to bytes after the
|
||||
last written byte. */
|
||||
void *
|
||||
mempcpy (void *dest, const void *src, size_t n)
|
||||
{
|
||||
return (char *) memcpy (dest, src, n) + n;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/* Copy memory area and return pointer after last written byte.
|
||||
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef mempcpy
|
||||
|
||||
# if HAVE_MEMPCPY
|
||||
|
||||
/* Get mempcpy() declaration. */
|
||||
# include <string.h>
|
||||
|
||||
# else
|
||||
|
||||
/* Get size_t */
|
||||
# include <stddef.h>
|
||||
|
||||
/* Copy N bytes of SRC to DEST, return pointer to bytes after the
|
||||
last written byte. */
|
||||
extern void *mempcpy (void *dest, const void *src, size_t n);
|
||||
|
||||
# endif
|
||||
|
||||
#endif
|
||||
@@ -1,99 +0,0 @@
|
||||
/* Definitions for communicating with a remote tape drive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1996, 1997, 2001, 2003, 2004 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
extern char *rmt_command;
|
||||
extern char *rmt_dev_name__;
|
||||
|
||||
int rmt_open__ (const char *, int, int, const char *);
|
||||
int rmt_close__ (int);
|
||||
size_t rmt_read__ (int, char *, size_t);
|
||||
size_t rmt_write__ (int, char *, size_t);
|
||||
off_t rmt_lseek__ (int, off_t, int);
|
||||
int rmt_ioctl__ (int, int, char *);
|
||||
|
||||
extern bool force_local_option;
|
||||
|
||||
/* A filename is remote if it contains a colon not preceded by a slash,
|
||||
to take care of `/:/' which is a shorthand for `/.../<CELL-NAME>/fs'
|
||||
on machines running OSF's Distributing Computing Environment (DCE) and
|
||||
Distributed File System (DFS). However, when --force-local, a
|
||||
filename is never remote. */
|
||||
|
||||
#define _remdev(dev_name) \
|
||||
(!force_local_option && (rmt_dev_name__ = strchr (dev_name, ':')) \
|
||||
&& rmt_dev_name__ > (dev_name) \
|
||||
&& ! memchr (dev_name, '/', rmt_dev_name__ - (dev_name)))
|
||||
|
||||
#define _isrmt(fd) \
|
||||
((fd) >= __REM_BIAS)
|
||||
|
||||
#define __REM_BIAS (1 << 30)
|
||||
|
||||
#ifndef O_CREAT
|
||||
# define O_CREAT 01000
|
||||
#endif
|
||||
|
||||
#define rmtopen(dev_name, oflag, mode, command) \
|
||||
(_remdev (dev_name) ? rmt_open__ (dev_name, oflag, __REM_BIAS, command) \
|
||||
: open (dev_name, oflag, mode))
|
||||
|
||||
#define rmtaccess(dev_name, amode) \
|
||||
(_remdev (dev_name) ? 0 : access (dev_name, amode))
|
||||
|
||||
#define rmtstat(dev_name, buffer) \
|
||||
(_remdev (dev_name) ? (errno = EOPNOTSUPP), -1 : stat (dev_name, buffer))
|
||||
|
||||
#define rmtcreat(dev_name, mode, command) \
|
||||
(_remdev (dev_name) \
|
||||
? rmt_open__ (dev_name, 1 | O_CREAT, __REM_BIAS, command) \
|
||||
: creat (dev_name, mode))
|
||||
|
||||
#define rmtlstat(dev_name, muffer) \
|
||||
(_remdev (dev_name) ? (errno = EOPNOTSUPP), -1 : lstat (dev_name, buffer))
|
||||
|
||||
#define rmtread(fd, buffer, length) \
|
||||
(_isrmt (fd) ? rmt_read__ (fd - __REM_BIAS, buffer, length) \
|
||||
: safe_read (fd, buffer, length))
|
||||
|
||||
#define rmtwrite(fd, buffer, length) \
|
||||
(_isrmt (fd) ? rmt_write__ (fd - __REM_BIAS, buffer, length) \
|
||||
: full_write (fd, buffer, length))
|
||||
|
||||
#define rmtlseek(fd, offset, where) \
|
||||
(_isrmt (fd) ? rmt_lseek__ (fd - __REM_BIAS, offset, where) \
|
||||
: lseek (fd, offset, where))
|
||||
|
||||
#define rmtclose(fd) \
|
||||
(_isrmt (fd) ? rmt_close__ (fd - __REM_BIAS) : close (fd))
|
||||
|
||||
#define rmtioctl(fd, request, argument) \
|
||||
(_isrmt (fd) ? rmt_ioctl__ (fd - __REM_BIAS, request, argument) \
|
||||
: ioctl (fd, request, argument))
|
||||
|
||||
#define rmtdup(fd) \
|
||||
(_isrmt (fd) ? (errno = EOPNOTSUPP), -1 : dup (fd))
|
||||
|
||||
#define rmtfstat(fd, buffer) \
|
||||
(_isrmt (fd) ? (errno = EOPNOTSUPP), -1 : fstat (fd, buffer))
|
||||
|
||||
#define rmtfcntl(cd, command, argument) \
|
||||
(_isrmt (fd) ? (errno = EOPNOTSUPP), -1 : fcntl (fd, command, argument))
|
||||
|
||||
#define rmtisatty(fd) \
|
||||
(_isrmt (fd) ? 0 : isatty (fd))
|
||||
@@ -1,740 +0,0 @@
|
||||
/* Functions for communicating with a remote tape drive.
|
||||
|
||||
Copyright 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2004 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* The man page rmt(8) for /etc/rmt documents the remote mag tape protocol
|
||||
which rdump and rrestore use. Unfortunately, the man page is *WRONG*.
|
||||
The author of the routines I'm including originally wrote his code just
|
||||
based on the man page, and it didn't work, so he went to the rdump source
|
||||
to figure out why. The only thing he had to change was to check for the
|
||||
'F' return code in addition to the 'E', and to separate the various
|
||||
arguments with \n instead of a space. I personally don't think that this
|
||||
is much of a problem, but I wanted to point it out. -- Arnold Robbins
|
||||
|
||||
Originally written by Jeff Lee, modified some by Arnold Robbins. Redone
|
||||
as a library that can replace open, read, write, etc., by Fred Fish, with
|
||||
some additional work by Arnold Robbins. Modified to make all rmt* calls
|
||||
into macros for speed by Jay Fenlason. Use -DWITH_REXEC for rexec
|
||||
code, courtesy of Dan Kegel. */
|
||||
|
||||
#include "system.h"
|
||||
#include <safe-read.h>
|
||||
#include <full-write.h>
|
||||
|
||||
/* Try hard to get EOPNOTSUPP defined. 486/ISC has it in net/errno.h,
|
||||
3B2/SVR3 has it in sys/inet.h. Otherwise, like on MSDOS, use EINVAL. */
|
||||
|
||||
#ifndef EOPNOTSUPP
|
||||
# if HAVE_NET_ERRNO_H
|
||||
# include <net/errno.h>
|
||||
# endif
|
||||
# if HAVE_SYS_INET_H
|
||||
# include <sys/inet.h>
|
||||
# endif
|
||||
# ifndef EOPNOTSUPP
|
||||
# define EOPNOTSUPP EINVAL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#if HAVE_NETDB_H
|
||||
# include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include <rmt.h>
|
||||
#include <localedir.h>
|
||||
|
||||
/* Exit status if exec errors. */
|
||||
#define EXIT_ON_EXEC_ERROR 128
|
||||
|
||||
/* FIXME: Size of buffers for reading and writing commands to rmt. */
|
||||
#define COMMAND_BUFFER_SIZE 64
|
||||
|
||||
#ifndef RETSIGTYPE
|
||||
# define RETSIGTYPE void
|
||||
#endif
|
||||
|
||||
/* FIXME: Maximum number of simultaneous remote tape connections. */
|
||||
#define MAXUNIT 4
|
||||
|
||||
#define PREAD 0 /* read file descriptor from pipe() */
|
||||
#define PWRITE 1 /* write file descriptor from pipe() */
|
||||
|
||||
/* Return the parent's read side of remote tape connection Fd. */
|
||||
#define READ_SIDE(Fd) (from_remote[Fd][PREAD])
|
||||
|
||||
/* Return the parent's write side of remote tape connection Fd. */
|
||||
#define WRITE_SIDE(Fd) (to_remote[Fd][PWRITE])
|
||||
|
||||
/* The pipes for receiving data from remote tape drives. */
|
||||
static int from_remote[MAXUNIT][2] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}};
|
||||
|
||||
/* The pipes for sending data to remote tape drives. */
|
||||
static int to_remote[MAXUNIT][2] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}};
|
||||
|
||||
char *rmt_command = DEFAULT_RMT_COMMAND;
|
||||
|
||||
/* Temporary variable used by macros in rmt.h. */
|
||||
char *rmt_dev_name__;
|
||||
|
||||
/* If true, always consider file names to be local, even if they contain
|
||||
colons */
|
||||
bool force_local_option;
|
||||
|
||||
|
||||
|
||||
/* Close remote tape connection HANDLE, and reset errno to ERRNO_VALUE. */
|
||||
static void
|
||||
_rmt_shutdown (int handle, int errno_value)
|
||||
{
|
||||
close (READ_SIDE (handle));
|
||||
close (WRITE_SIDE (handle));
|
||||
READ_SIDE (handle) = -1;
|
||||
WRITE_SIDE (handle) = -1;
|
||||
errno = errno_value;
|
||||
}
|
||||
|
||||
/* Attempt to perform the remote tape command specified in BUFFER on
|
||||
remote tape connection HANDLE. Return 0 if successful, -1 on
|
||||
error. */
|
||||
static int
|
||||
do_command (int handle, const char *buffer)
|
||||
{
|
||||
/* Save the current pipe handler and try to make the request. */
|
||||
|
||||
size_t length = strlen (buffer);
|
||||
RETSIGTYPE (*pipe_handler) () = signal (SIGPIPE, SIG_IGN);
|
||||
ssize_t written = full_write (WRITE_SIDE (handle), buffer, length);
|
||||
signal (SIGPIPE, pipe_handler);
|
||||
|
||||
if (written == length)
|
||||
return 0;
|
||||
|
||||
/* Something went wrong. Close down and go home. */
|
||||
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_status_string (int handle, char *command_buffer)
|
||||
{
|
||||
char *cursor;
|
||||
int counter;
|
||||
|
||||
/* Read the reply command line. */
|
||||
|
||||
for (counter = 0, cursor = command_buffer;
|
||||
counter < COMMAND_BUFFER_SIZE;
|
||||
counter++, cursor++)
|
||||
{
|
||||
if (safe_read (READ_SIDE (handle), cursor, 1) != 1)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return 0;
|
||||
}
|
||||
if (*cursor == '\n')
|
||||
{
|
||||
*cursor = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (counter == COMMAND_BUFFER_SIZE)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check the return status. */
|
||||
|
||||
for (cursor = command_buffer; *cursor; cursor++)
|
||||
if (*cursor != ' ')
|
||||
break;
|
||||
|
||||
if (*cursor == 'E' || *cursor == 'F')
|
||||
{
|
||||
/* Skip the error message line. */
|
||||
|
||||
/* FIXME: there is better to do than merely ignoring error messages
|
||||
coming from the remote end. Translate them, too... */
|
||||
|
||||
{
|
||||
char character;
|
||||
|
||||
while (safe_read (READ_SIDE (handle), &character, 1) == 1)
|
||||
if (character == '\n')
|
||||
break;
|
||||
}
|
||||
|
||||
errno = atoi (cursor + 1);
|
||||
|
||||
if (*cursor == 'F')
|
||||
_rmt_shutdown (handle, errno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for mis-synced pipes. */
|
||||
|
||||
if (*cursor != 'A')
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Got an `A' (success) response. */
|
||||
|
||||
return cursor + 1;
|
||||
}
|
||||
|
||||
/* Read and return the status from remote tape connection HANDLE. If
|
||||
an error occurred, return -1 and set errno. */
|
||||
static long int
|
||||
get_status (int handle)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
const char *status = get_status_string (handle, command_buffer);
|
||||
if (status)
|
||||
{
|
||||
long int result = atol (status);
|
||||
if (0 <= result)
|
||||
return result;
|
||||
errno = EIO;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static off_t
|
||||
get_status_off (int handle)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
const char *status = get_status_string (handle, command_buffer);
|
||||
|
||||
if (! status)
|
||||
return -1;
|
||||
else
|
||||
{
|
||||
/* Parse status, taking care to check for overflow.
|
||||
We can't use standard functions,
|
||||
since off_t might be longer than long. */
|
||||
|
||||
off_t count = 0;
|
||||
int negative;
|
||||
|
||||
for (; *status == ' ' || *status == '\t'; status++)
|
||||
continue;
|
||||
|
||||
negative = *status == '-';
|
||||
status += negative || *status == '+';
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int digit = *status++ - '0';
|
||||
if (9 < (unsigned) digit)
|
||||
break;
|
||||
else
|
||||
{
|
||||
off_t c10 = 10 * count;
|
||||
off_t nc = negative ? c10 - digit : c10 + digit;
|
||||
if (c10 / 10 != count || (negative ? c10 < nc : nc < c10))
|
||||
return -1;
|
||||
count = nc;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
#if WITH_REXEC
|
||||
|
||||
/* Execute /etc/rmt as user USER on remote system HOST using rexec.
|
||||
Return a file descriptor of a bidirectional socket for stdin and
|
||||
stdout. If USER is zero, use the current username.
|
||||
|
||||
By default, this code is not used, since it requires that the user
|
||||
have a .netrc file in his/her home directory, or that the
|
||||
application designer be willing to have rexec prompt for login and
|
||||
password info. This may be unacceptable, and .rhosts files for use
|
||||
with rsh are much more common on BSD systems. */
|
||||
static int
|
||||
_rmt_rexec (char *host, char *user)
|
||||
{
|
||||
int saved_stdin = dup (STDIN_FILENO);
|
||||
int saved_stdout = dup (STDOUT_FILENO);
|
||||
struct servent *rexecserv;
|
||||
int result;
|
||||
|
||||
/* When using cpio -o < filename, stdin is no longer the tty. But the
|
||||
rexec subroutine reads the login and the passwd on stdin, to allow
|
||||
remote execution of the command. So, reopen stdin and stdout on
|
||||
/dev/tty before the rexec and give them back their original value
|
||||
after. */
|
||||
|
||||
if (! freopen ("/dev/tty", "r", stdin))
|
||||
freopen ("/dev/null", "r", stdin);
|
||||
if (! freopen ("/dev/tty", "w", stdout))
|
||||
freopen ("/dev/null", "w", stdout);
|
||||
|
||||
if (rexecserv = getservbyname ("exec", "tcp"), !rexecserv)
|
||||
error (EXIT_ON_EXEC_ERROR, 0, _("exec/tcp: Service not available"));
|
||||
|
||||
result = rexec (&host, rexecserv->s_port, user, 0, rmt_command, 0);
|
||||
if (fclose (stdin) == EOF)
|
||||
error (0, errno, _("stdin"));
|
||||
fdopen (saved_stdin, "r");
|
||||
if (fclose (stdout) == EOF)
|
||||
error (0, errno, _("stdout"));
|
||||
fdopen (saved_stdout, "w");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* WITH_REXEC */
|
||||
|
||||
/* Place into BUF a string representing OFLAG, which must be suitable
|
||||
as argument 2 of `open'. BUF must be large enough to hold the
|
||||
result. This function should generate a string that decode_oflag
|
||||
can parse. */
|
||||
static void
|
||||
encode_oflag (char *buf, int oflag)
|
||||
{
|
||||
sprintf (buf, "%d ", oflag);
|
||||
|
||||
switch (oflag & O_ACCMODE)
|
||||
{
|
||||
case O_RDONLY: strcat (buf, "O_RDONLY"); break;
|
||||
case O_RDWR: strcat (buf, "O_RDWR"); break;
|
||||
case O_WRONLY: strcat (buf, "O_WRONLY"); break;
|
||||
default: abort ();
|
||||
}
|
||||
|
||||
#ifdef O_APPEND
|
||||
if (oflag & O_APPEND) strcat (buf, "|O_APPEND");
|
||||
#endif
|
||||
if (oflag & O_CREAT) strcat (buf, "|O_CREAT");
|
||||
#ifdef O_DSYNC
|
||||
if (oflag & O_DSYNC) strcat (buf, "|O_DSYNC");
|
||||
#endif
|
||||
if (oflag & O_EXCL) strcat (buf, "|O_EXCL");
|
||||
#ifdef O_LARGEFILE
|
||||
if (oflag & O_LARGEFILE) strcat (buf, "|O_LARGEFILE");
|
||||
#endif
|
||||
#ifdef O_NOCTTY
|
||||
if (oflag & O_NOCTTY) strcat (buf, "|O_NOCTTY");
|
||||
#endif
|
||||
#ifdef O_NONBLOCK
|
||||
if (oflag & O_NONBLOCK) strcat (buf, "|O_NONBLOCK");
|
||||
#endif
|
||||
#ifdef O_RSYNC
|
||||
if (oflag & O_RSYNC) strcat (buf, "|O_RSYNC");
|
||||
#endif
|
||||
#ifdef O_SYNC
|
||||
if (oflag & O_SYNC) strcat (buf, "|O_SYNC");
|
||||
#endif
|
||||
if (oflag & O_TRUNC) strcat (buf, "|O_TRUNC");
|
||||
}
|
||||
|
||||
/* Open a file (a magnetic tape device?) on the system specified in
|
||||
FILE_NAME, as the given user. FILE_NAME has the form `[USER@]HOST:FILE'.
|
||||
OPEN_MODE is O_RDONLY, O_WRONLY, etc. If successful, return the
|
||||
remote pipe number plus BIAS. REMOTE_SHELL may be overridden. On
|
||||
error, return -1. */
|
||||
int
|
||||
rmt_open__ (const char *file_name, int open_mode, int bias,
|
||||
const char *remote_shell)
|
||||
{
|
||||
int remote_pipe_number; /* pseudo, biased file descriptor */
|
||||
char *file_name_copy; /* copy of file_name string */
|
||||
char *remote_host; /* remote host name */
|
||||
char *remote_file; /* remote file name (often a device) */
|
||||
char *remote_user; /* remote user name */
|
||||
|
||||
/* Find an unused pair of file descriptors. */
|
||||
|
||||
for (remote_pipe_number = 0;
|
||||
remote_pipe_number < MAXUNIT;
|
||||
remote_pipe_number++)
|
||||
if (READ_SIDE (remote_pipe_number) == -1
|
||||
&& WRITE_SIDE (remote_pipe_number) == -1)
|
||||
break;
|
||||
|
||||
if (remote_pipe_number == MAXUNIT)
|
||||
{
|
||||
errno = EMFILE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Pull apart the system and device, and optional user. */
|
||||
|
||||
{
|
||||
char *cursor;
|
||||
|
||||
file_name_copy = xstrdup (file_name);
|
||||
remote_host = file_name_copy;
|
||||
remote_user = 0;
|
||||
remote_file = 0;
|
||||
|
||||
for (cursor = file_name_copy; *cursor; cursor++)
|
||||
switch (*cursor)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
/* Do not allow newlines in the file_name, since the protocol
|
||||
uses newline delimiters. */
|
||||
free (file_name_copy);
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
|
||||
case '@':
|
||||
if (!remote_user)
|
||||
{
|
||||
remote_user = remote_host;
|
||||
*cursor = '\0';
|
||||
remote_host = cursor + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ':':
|
||||
if (!remote_file)
|
||||
{
|
||||
*cursor = '\0';
|
||||
remote_file = cursor + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: Should somewhat validate the decoding, here. */
|
||||
|
||||
if (remote_user && *remote_user == '\0')
|
||||
remote_user = 0;
|
||||
|
||||
#if WITH_REXEC
|
||||
|
||||
/* Execute the remote command using rexec. */
|
||||
|
||||
READ_SIDE (remote_pipe_number) = _rmt_rexec (remote_host, remote_user);
|
||||
if (READ_SIDE (remote_pipe_number) < 0)
|
||||
{
|
||||
int e = errno;
|
||||
free (file_name_copy);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
|
||||
WRITE_SIDE (remote_pipe_number) = READ_SIDE (remote_pipe_number);
|
||||
|
||||
#else /* not WITH_REXEC */
|
||||
{
|
||||
const char *remote_shell_basename;
|
||||
pid_t status;
|
||||
|
||||
/* Identify the remote command to be executed. */
|
||||
|
||||
if (!remote_shell)
|
||||
{
|
||||
#ifdef REMOTE_SHELL
|
||||
remote_shell = REMOTE_SHELL;
|
||||
#else
|
||||
free (file_name_copy);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
remote_shell_basename = base_name (remote_shell);
|
||||
|
||||
/* Set up the pipes for the `rsh' command, and fork. */
|
||||
|
||||
if (pipe (to_remote[remote_pipe_number]) == -1
|
||||
|| pipe (from_remote[remote_pipe_number]) == -1)
|
||||
{
|
||||
int e = errno;
|
||||
free (file_name_copy);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = fork ();
|
||||
if (status == -1)
|
||||
{
|
||||
int e = errno;
|
||||
free (file_name_copy);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
/* Child. */
|
||||
|
||||
close (STDIN_FILENO);
|
||||
dup (to_remote[remote_pipe_number][PREAD]);
|
||||
close (to_remote[remote_pipe_number][PREAD]);
|
||||
close (to_remote[remote_pipe_number][PWRITE]);
|
||||
|
||||
close (STDOUT_FILENO);
|
||||
dup (from_remote[remote_pipe_number][PWRITE]);
|
||||
close (from_remote[remote_pipe_number][PREAD]);
|
||||
close (from_remote[remote_pipe_number][PWRITE]);
|
||||
|
||||
sys_reset_uid_gid ();
|
||||
|
||||
if (remote_user)
|
||||
execl (remote_shell, remote_shell_basename, remote_host,
|
||||
"-l", remote_user, rmt_command, (char *) 0);
|
||||
else
|
||||
execl (remote_shell, remote_shell_basename, remote_host,
|
||||
rmt_command, (char *) 0);
|
||||
|
||||
/* Bad problems if we get here. */
|
||||
|
||||
/* In a previous version, _exit was used here instead of exit. */
|
||||
error (EXIT_ON_EXEC_ERROR, errno, _("Cannot execute remote shell"));
|
||||
}
|
||||
|
||||
/* Parent. */
|
||||
|
||||
close (from_remote[remote_pipe_number][PWRITE]);
|
||||
close (to_remote[remote_pipe_number][PREAD]);
|
||||
}
|
||||
#endif /* not WITH_REXEC */
|
||||
|
||||
/* Attempt to open the tape device. */
|
||||
|
||||
{
|
||||
size_t remote_file_len = strlen (remote_file);
|
||||
char *command_buffer = xmalloc (remote_file_len + 1000);
|
||||
sprintf (command_buffer, "O%s\n", remote_file);
|
||||
encode_oflag (command_buffer + remote_file_len + 2, open_mode);
|
||||
strcat (command_buffer, "\n");
|
||||
if (do_command (remote_pipe_number, command_buffer) == -1
|
||||
|| get_status (remote_pipe_number) == -1)
|
||||
{
|
||||
int e = errno;
|
||||
free (command_buffer);
|
||||
free (file_name_copy);
|
||||
_rmt_shutdown (remote_pipe_number, e);
|
||||
return -1;
|
||||
}
|
||||
free (command_buffer);
|
||||
}
|
||||
|
||||
free (file_name_copy);
|
||||
return remote_pipe_number + bias;
|
||||
}
|
||||
|
||||
/* Close remote tape connection HANDLE and shut down. Return 0 if
|
||||
successful, -1 on error. */
|
||||
int
|
||||
rmt_close__ (int handle)
|
||||
{
|
||||
long int status;
|
||||
|
||||
if (do_command (handle, "C\n") == -1)
|
||||
return -1;
|
||||
|
||||
status = get_status (handle);
|
||||
_rmt_shutdown (handle, errno);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Read up to LENGTH bytes into BUFFER from remote tape connection HANDLE.
|
||||
Return the number of bytes read on success, SAFE_READ_ERROR on error. */
|
||||
size_t
|
||||
rmt_read__ (int handle, char *buffer, size_t length)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
size_t status;
|
||||
size_t rlen;
|
||||
size_t counter;
|
||||
|
||||
sprintf (command_buffer, "R%lu\n", (unsigned long) length);
|
||||
if (do_command (handle, command_buffer) == -1
|
||||
|| (status = get_status (handle)) == SAFE_READ_ERROR)
|
||||
return SAFE_READ_ERROR;
|
||||
|
||||
for (counter = 0; counter < status; counter += rlen, buffer += rlen)
|
||||
{
|
||||
rlen = safe_read (READ_SIDE (handle), buffer, status - counter);
|
||||
if (rlen == SAFE_READ_ERROR || rlen == 0)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return SAFE_READ_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Write LENGTH bytes from BUFFER to remote tape connection HANDLE.
|
||||
Return the number of bytes written. */
|
||||
size_t
|
||||
rmt_write__ (int handle, char *buffer, size_t length)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
RETSIGTYPE (*pipe_handler) ();
|
||||
size_t written;
|
||||
|
||||
sprintf (command_buffer, "W%lu\n", (unsigned long) length);
|
||||
if (do_command (handle, command_buffer) == -1)
|
||||
return 0;
|
||||
|
||||
pipe_handler = signal (SIGPIPE, SIG_IGN);
|
||||
written = full_write (WRITE_SIDE (handle), buffer, length);
|
||||
signal (SIGPIPE, pipe_handler);
|
||||
if (written == length)
|
||||
{
|
||||
long int r = get_status (handle);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
if (r == length)
|
||||
return length;
|
||||
written = r;
|
||||
}
|
||||
|
||||
/* Write error. */
|
||||
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return written;
|
||||
}
|
||||
|
||||
/* Perform an imitation lseek operation on remote tape connection
|
||||
HANDLE. Return the new file offset if successful, -1 if on error. */
|
||||
off_t
|
||||
rmt_lseek__ (int handle, off_t offset, int whence)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
char operand_buffer[UINTMAX_STRSIZE_BOUND];
|
||||
uintmax_t u = offset < 0 ? - (uintmax_t) offset : (uintmax_t) offset;
|
||||
char *p = operand_buffer + sizeof operand_buffer;
|
||||
|
||||
*--p = 0;
|
||||
do
|
||||
*--p = '0' + (int) (u % 10);
|
||||
while ((u /= 10) != 0);
|
||||
if (offset < 0)
|
||||
*--p = '-';
|
||||
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET: whence = 0; break;
|
||||
case SEEK_CUR: whence = 1; break;
|
||||
case SEEK_END: whence = 2; break;
|
||||
default: abort ();
|
||||
}
|
||||
|
||||
sprintf (command_buffer, "L%s\n%d\n", p, whence);
|
||||
|
||||
if (do_command (handle, command_buffer) == -1)
|
||||
return -1;
|
||||
|
||||
return get_status_off (handle);
|
||||
}
|
||||
|
||||
/* Perform a raw tape operation on remote tape connection HANDLE.
|
||||
Return the results of the ioctl, or -1 on error. */
|
||||
int
|
||||
rmt_ioctl__ (int handle, int operation, char *argument)
|
||||
{
|
||||
switch (operation)
|
||||
{
|
||||
default:
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
|
||||
#ifdef MTIOCTOP
|
||||
case MTIOCTOP:
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
char operand_buffer[UINTMAX_STRSIZE_BOUND];
|
||||
uintmax_t u = (((struct mtop *) argument)->mt_count < 0
|
||||
? - (uintmax_t) ((struct mtop *) argument)->mt_count
|
||||
: (uintmax_t) ((struct mtop *) argument)->mt_count);
|
||||
char *p = operand_buffer + sizeof operand_buffer;
|
||||
|
||||
*--p = 0;
|
||||
do
|
||||
*--p = '0' + (int) (u % 10);
|
||||
while ((u /= 10) != 0);
|
||||
if (((struct mtop *) argument)->mt_count < 0)
|
||||
*--p = '-';
|
||||
|
||||
/* MTIOCTOP is the easy one. Nothing is transferred in binary. */
|
||||
|
||||
sprintf (command_buffer, "I%d\n%s\n",
|
||||
((struct mtop *) argument)->mt_op, p);
|
||||
if (do_command (handle, command_buffer) == -1)
|
||||
return -1;
|
||||
|
||||
return get_status (handle);
|
||||
}
|
||||
#endif /* MTIOCTOP */
|
||||
|
||||
#ifdef MTIOCGET
|
||||
case MTIOCGET:
|
||||
{
|
||||
ssize_t status;
|
||||
size_t counter;
|
||||
|
||||
/* Grab the status and read it directly into the structure. This
|
||||
assumes that the status buffer is not padded and that 2 shorts
|
||||
fit in a long without any word alignment problems; i.e., the
|
||||
whole struct is contiguous. NOTE - this is probably NOT a good
|
||||
assumption. */
|
||||
|
||||
if (do_command (handle, "S") == -1
|
||||
|| (status = get_status (handle), status == -1))
|
||||
return -1;
|
||||
|
||||
for (; status > 0; status -= counter, argument += counter)
|
||||
{
|
||||
counter = safe_read (READ_SIDE (handle), argument, status);
|
||||
if (counter == SAFE_READ_ERROR || counter == 0)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for byte position. mt_type (or mt_model) is a small integer
|
||||
field (normally) so we will check its magnitude. If it is larger
|
||||
than 256, we will assume that the bytes are swapped and go through
|
||||
and reverse all the bytes. */
|
||||
|
||||
if (((struct mtget *) argument)->MTIO_CHECK_FIELD < 256)
|
||||
return 0;
|
||||
|
||||
for (counter = 0; counter < status; counter += 2)
|
||||
{
|
||||
char copy = argument[counter];
|
||||
|
||||
argument[counter] = argument[counter + 1];
|
||||
argument[counter + 1] = copy;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MTIOCGET */
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/* An interface to read and write that retries after interrupts.
|
||||
|
||||
Copyright (C) 1993, 1994, 1998, 2002, 2003, 2004 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
/* Specification. */
|
||||
#ifdef SAFE_WRITE
|
||||
# include "safe-write.h"
|
||||
#else
|
||||
# include "safe-read.h"
|
||||
#endif
|
||||
|
||||
/* Get ssize_t. */
|
||||
#include <sys/types.h>
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef EINTR
|
||||
# define IS_EINTR(x) ((x) == EINTR)
|
||||
#else
|
||||
# define IS_EINTR(x) 0
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef SAFE_WRITE
|
||||
# define safe_rw safe_write
|
||||
# define rw write
|
||||
#else
|
||||
# define safe_rw safe_read
|
||||
# define rw read
|
||||
# undef const
|
||||
# define const /* empty */
|
||||
#endif
|
||||
|
||||
/* Read(write) up to COUNT bytes at BUF from(to) descriptor FD, retrying if
|
||||
interrupted. Return the actual number of bytes read(written), zero for EOF,
|
||||
or SAFE_READ_ERROR(SAFE_WRITE_ERROR) upon error. */
|
||||
size_t
|
||||
safe_rw (int fd, void const *buf, size_t count)
|
||||
{
|
||||
/* Work around a bug in Tru64 5.1. Attempting to read more than
|
||||
INT_MAX bytes fails with errno == EINVAL. See
|
||||
<http://lists.gnu.org/archive/html/bug-gnu-utils/2002-04/msg00010.html>.
|
||||
When decreasing COUNT, keep it block-aligned. */
|
||||
enum { BUGGY_READ_MAXIMUM = INT_MAX & ~8191 };
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ssize_t result = rw (fd, buf, count);
|
||||
|
||||
if (0 <= result)
|
||||
return result;
|
||||
else if (IS_EINTR (errno))
|
||||
continue;
|
||||
else if (errno == EINVAL && BUGGY_READ_MAXIMUM < count)
|
||||
count = BUGGY_READ_MAXIMUM;
|
||||
else
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/* An interface to read() that retries after interrupts.
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define SAFE_READ_ERROR ((size_t) -1)
|
||||
|
||||
/* Read up to COUNT bytes at BUF from descriptor FD, retrying if interrupted.
|
||||
Return the actual number of bytes read, zero for EOF, or SAFE_READ_ERROR
|
||||
upon error. */
|
||||
extern size_t safe_read (int fd, void *buf, size_t count);
|
||||
@@ -1,19 +0,0 @@
|
||||
/* An interface to write that retries after interrupts.
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#define SAFE_WRITE
|
||||
#include "safe-read.c"
|
||||
@@ -1,25 +0,0 @@
|
||||
/* An interface to write() that retries after interrupts.
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define SAFE_WRITE_ERROR ((size_t) -1)
|
||||
|
||||
/* Write up to COUNT bytes at BUF to descriptor FD, retrying if interrupted.
|
||||
Return the actual number of bytes written, zero for EOF, or SAFE_WRITE_ERROR
|
||||
upon error. */
|
||||
extern size_t safe_write (int fd, const void *buf, size_t count);
|
||||
@@ -1,123 +0,0 @@
|
||||
/* savedir.c -- save the list of files in a directory in a string
|
||||
|
||||
Copyright 1990, 1997, 1998, 1999, 2000, 2001, 2003, 2004 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by David MacKenzie <[email protected]>. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "savedir.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
#else
|
||||
# define dirent direct
|
||||
# if HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if HAVE_SYS_DIR_H
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if HAVE_NDIR_H
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef CLOSEDIR_VOID
|
||||
/* Fake a return value. */
|
||||
# define CLOSEDIR(d) (closedir (d), 0)
|
||||
#else
|
||||
# define CLOSEDIR(d) closedir (d)
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xalloc.h"
|
||||
|
||||
/* Return a freshly allocated string containing the filenames
|
||||
in directory DIR, separated by '\0' characters;
|
||||
the end is marked by two '\0' characters in a row.
|
||||
Return NULL (setting errno) if DIR cannot be opened, read, or closed. */
|
||||
|
||||
#ifndef NAME_SIZE_DEFAULT
|
||||
# define NAME_SIZE_DEFAULT 512
|
||||
#endif
|
||||
|
||||
char *
|
||||
savedir (const char *dir)
|
||||
{
|
||||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
char *name_space;
|
||||
size_t allocated = NAME_SIZE_DEFAULT;
|
||||
size_t used = 0;
|
||||
int save_errno;
|
||||
|
||||
dirp = opendir (dir);
|
||||
if (dirp == NULL)
|
||||
return NULL;
|
||||
|
||||
name_space = xmalloc (allocated);
|
||||
|
||||
errno = 0;
|
||||
while ((dp = readdir (dirp)) != NULL)
|
||||
{
|
||||
/* Skip "", ".", and "..". "" is returned by at least one buggy
|
||||
implementation: Solaris 2.4 readdir on NFS file systems. */
|
||||
char const *entry = dp->d_name;
|
||||
if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0')
|
||||
{
|
||||
size_t entry_size = strlen (entry) + 1;
|
||||
if (used + entry_size < used)
|
||||
xalloc_die ();
|
||||
if (allocated <= used + entry_size)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (2 * allocated < allocated)
|
||||
xalloc_die ();
|
||||
allocated *= 2;
|
||||
}
|
||||
while (allocated <= used + entry_size);
|
||||
|
||||
name_space = xrealloc (name_space, allocated);
|
||||
}
|
||||
memcpy (name_space + used, entry, entry_size);
|
||||
used += entry_size;
|
||||
}
|
||||
}
|
||||
name_space[used] = '\0';
|
||||
save_errno = errno;
|
||||
if (CLOSEDIR (dirp) != 0)
|
||||
save_errno = errno;
|
||||
if (save_errno != 0)
|
||||
{
|
||||
free (name_space);
|
||||
errno = save_errno;
|
||||
return NULL;
|
||||
}
|
||||
return name_space;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/* Save the list of files in a directory in a string.
|
||||
|
||||
Copyright 1997, 1999, 2001, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by David MacKenzie <[email protected]>. */
|
||||
|
||||
#if !defined SAVEDIR_H_
|
||||
# define SAVEDIR_H_
|
||||
|
||||
char *savedir (const char *dir);
|
||||
|
||||
#endif
|
||||
@@ -1,47 +0,0 @@
|
||||
/* Case-insensitive string comparison functions.
|
||||
Copyright (C) 1995-1996, 2001, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _STRCASE_H
|
||||
#define _STRCASE_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Compare strings S1 and S2, ignoring case, returning less than, equal to or
|
||||
greater than zero if S1 is lexicographically less than, equal to or greater
|
||||
than S2.
|
||||
Note: This function does not work correctly in multibyte locales. */
|
||||
extern int strcasecmp (const char *s1, const char *s2);
|
||||
|
||||
/* Compare no more than N characters of strings S1 and S2, ignoring case,
|
||||
returning less than, equal to or greater than zero if S1 is
|
||||
lexicographically less than, equal to or greater than S2.
|
||||
Note: This function can not work correctly in multibyte locales. */
|
||||
extern int strncasecmp (const char *s1, const char *s2, size_t n);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _STRCASE_H */
|
||||
@@ -1,30 +0,0 @@
|
||||
/* Searching in a string.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Specification. */
|
||||
#include "strchrnul.h"
|
||||
|
||||
/* Find the first occurrence of C in S or the final NUL byte. */
|
||||
char *
|
||||
strchrnul (const char *s, int c_in)
|
||||
{
|
||||
char c = c_in;
|
||||
while (*s && (*s != c))
|
||||
s++;
|
||||
|
||||
return (char *) s;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/* Searching in a string.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_STRCHRNUL
|
||||
|
||||
/* Get strchrnul() declaration. */
|
||||
#include <string.h>
|
||||
|
||||
#else
|
||||
|
||||
/* Find the first occurrence of C in S or the final NUL byte. */
|
||||
extern char *strchrnul (const char *s, int c_in);
|
||||
|
||||
#endif
|
||||
@@ -1,39 +0,0 @@
|
||||
/* stripslash.c -- remove redundant trailing slashes from a file name
|
||||
Copyright (C) 1990, 2001, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "dirname.h"
|
||||
|
||||
/* Remove trailing slashes from PATH.
|
||||
Return true if a trailing slash was removed.
|
||||
This is useful when using filename completion from a shell that
|
||||
adds a "/" after directory names (such as tcsh and bash), because
|
||||
the Unix rename and rmdir system calls return an "Invalid argument" error
|
||||
when given a path that ends in "/" (except for the root directory). */
|
||||
|
||||
bool
|
||||
strip_trailing_slashes (char *path)
|
||||
{
|
||||
char *base = base_name (path);
|
||||
char *base_lim = base + base_len (base);
|
||||
bool had_slash = (*base_lim != '\0');
|
||||
*base_lim = '\0';
|
||||
return had_slash;
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/* Copyright (C) 1996, 1997, 1998, 2000, 2003 Free Software Foundation, Inc.
|
||||
|
||||
NOTE: The canonical source of this file is maintained with the GNU C Library.
|
||||
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef HAVE_DECL_STRNLEN
|
||||
"this configure-time declaration test was not run"
|
||||
#endif
|
||||
#if !HAVE_DECL_STRNLEN
|
||||
size_t strnlen ();
|
||||
#endif
|
||||
|
||||
#undef __strndup
|
||||
#undef strndup
|
||||
|
||||
#ifndef weak_alias
|
||||
# define __strndup strndup
|
||||
#endif
|
||||
|
||||
char *
|
||||
__strndup (const char *s, size_t n)
|
||||
{
|
||||
size_t len = strnlen (s, n);
|
||||
char *new = malloc (len + 1);
|
||||
|
||||
if (new == NULL)
|
||||
return NULL;
|
||||
|
||||
new[len] = '\0';
|
||||
return memcpy (new, s, len);
|
||||
}
|
||||
#ifdef weak_alias
|
||||
weak_alias (__strndup, strndup)
|
||||
#endif
|
||||
@@ -1,30 +0,0 @@
|
||||
/* Duplicate a size-bounded string.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_STRNDUP
|
||||
|
||||
/* Get strndup() declaration. */
|
||||
#include <string.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Return a newly allocated copy of at most N bytes of STRING. */
|
||||
extern char *strndup (const char *string, size_t n);
|
||||
|
||||
#endif
|
||||
@@ -1,48 +0,0 @@
|
||||
/* Find the length of STRING, but scan at most MAXLEN characters.
|
||||
Copyright (C) 1996, 1997, 1998, 2000-2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#undef strnlen
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#undef __strnlen
|
||||
#undef strnlen
|
||||
|
||||
#ifndef _LIBC
|
||||
# define strnlen rpl_strnlen
|
||||
#endif
|
||||
|
||||
#ifndef weak_alias
|
||||
# define __strnlen strnlen
|
||||
#endif
|
||||
|
||||
/* Find the length of STRING, but scan at most MAXLEN characters.
|
||||
If no '\0' terminator is found in that many characters, return MAXLEN. */
|
||||
|
||||
size_t
|
||||
__strnlen (const char *string, size_t maxlen)
|
||||
{
|
||||
const char *end = memchr (string, '\0', maxlen);
|
||||
return end ? (size_t) (end - string) : maxlen;
|
||||
}
|
||||
#ifdef weak_alias
|
||||
weak_alias (__strnlen, strnlen)
|
||||
#endif
|
||||
@@ -1,524 +0,0 @@
|
||||
/* System dependent definitions for GNU tar.
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
|
||||
2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <alloca.h>
|
||||
|
||||
#ifndef __attribute__
|
||||
/* This feature is available in gcc versions 2.5 and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
|
||||
# define __attribute__(spec) /* empty */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* IN_CTYPE_DOMAIN (C) is nonzero if the unsigned char C can safely be given
|
||||
as an argument to <ctype.h> macros like `isspace'. */
|
||||
#if STDC_HEADERS
|
||||
# define IN_CTYPE_DOMAIN(c) 1
|
||||
#else
|
||||
# define IN_CTYPE_DOMAIN(c) ((unsigned) (c) <= 0177)
|
||||
#endif
|
||||
|
||||
#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
|
||||
#define ISODIGIT(c) ((unsigned) (c) - '0' <= 7)
|
||||
#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
|
||||
#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
|
||||
|
||||
/* Declare string and memory handling routines. Take care that an ANSI
|
||||
string.h and pre-ANSI memory.h might conflict, and that memory.h and
|
||||
strings.h conflict on some systems. */
|
||||
|
||||
#if STDC_HEADERS || HAVE_STRING_H
|
||||
# include <string.h>
|
||||
# if !STDC_HEADERS && HAVE_MEMORY_H
|
||||
# include <memory.h>
|
||||
# endif
|
||||
#else
|
||||
# include <strings.h>
|
||||
# ifndef strchr
|
||||
# define strchr index
|
||||
# endif
|
||||
# ifndef strrchr
|
||||
# define strrchr rindex
|
||||
# endif
|
||||
# ifndef memcpy
|
||||
# define memcpy(d, s, n) bcopy ((char const *) (s), (char *) (d), n)
|
||||
# endif
|
||||
# ifndef memcmp
|
||||
# define memcmp(a, b, n) bcmp ((char const *) (a), (char const *) (b), n)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Declare errno. */
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
/* Declare open parameters. */
|
||||
|
||||
#if HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#else
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
/* Pick only one of the next three: */
|
||||
#ifndef O_RDONLY
|
||||
# define O_RDONLY 0 /* only allow read */
|
||||
#endif
|
||||
#ifndef O_WRONLY
|
||||
# define O_WRONLY 1 /* only allow write */
|
||||
#endif
|
||||
#ifndef O_RDWR
|
||||
# define O_RDWR 2 /* both are allowed */
|
||||
#endif
|
||||
#ifndef O_ACCMODE
|
||||
# define O_ACCMODE (O_RDONLY | O_RDWR | O_WRONLY)
|
||||
#endif
|
||||
/* The rest can be OR-ed in to the above: */
|
||||
#ifndef O_CREAT
|
||||
# define O_CREAT 8 /* create file if needed */
|
||||
#endif
|
||||
#ifndef O_EXCL
|
||||
# define O_EXCL 16 /* file cannot already exist */
|
||||
#endif
|
||||
#ifndef O_TRUNC
|
||||
# define O_TRUNC 32 /* truncate file on open */
|
||||
#endif
|
||||
/* MS-DOG forever, with my love! */
|
||||
#ifndef O_BINARY
|
||||
# define O_BINARY 0
|
||||
#endif
|
||||
|
||||
/* Declare file status routines and bits. */
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if !HAVE_LSTAT && !defined lstat
|
||||
# define lstat stat
|
||||
#endif
|
||||
|
||||
#if STX_HIDDEN && !_LARGE_FILES /* AIX */
|
||||
# ifdef stat
|
||||
# undef stat
|
||||
# endif
|
||||
# define stat(file_name, buf) statx (file_name, buf, STATSIZE, STX_HIDDEN)
|
||||
# ifdef lstat
|
||||
# undef lstat
|
||||
# endif
|
||||
# define lstat(file_name, buf) statx (file_name, buf, STATSIZE, STX_HIDDEN | STX_LINK)
|
||||
#endif
|
||||
|
||||
#if STAT_MACROS_BROKEN
|
||||
# undef S_ISBLK
|
||||
# undef S_ISCHR
|
||||
# undef S_ISCTG
|
||||
# undef S_ISDIR
|
||||
# undef S_ISFIFO
|
||||
# undef S_ISLNK
|
||||
# undef S_ISREG
|
||||
# undef S_ISSOCK
|
||||
#endif
|
||||
|
||||
/* On MSDOS, there are missing things from <sys/stat.h>. */
|
||||
#if MSDOS
|
||||
# define S_ISUID 0
|
||||
# define S_ISGID 0
|
||||
# define S_ISVTX 0
|
||||
#endif
|
||||
|
||||
#ifndef S_ISDIR
|
||||
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
#ifndef S_ISREG
|
||||
# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISBLK
|
||||
# ifdef S_IFBLK
|
||||
# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
|
||||
# else
|
||||
# define S_ISBLK(mode) 0
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISCHR
|
||||
# ifdef S_IFCHR
|
||||
# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
|
||||
# else
|
||||
# define S_ISCHR(mode) 0
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISCTG
|
||||
# ifdef S_IFCTG
|
||||
# define S_ISCTG(mode) (((mode) & S_IFMT) == S_IFCTG)
|
||||
# else
|
||||
# define S_ISCTG(mode) 0
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISDOOR
|
||||
# define S_ISDOOR(mode) 0
|
||||
#endif
|
||||
#ifndef S_ISFIFO
|
||||
# ifdef S_IFIFO
|
||||
# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
|
||||
# else
|
||||
# define S_ISFIFO(mode) 0
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISLNK
|
||||
# ifdef S_IFLNK
|
||||
# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
|
||||
# else
|
||||
# define S_ISLNK(mode) 0
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISSOCK
|
||||
# ifdef S_IFSOCK
|
||||
# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
|
||||
# else
|
||||
# define S_ISSOCK(mode) 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !HAVE_MKFIFO && !defined mkfifo && defined S_IFIFO
|
||||
# define mkfifo(file_name, mode) (mknod (file_name, (mode) | S_IFIFO, 0))
|
||||
#endif
|
||||
|
||||
#ifndef S_ISUID
|
||||
# define S_ISUID 0004000
|
||||
#endif
|
||||
#ifndef S_ISGID
|
||||
# define S_ISGID 0002000
|
||||
#endif
|
||||
#ifndef S_ISVTX
|
||||
# define S_ISVTX 0001000
|
||||
#endif
|
||||
#ifndef S_IRUSR
|
||||
# define S_IRUSR 0000400
|
||||
#endif
|
||||
#ifndef S_IWUSR
|
||||
# define S_IWUSR 0000200
|
||||
#endif
|
||||
#ifndef S_IXUSR
|
||||
# define S_IXUSR 0000100
|
||||
#endif
|
||||
#ifndef S_IRGRP
|
||||
# define S_IRGRP 0000040
|
||||
#endif
|
||||
#ifndef S_IWGRP
|
||||
# define S_IWGRP 0000020
|
||||
#endif
|
||||
#ifndef S_IXGRP
|
||||
# define S_IXGRP 0000010
|
||||
#endif
|
||||
#ifndef S_IROTH
|
||||
# define S_IROTH 0000004
|
||||
#endif
|
||||
#ifndef S_IWOTH
|
||||
# define S_IWOTH 0000002
|
||||
#endif
|
||||
#ifndef S_IXOTH
|
||||
# define S_IXOTH 0000001
|
||||
#endif
|
||||
|
||||
#define MODE_WXUSR (S_IWUSR | S_IXUSR)
|
||||
#define MODE_R (S_IRUSR | S_IRGRP | S_IROTH)
|
||||
#define MODE_RW (S_IWUSR | S_IWGRP | S_IWOTH | MODE_R)
|
||||
#define MODE_RWX (S_IXUSR | S_IXGRP | S_IXOTH | MODE_RW)
|
||||
#define MODE_ALL (S_ISUID | S_ISGID | S_ISVTX | MODE_RWX)
|
||||
|
||||
/* Include <unistd.h> before any preprocessor test of _POSIX_VERSION. */
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET
|
||||
# define SEEK_SET 0
|
||||
#endif
|
||||
#ifndef SEEK_CUR
|
||||
# define SEEK_CUR 1
|
||||
#endif
|
||||
#ifndef SEEK_END
|
||||
# define SEEK_END 2
|
||||
#endif
|
||||
|
||||
#ifndef STDIN_FILENO
|
||||
# define STDIN_FILENO 0
|
||||
#endif
|
||||
#ifndef STDOUT_FILENO
|
||||
# define STDOUT_FILENO 1
|
||||
#endif
|
||||
#ifndef STDERR_FILENO
|
||||
# define STDERR_FILENO 2
|
||||
#endif
|
||||
|
||||
/* Declare make device, major and minor. Since major is a function on
|
||||
SVR4, we have to resort to GOT_MAJOR instead of just testing if
|
||||
major is #define'd. */
|
||||
|
||||
#if MAJOR_IN_MKDEV
|
||||
# include <sys/mkdev.h>
|
||||
# define GOT_MAJOR
|
||||
#endif
|
||||
|
||||
#if MAJOR_IN_SYSMACROS
|
||||
# include <sys/sysmacros.h>
|
||||
# define GOT_MAJOR
|
||||
#endif
|
||||
|
||||
/* Some <sys/types.h> defines the macros. */
|
||||
#ifdef major
|
||||
# define GOT_MAJOR
|
||||
#endif
|
||||
|
||||
#ifndef GOT_MAJOR
|
||||
# if MSDOS
|
||||
# define major(device) (device)
|
||||
# define minor(device) (device)
|
||||
# define makedev(major, minor) (((major) << 8) | (minor))
|
||||
# define GOT_MAJOR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* For HP-UX before HP-UX 8, major/minor are not in <sys/sysmacros.h>. */
|
||||
#ifndef GOT_MAJOR
|
||||
# if defined(hpux) || defined(__hpux__) || defined(__hpux)
|
||||
# include <sys/mknod.h>
|
||||
# define GOT_MAJOR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef GOT_MAJOR
|
||||
# define major(device) (((device) >> 8) & 0xff)
|
||||
# define minor(device) ((device) & 0xff)
|
||||
# define makedev(major, minor) (((major) << 8) | (minor))
|
||||
#endif
|
||||
|
||||
#undef GOT_MAJOR
|
||||
|
||||
/* Declare wait status. */
|
||||
|
||||
#if HAVE_SYS_WAIT_H
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
#ifndef WEXITSTATUS
|
||||
# define WEXITSTATUS(s) (((s) >> 8) & 0xff)
|
||||
#endif
|
||||
#ifndef WIFSIGNALED
|
||||
# define WIFSIGNALED(s) (((s) & 0xffff) - 1 < (unsigned) 0xff)
|
||||
#endif
|
||||
#ifndef WTERMSIG
|
||||
# define WTERMSIG(s) ((s) & 0x7f)
|
||||
#endif
|
||||
|
||||
/* FIXME: It is wrong to use BLOCKSIZE for buffers when the logical block
|
||||
size is greater than 512 bytes; so ST_BLKSIZE code below, in preparation
|
||||
for some cleanup in this area, later. */
|
||||
|
||||
/* Extract or fake data from a `struct stat'. ST_BLKSIZE gives the
|
||||
optimal I/O blocksize for the file, in bytes. Some systems, like
|
||||
Sequents, return st_blksize of 0 on pipes. */
|
||||
|
||||
#define DEFAULT_ST_BLKSIZE 512
|
||||
|
||||
#if !HAVE_ST_BLKSIZE
|
||||
# define ST_BLKSIZE(statbuf) DEFAULT_ST_BLKSIZE
|
||||
#else
|
||||
# define ST_BLKSIZE(statbuf) \
|
||||
((statbuf).st_blksize > 0 ? (statbuf).st_blksize : DEFAULT_ST_BLKSIZE)
|
||||
#endif
|
||||
|
||||
/* Extract or fake data from a `struct stat'. ST_NBLOCKS gives the
|
||||
number of ST_NBLOCKSIZE-byte blocks in the file (including indirect blocks).
|
||||
HP-UX counts st_blocks in 1024-byte units,
|
||||
this loses when mixing HP-UX and BSD filesystems with NFS. AIX PS/2
|
||||
counts st_blocks in 4K units. */
|
||||
|
||||
#if !HAVE_ST_BLOCKS
|
||||
# if defined(_POSIX_SOURCE) || !defined(BSIZE)
|
||||
# define ST_NBLOCKS(statbuf) ((statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0))
|
||||
# else
|
||||
off_t st_blocks ();
|
||||
# define ST_NBLOCKS(statbuf) (st_blocks ((statbuf).st_size))
|
||||
# endif
|
||||
#else
|
||||
# define ST_NBLOCKS(statbuf) ((statbuf).st_blocks)
|
||||
# if defined(hpux) || defined(__hpux__) || defined(__hpux)
|
||||
# define ST_NBLOCKSIZE 1024
|
||||
# else
|
||||
# if defined(_AIX) && defined(_I386)
|
||||
# define ST_NBLOCKSIZE (4 * 1024)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ST_NBLOCKSIZE
|
||||
#define ST_NBLOCKSIZE 512
|
||||
#endif
|
||||
|
||||
/* This is a real challenge to properly get MTIO* symbols :-(. ISC uses
|
||||
<sys/gentape.h>. SCO and BSDi uses <sys/tape.h>; BSDi also requires
|
||||
<sys/tprintf.h> and <sys/device.h> for defining tp_dev and tpr_t. It
|
||||
seems that the rest use <sys/mtio.h>, which itself requires other files,
|
||||
depending on systems. Pyramid defines _IOW in <sgtty.h>, for example. */
|
||||
|
||||
#if HAVE_SYS_GENTAPE_H
|
||||
# include <sys/gentape.h>
|
||||
#else
|
||||
# if HAVE_SYS_TAPE_H
|
||||
# if HAVE_SYS_DEVICE_H
|
||||
# include <sys/device.h>
|
||||
# endif
|
||||
# if HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
# endif
|
||||
# if HAVE_SYS_BUF_H
|
||||
# include <sys/buf.h>
|
||||
# endif
|
||||
# if HAVE_SYS_TPRINTF_H
|
||||
# include <sys/tprintf.h>
|
||||
# endif
|
||||
# include <sys/tape.h>
|
||||
# else
|
||||
# if HAVE_SYS_MTIO_H
|
||||
# include <sys/ioctl.h>
|
||||
# if HAVE_SGTTY_H
|
||||
# include <sgtty.h>
|
||||
# endif
|
||||
# if HAVE_SYS_IO_TRIOCTL_H
|
||||
# include <sys/io/trioctl.h>
|
||||
# endif
|
||||
# include <sys/mtio.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Declare standard functions. */
|
||||
|
||||
#if STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
void *malloc ();
|
||||
char *getenv ();
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#if !defined _POSIX_VERSION && MSDOS
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#if WITH_DMALLOC
|
||||
# undef HAVE_DECL_VALLOC
|
||||
# define DMALLOC_FUNC_CHECK
|
||||
# include <dmalloc.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef MB_LEN_MAX
|
||||
# define MB_LEN_MAX 1
|
||||
#endif
|
||||
|
||||
#if HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/* These macros work even on ones'-complement hosts (!).
|
||||
The extra casts work around common compiler bugs. */
|
||||
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
|
||||
#define TYPE_MINIMUM(t) (TYPE_SIGNED (t) \
|
||||
? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \
|
||||
: (t) 0)
|
||||
#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
|
||||
|
||||
/* Bound on length of the string representing an integer value of type t.
|
||||
Subtract one for the sign bit if t is signed;
|
||||
302 / 1000 is log10 (2) rounded up;
|
||||
add one for integer division truncation;
|
||||
add one more for a minus sign if t is signed. */
|
||||
#define INT_STRLEN_BOUND(t) \
|
||||
((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
|
||||
+ 1 + TYPE_SIGNED (t))
|
||||
|
||||
#define UINTMAX_STRSIZE_BOUND (INT_STRLEN_BOUND (uintmax_t) + 1)
|
||||
|
||||
/* Prototypes for external functions. */
|
||||
|
||||
#if HAVE_LOCALE_H
|
||||
# include <locale.h>
|
||||
#endif
|
||||
#if !HAVE_SETLOCALE
|
||||
# define setlocale(category, locale) /* empty */
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#if defined(HAVE_SYS_TIME_H) && defined(TIME_WITH_SYS_TIME)
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
#if ! HAVE_DECL_TIME
|
||||
time_t time ();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UTIME_H
|
||||
# include <utime.h>
|
||||
#endif
|
||||
|
||||
/* Library modules. */
|
||||
|
||||
#include <dirname.h>
|
||||
#include <error.h>
|
||||
#include <savedir.h>
|
||||
#include <unlocked-io.h>
|
||||
#include <xalloc.h>
|
||||
|
||||
#include <gettext.h>
|
||||
#define _(msgid) gettext (msgid)
|
||||
#define N_(msgid) msgid
|
||||
|
||||
#if MSDOS
|
||||
# include <process.h>
|
||||
# define SET_BINARY_MODE(arc) setmode(arc, O_BINARY)
|
||||
# define ERRNO_IS_EACCES errno == EACCES
|
||||
# define mkdir(file, mode) (mkdir) (file)
|
||||
# define TTY_NAME "con"
|
||||
# define sys_reset_uid_gid()
|
||||
#else
|
||||
# include <pwd.h>
|
||||
# include <grp.h>
|
||||
# define SET_BINARY_MODE(arc)
|
||||
# define ERRNO_IS_EACCES 0
|
||||
# define TTY_NAME "/dev/tty"
|
||||
# define sys_reset_uid_gid() \
|
||||
do { setuid (getuid ()); setgid (getgid ()); } while (0)
|
||||
#endif
|
||||
|
||||
#if XENIX
|
||||
# include <sys/inode.h>
|
||||
#endif
|
||||
@@ -1,137 +0,0 @@
|
||||
/* Prefer faster, non-thread-safe stdio functions if available.
|
||||
|
||||
Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by Jim Meyering. */
|
||||
|
||||
#ifndef UNLOCKED_IO_H
|
||||
#define UNLOCKED_IO_H 1
|
||||
|
||||
/* These are wrappers for functions/macros from the GNU C library, and
|
||||
from other C libraries supporting POSIX's optional thread-safe functions.
|
||||
|
||||
The standard I/O functions are thread-safe. These *_unlocked ones are
|
||||
more efficient but not thread-safe. That they're not thread-safe is
|
||||
fine since all of the applications in this package are single threaded.
|
||||
|
||||
Also, some code that is shared with the GNU C library may invoke
|
||||
the *_unlocked functions directly. On hosts that lack those
|
||||
functions, invoke the non-thread-safe versions instead. */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if HAVE_DECL_CLEARERR_UNLOCKED
|
||||
# undef clearerr
|
||||
# define clearerr(x) clearerr_unlocked (x)
|
||||
#else
|
||||
# define clearerr_unlocked(x) clearerr (x)
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_FEOF_UNLOCKED
|
||||
# undef feof
|
||||
# define feof(x) feof_unlocked (x)
|
||||
#else
|
||||
# define feof_unlocked(x) feof (x)
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_FERROR_UNLOCKED
|
||||
# undef ferror
|
||||
# define ferror(x) ferror_unlocked (x)
|
||||
#else
|
||||
# define ferror_unlocked(x) ferror (x)
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_FFLUSH_UNLOCKED
|
||||
# undef fflush
|
||||
# define fflush(x) fflush_unlocked (x)
|
||||
#else
|
||||
# define fflush_unlocked(x) fflush (x)
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_FGETS_UNLOCKED
|
||||
# undef fgets
|
||||
# define fgets(x,y,z) fgets_unlocked (x,y,z)
|
||||
#else
|
||||
# define fgets_unlocked(x,y,z) fgets (x,y,z)
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_FPUTC_UNLOCKED
|
||||
# undef fputc
|
||||
# define fputc(x,y) fputc_unlocked (x,y)
|
||||
#else
|
||||
# define fputc_unlocked(x,y) fputc (x,y)
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_FPUTS_UNLOCKED
|
||||
# undef fputs
|
||||
# define fputs(x,y) fputs_unlocked (x,y)
|
||||
#else
|
||||
# define fputs_unlocked(x,y) fputs (x,y)
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_FREAD_UNLOCKED
|
||||
# undef fread
|
||||
# define fread(w,x,y,z) fread_unlocked (w,x,y,z)
|
||||
#else
|
||||
# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_FWRITE_UNLOCKED
|
||||
# undef fwrite
|
||||
# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z)
|
||||
#else
|
||||
# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_GETC_UNLOCKED
|
||||
# undef getc
|
||||
# define getc(x) getc_unlocked (x)
|
||||
#else
|
||||
# define getc_unlocked(x) getc (x)
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_GETCHAR_UNLOCKED
|
||||
# undef getchar
|
||||
# define getchar() getchar_unlocked ()
|
||||
#else
|
||||
# define getchar_unlocked() getchar ()
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_PUTC_UNLOCKED
|
||||
# undef putc
|
||||
# define putc(x,y) putc_unlocked (x,y)
|
||||
#else
|
||||
# define putc_unlocked(x,y) putc (x,y)
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_PUTCHAR_UNLOCKED
|
||||
# undef putchar
|
||||
# define putchar(x) putchar_unlocked (x)
|
||||
#else
|
||||
# define putchar_unlocked(x) putchar (x)
|
||||
#endif
|
||||
|
||||
#undef flockfile
|
||||
#define flockfile(x) ((void) 0)
|
||||
|
||||
#undef ftrylockfile
|
||||
#define ftrylockfile(x) 0
|
||||
|
||||
#undef funlockfile
|
||||
#define funlockfile(x) ((void) 0)
|
||||
|
||||
#endif /* UNLOCKED_IO_H */
|
||||
@@ -1,45 +0,0 @@
|
||||
/* Report a memory allocation failure and exit.
|
||||
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "xalloc.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "error.h"
|
||||
#include "exitfail.h"
|
||||
|
||||
#include "gettext.h"
|
||||
#define _(msgid) gettext (msgid)
|
||||
#define N_(msgid) msgid
|
||||
|
||||
void
|
||||
xalloc_die (void)
|
||||
{
|
||||
error (exit_failure, 0, "%s", _("memory exhausted"));
|
||||
|
||||
/* The `noreturn' cannot be given to error, since it may return if
|
||||
its first argument is 0. To help compilers understand the
|
||||
xalloc_die does not return, call abort. Also, the abort is a
|
||||
safety feature if exit_failure is 0 (which shouldn't happen). */
|
||||
abort ();
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/* xalloc.h -- malloc with out-of-memory checking
|
||||
|
||||
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef XALLOC_H_
|
||||
# define XALLOC_H_
|
||||
|
||||
# include <stddef.h>
|
||||
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
|
||||
# ifndef __attribute__
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
|
||||
# define __attribute__(x)
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef ATTRIBUTE_NORETURN
|
||||
# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
|
||||
# endif
|
||||
|
||||
/* This function is always triggered when memory is exhausted.
|
||||
It must be defined by the application, either explicitly
|
||||
or by using gnulib's xalloc-die module. This is the
|
||||
function to call when one wants the program to die because of a
|
||||
memory allocation failure. */
|
||||
extern void xalloc_die (void) ATTRIBUTE_NORETURN;
|
||||
|
||||
void *xmalloc (size_t s);
|
||||
void *xnmalloc (size_t n, size_t s);
|
||||
void *xzalloc (size_t s);
|
||||
void *xcalloc (size_t n, size_t s);
|
||||
void *xrealloc (void *p, size_t s);
|
||||
void *xnrealloc (void *p, size_t n, size_t s);
|
||||
void *x2realloc (void *p, size_t *pn);
|
||||
void *x2nrealloc (void *p, size_t *pn, size_t s);
|
||||
void *xmemdup (void const *p, size_t s);
|
||||
char *xstrdup (char const *str);
|
||||
|
||||
/* Return 1 if an array of N objects, each of size S, cannot exist due
|
||||
to size arithmetic overflow. S must be positive and N must be
|
||||
nonnegative. This is a macro, not an inline function, so that it
|
||||
works correctly even when SIZE_MAX < N.
|
||||
|
||||
By gnulib convention, SIZE_MAX represents overflow in size
|
||||
calculations, so the conservative dividend to use here is
|
||||
SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
|
||||
However, malloc (SIZE_MAX) fails on all known hosts where
|
||||
sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
|
||||
exactly-SIZE_MAX allocations on such hosts; this avoids a test and
|
||||
branch when S is known to be 1. */
|
||||
# define xalloc_oversized(n, s) \
|
||||
((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
|
||||
#endif /* !XALLOC_H_ */
|
||||
@@ -1,229 +0,0 @@
|
||||
/* xmalloc.c -- malloc with out of memory checking
|
||||
|
||||
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "xalloc.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX ((size_t) -1)
|
||||
#endif
|
||||
|
||||
/* Allocate an array of N objects, each with S bytes of memory,
|
||||
dynamically, with error checking. S must be nonzero. */
|
||||
|
||||
static inline void *
|
||||
xnmalloc_inline (size_t n, size_t s)
|
||||
{
|
||||
void *p;
|
||||
if (xalloc_oversized (n, s) || (! (p = malloc (n * s)) && n != 0))
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
|
||||
void *
|
||||
xnmalloc (size_t n, size_t s)
|
||||
{
|
||||
return xnmalloc_inline (n, s);
|
||||
}
|
||||
|
||||
/* Allocate N bytes of memory dynamically, with error checking. */
|
||||
|
||||
void *
|
||||
xmalloc (size_t n)
|
||||
{
|
||||
return xnmalloc_inline (n, 1);
|
||||
}
|
||||
|
||||
/* Change the size of an allocated block of memory P to an array of N
|
||||
objects each of S bytes, with error checking. S must be nonzero. */
|
||||
|
||||
static inline void *
|
||||
xnrealloc_inline (void *p, size_t n, size_t s)
|
||||
{
|
||||
if (xalloc_oversized (n, s) || (! (p = realloc (p, n * s)) && n != 0))
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
|
||||
void *
|
||||
xnrealloc (void *p, size_t n, size_t s)
|
||||
{
|
||||
return xnrealloc_inline (p, n, s);
|
||||
}
|
||||
|
||||
/* Change the size of an allocated block of memory P to N bytes,
|
||||
with error checking. */
|
||||
|
||||
void *
|
||||
xrealloc (void *p, size_t n)
|
||||
{
|
||||
return xnrealloc_inline (p, n, 1);
|
||||
}
|
||||
|
||||
|
||||
/* If P is null, allocate a block of at least *PN such objects;
|
||||
otherwise, reallocate P so that it contains more than *PN objects
|
||||
each of S bytes. *PN must be nonzero unless P is null, and S must
|
||||
be nonzero. Set *PN to the new number of objects, and return the
|
||||
pointer to the new block. *PN is never set to zero, and the
|
||||
returned pointer is never null.
|
||||
|
||||
Repeated reallocations are guaranteed to make progress, either by
|
||||
allocating an initial block with a nonzero size, or by allocating a
|
||||
larger block.
|
||||
|
||||
In the following implementation, nonzero sizes are doubled so that
|
||||
repeated reallocations have O(N log N) overall cost rather than
|
||||
O(N**2) cost, but the specification for this function does not
|
||||
guarantee that sizes are doubled.
|
||||
|
||||
Here is an example of use:
|
||||
|
||||
int *p = NULL;
|
||||
size_t used = 0;
|
||||
size_t allocated = 0;
|
||||
|
||||
void
|
||||
append_int (int value)
|
||||
{
|
||||
if (used == allocated)
|
||||
p = x2nrealloc (p, &allocated, sizeof *p);
|
||||
p[used++] = value;
|
||||
}
|
||||
|
||||
This causes x2nrealloc to allocate a block of some nonzero size the
|
||||
first time it is called.
|
||||
|
||||
To have finer-grained control over the initial size, set *PN to a
|
||||
nonzero value before calling this function with P == NULL. For
|
||||
example:
|
||||
|
||||
int *p = NULL;
|
||||
size_t used = 0;
|
||||
size_t allocated = 0;
|
||||
size_t allocated1 = 1000;
|
||||
|
||||
void
|
||||
append_int (int value)
|
||||
{
|
||||
if (used == allocated)
|
||||
{
|
||||
p = x2nrealloc (p, &allocated1, sizeof *p);
|
||||
allocated = allocated1;
|
||||
}
|
||||
p[used++] = value;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
static inline void *
|
||||
x2nrealloc_inline (void *p, size_t *pn, size_t s)
|
||||
{
|
||||
size_t n = *pn;
|
||||
|
||||
if (! p)
|
||||
{
|
||||
if (! n)
|
||||
{
|
||||
/* The approximate size to use for initial small allocation
|
||||
requests, when the invoking code specifies an old size of
|
||||
zero. 64 bytes is the largest "small" request for the
|
||||
GNU C library malloc. */
|
||||
enum { DEFAULT_MXFAST = 64 };
|
||||
|
||||
n = DEFAULT_MXFAST / s;
|
||||
n += !n;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SIZE_MAX / 2 / s < n)
|
||||
xalloc_die ();
|
||||
n *= 2;
|
||||
}
|
||||
|
||||
*pn = n;
|
||||
return xrealloc (p, n * s);
|
||||
}
|
||||
|
||||
void *
|
||||
x2nrealloc (void *p, size_t *pn, size_t s)
|
||||
{
|
||||
return x2nrealloc_inline (p, pn, s);
|
||||
}
|
||||
|
||||
/* If P is null, allocate a block of at least *PN bytes; otherwise,
|
||||
reallocate P so that it contains more than *PN bytes. *PN must be
|
||||
nonzero unless P is null. Set *PN to the new block's size, and
|
||||
return the pointer to the new block. *PN is never set to zero, and
|
||||
the returned pointer is never null. */
|
||||
|
||||
void *
|
||||
x2realloc (void *p, size_t *pn)
|
||||
{
|
||||
return x2nrealloc_inline (p, pn, 1);
|
||||
}
|
||||
|
||||
/* Allocate S bytes of zeroed memory dynamically, with error checking.
|
||||
There's no need for xnzalloc (N, S), since it would be equivalent
|
||||
to xcalloc (N, S). */
|
||||
|
||||
void *
|
||||
xzalloc (size_t s)
|
||||
{
|
||||
return memset (xmalloc (s), 0, s);
|
||||
}
|
||||
|
||||
/* Allocate zeroed memory for N elements of S bytes, with error
|
||||
checking. S must be nonzero. */
|
||||
|
||||
void *
|
||||
xcalloc (size_t n, size_t s)
|
||||
{
|
||||
void *p;
|
||||
/* Test for overflow, since some calloc implementations don't have
|
||||
proper overflow checks. */
|
||||
if (xalloc_oversized (n, s) || (! (p = calloc (n, s)) && n != 0))
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Clone an object P of size S, with error checking. There's no need
|
||||
for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
|
||||
need for an arithmetic overflow check. */
|
||||
|
||||
void *
|
||||
xmemdup (void const *p, size_t s)
|
||||
{
|
||||
return memcpy (xmalloc (s), p, s);
|
||||
}
|
||||
|
||||
/* Clone STRING. */
|
||||
|
||||
char *
|
||||
xstrdup (char const *string)
|
||||
{
|
||||
return xmemdup (string, strlen (string) + 1);
|
||||
}
|
||||
+6
-6
@@ -56,7 +56,7 @@ struct option long_opts[] =
|
||||
{"list", 0, &table_flag, TRUE},
|
||||
{"make-directories", 0, &create_dir_flag, TRUE},
|
||||
{"message", 1, 0, 'M'},
|
||||
{"no-absolute-filenames", 0, 0, 136},
|
||||
{"absolute-filenames", 0, 0, 136},
|
||||
{"no-preserve-owner", 0, 0, 134},
|
||||
{"nonmatching", 0, ©_matching_files, FALSE},
|
||||
{"numeric-uid-gid", 0, &numeric_uid, TRUE},
|
||||
@@ -105,7 +105,7 @@ Usage: %s {-o|--create} [-0acvABLV] [-C bytes] [-H format] [-M message]\n\
|
||||
[--unconditional] [--verbose] [--block-size=blocks] [--swap-halfwords]\n\
|
||||
[--io-size=bytes] [--pattern-file=file] [--format=format]\n\
|
||||
[--owner=[user][:.][group]] [--no-preserve-owner] [--message=message]\n\
|
||||
[--force-local] [--no-absolute-filenames] [--sparse] [--only-verify-crc]\n\
|
||||
[--force-local] [--absolute-filenames] [--sparse] [--only-verify-crc]\n\
|
||||
[--quiet] [--help] [--version] [pattern...] [< archive]\n",
|
||||
program_name);
|
||||
fprintf (fp, "\
|
||||
@@ -266,8 +266,8 @@ crc newc odc bin ustar tar (all-caps also recognized)", optarg);
|
||||
numeric_uid = TRUE;
|
||||
break;
|
||||
|
||||
case 136: /* --no-absolute-filenames */
|
||||
no_abs_paths_flag = TRUE;
|
||||
case 136: /* --absolute-filenames */
|
||||
abs_paths_flag = TRUE;
|
||||
break;
|
||||
|
||||
case 134: /* --no-preserve-owner */
|
||||
@@ -414,7 +414,7 @@ crc newc odc bin ustar tar (all-caps also recognized)", optarg);
|
||||
|| retain_time_flag || no_chown_flag || set_owner_flag
|
||||
|| set_group_flag || swap_bytes_flag || swap_halfwords_flag
|
||||
|| (append_flag && !(archive_name || output_archive_name))
|
||||
|| rename_batch_file || no_abs_paths_flag
|
||||
|| rename_batch_file || abs_paths_flag
|
||||
|| input_archive_name || (archive_name && output_archive_name))
|
||||
usage (stderr, 2);
|
||||
if (archive_format == arf_unknown)
|
||||
@@ -429,7 +429,7 @@ crc newc odc bin ustar tar (all-caps also recognized)", optarg);
|
||||
if (argc - 1 != optind || archive_format != arf_unknown
|
||||
|| swap_bytes_flag || swap_halfwords_flag
|
||||
|| table_flag || rename_flag || append_flag
|
||||
|| rename_batch_file || no_abs_paths_flag)
|
||||
|| rename_batch_file || abs_paths_flag)
|
||||
usage (stderr, 2);
|
||||
directory_name = argv[optind];
|
||||
}
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
/* Extended cpio format from POSIX.1.
|
||||
Copyright (C) 1992 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _CPIO_H
|
||||
|
||||
#define _CPIO_H 1
|
||||
|
||||
/* A cpio archive consists of a sequence of files.
|
||||
Each file has a 76 byte header,
|
||||
a variable length, NUL terminated filename,
|
||||
and variable length file data.
|
||||
A header for a filename "TRAILER!!!" indicates the end of the archive. */
|
||||
|
||||
/* All the fields in the header are ISO 646 (approximately ASCII) strings
|
||||
of octal numbers, left padded, not NUL terminated.
|
||||
|
||||
Field Name Length in Bytes Notes
|
||||
c_magic 6 must be "070707"
|
||||
c_dev 6
|
||||
c_ino 6
|
||||
c_mode 6 see below for value
|
||||
c_uid 6
|
||||
c_gid 6
|
||||
c_nlink 6
|
||||
c_rdev 6 only valid for chr and blk special files
|
||||
c_mtime 11
|
||||
c_namesize 6 count includes terminating NUL in pathname
|
||||
c_filesize 11 must be 0 for FIFOs and directories */
|
||||
|
||||
/* Values for c_mode, OR'd together: */
|
||||
|
||||
#define C_IRUSR 000400
|
||||
#define C_IWUSR 000200
|
||||
#define C_IXUSR 000100
|
||||
#define C_IRGRP 000040
|
||||
#define C_IWGRP 000020
|
||||
#define C_IXGRP 000010
|
||||
#define C_IROTH 000004
|
||||
#define C_IWOTH 000002
|
||||
#define C_IXOTH 000001
|
||||
|
||||
#define C_ISUID 004000
|
||||
#define C_ISGID 002000
|
||||
#define C_ISVTX 001000
|
||||
|
||||
#define C_ISBLK 060000
|
||||
#define C_ISCHR 020000
|
||||
#define C_ISDIR 040000
|
||||
#define C_ISFIFO 010000
|
||||
#define C_ISSOCK 0140000
|
||||
#define C_ISLNK 0120000
|
||||
#define C_ISCTG 0110000
|
||||
#define C_ISREG 0100000
|
||||
|
||||
#endif /* cpio.h */
|
||||
@@ -1,90 +0,0 @@
|
||||
/* Extended cpio header from POSIX.1.
|
||||
Copyright (C) 1992 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _CPIOHDR_H
|
||||
|
||||
#define _CPIOHDR_H 1
|
||||
|
||||
#include <cpio.h>
|
||||
|
||||
struct old_cpio_header
|
||||
{
|
||||
unsigned short c_magic;
|
||||
short c_dev;
|
||||
unsigned short c_ino;
|
||||
unsigned short c_mode;
|
||||
unsigned short c_uid;
|
||||
unsigned short c_gid;
|
||||
unsigned short c_nlink;
|
||||
short c_rdev;
|
||||
unsigned short c_mtimes[2];
|
||||
unsigned short c_namesize;
|
||||
unsigned short c_filesizes[2];
|
||||
unsigned long c_mtime; /* Long-aligned copy of `c_mtimes'. */
|
||||
unsigned long c_filesize; /* Long-aligned copy of `c_filesizes'. */
|
||||
char *c_name;
|
||||
};
|
||||
|
||||
/* "New" portable format and CRC format:
|
||||
|
||||
Each file has a 110 byte header,
|
||||
a variable length, NUL terminated filename,
|
||||
and variable length file data.
|
||||
A header for a filename "TRAILER!!!" indicates the end of the archive. */
|
||||
|
||||
/* All the fields in the header are ISO 646 (approximately ASCII) strings
|
||||
of hexadecimal numbers, left padded, not NUL terminated.
|
||||
|
||||
Field Name Length in Bytes Notes
|
||||
c_magic 6 "070701" for "new" portable format
|
||||
"070702" for CRC format
|
||||
c_ino 8
|
||||
c_mode 8
|
||||
c_uid 8
|
||||
c_gid 8
|
||||
c_nlink 8
|
||||
c_mtime 8
|
||||
c_filesize 8 must be 0 for FIFOs and directories
|
||||
c_maj 8
|
||||
c_min 8
|
||||
c_rmaj 8 only valid for chr and blk special files
|
||||
c_rmin 8 only valid for chr and blk special files
|
||||
c_namesize 8 count includes terminating NUL in pathname
|
||||
c_chksum 8 0 for "new" portable format; for CRC format
|
||||
the sum of all the bytes in the file */
|
||||
|
||||
struct new_cpio_header
|
||||
{
|
||||
unsigned short c_magic;
|
||||
unsigned long c_ino;
|
||||
unsigned long c_mode;
|
||||
unsigned long c_uid;
|
||||
unsigned long c_gid;
|
||||
unsigned long c_nlink;
|
||||
unsigned long c_mtime;
|
||||
unsigned long c_filesize;
|
||||
long c_dev_maj;
|
||||
long c_dev_min;
|
||||
long c_rdev_maj;
|
||||
long c_rdev_min;
|
||||
unsigned long c_namesize;
|
||||
unsigned long c_chksum;
|
||||
char *c_name;
|
||||
char *c_tar_linkname;
|
||||
};
|
||||
|
||||
#endif /* cpiohdr.h */
|
||||
@@ -1,42 +0,0 @@
|
||||
/* defer.c - handle "defered" links in newc and crc archives
|
||||
Copyright (C) 1993,2003,2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "cpiohdr.h"
|
||||
#include "extern.h"
|
||||
#include "defer.h"
|
||||
|
||||
struct deferment *
|
||||
create_deferment (struct new_cpio_header *file_hdr)
|
||||
{
|
||||
struct deferment *d;
|
||||
d = (struct deferment *) xmalloc (sizeof (struct deferment) );
|
||||
d->header = *file_hdr;
|
||||
d->header.c_name = (char *) xmalloc (strlen (file_hdr->c_name) + 1);
|
||||
strcpy (d->header.c_name, file_hdr->c_name);
|
||||
return d;
|
||||
}
|
||||
|
||||
void
|
||||
free_deferment (struct deferment *d)
|
||||
{
|
||||
free (d->header.c_name);
|
||||
free (d);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/* defer.h
|
||||
Copyright (C) 1993, 2001, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
struct deferment
|
||||
{
|
||||
struct deferment *next;
|
||||
struct new_cpio_header header;
|
||||
};
|
||||
|
||||
struct deferment *create_deferment P_((struct new_cpio_header *file_hdr));
|
||||
void free_deferment P_((struct deferment *d));
|
||||
@@ -1,107 +0,0 @@
|
||||
/* dstring.c - The dynamic string handling routines used by cpio.
|
||||
Copyright (C) 1990, 1991, 1992, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
|
||||
#include <string.h>
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#include "dstring.h"
|
||||
|
||||
#if __STDC__
|
||||
# define P_(s) s
|
||||
#else
|
||||
# define P_(s) ()
|
||||
#endif
|
||||
char *xmalloc P_((unsigned n));
|
||||
char *xrealloc P_((char *p, unsigned n));
|
||||
|
||||
/* Initialiaze dynamic string STRING with space for SIZE characters. */
|
||||
|
||||
void
|
||||
ds_init (dynamic_string *string, int size)
|
||||
{
|
||||
string->ds_length = size;
|
||||
string->ds_string = (char *) xmalloc (size);
|
||||
}
|
||||
|
||||
/* Expand dynamic string STRING, if necessary, to hold SIZE characters. */
|
||||
|
||||
void
|
||||
ds_resize (dynamic_string *string, int size)
|
||||
{
|
||||
if (size > string->ds_length)
|
||||
{
|
||||
string->ds_length = size;
|
||||
string->ds_string = (char *) xrealloc ((char *) string->ds_string, size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Dynamic string S gets a string terminated by the EOS character
|
||||
(which is removed) from file F. S will increase
|
||||
in size during the function if the string from F is longer than
|
||||
the current size of S.
|
||||
Return NULL if end of file is detected. Otherwise,
|
||||
Return a pointer to the null-terminated string in S. */
|
||||
|
||||
char *
|
||||
ds_fgetstr (FILE *f, dynamic_string *s, char eos)
|
||||
{
|
||||
int insize; /* Amount needed for line. */
|
||||
int strsize; /* Amount allocated for S. */
|
||||
int next_ch;
|
||||
|
||||
/* Initialize. */
|
||||
insize = 0;
|
||||
strsize = s->ds_length;
|
||||
|
||||
/* Read the input string. */
|
||||
next_ch = getc (f);
|
||||
while (next_ch != eos && next_ch != EOF)
|
||||
{
|
||||
if (insize >= strsize - 1)
|
||||
{
|
||||
ds_resize (s, strsize * 2 + 2);
|
||||
strsize = s->ds_length;
|
||||
}
|
||||
s->ds_string[insize++] = next_ch;
|
||||
next_ch = getc (f);
|
||||
}
|
||||
s->ds_string[insize++] = '\0';
|
||||
|
||||
if (insize == 1 && next_ch == EOF)
|
||||
return NULL;
|
||||
else
|
||||
return s->ds_string;
|
||||
}
|
||||
|
||||
char *
|
||||
ds_fgets (FILE *f, dynamic_string *s)
|
||||
{
|
||||
return ds_fgetstr (f, s, '\n');
|
||||
}
|
||||
|
||||
char *
|
||||
ds_fgetname (FILE *f, dynamic_string *s)
|
||||
{
|
||||
return ds_fgetstr (f, s, '\0');
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/* dstring.h - Dynamic string handling include file. Requires strings.h.
|
||||
Copyright (C) 1990, 1991, 1992, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
/* A dynamic string consists of record that records the size of an
|
||||
allocated string and the pointer to that string. The actual string
|
||||
is a normal zero byte terminated string that can be used with the
|
||||
usual string functions. The major difference is that the
|
||||
dynamic_string routines know how to get more space if it is needed
|
||||
by allocating new space and copying the current string. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int ds_length; /* Actual amount of storage allocated. */
|
||||
char *ds_string; /* String. */
|
||||
} dynamic_string;
|
||||
|
||||
|
||||
/* Macros that look similar to the original string functions.
|
||||
WARNING: These macros work only on pointers to dynamic string records.
|
||||
If used with a real record, an "&" must be used to get the pointer. */
|
||||
#define ds_strlen(s) strlen ((s)->ds_string)
|
||||
#define ds_strcmp(s1, s2) strcmp ((s1)->ds_string, (s2)->ds_string)
|
||||
#define ds_strncmp(s1, s2, n) strncmp ((s1)->ds_string, (s2)->ds_string, n)
|
||||
#define ds_index(s, c) index ((s)->ds_string, c)
|
||||
#define ds_rindex(s, c) rindex ((s)->ds_string, c)
|
||||
|
||||
void ds_init (dynamic_string *string, int size);
|
||||
void ds_resize (dynamic_string *string, int size);
|
||||
char *ds_fgetname (FILE *f, dynamic_string *s);
|
||||
char *ds_fgets (FILE *f, dynamic_string *s);
|
||||
char *ds_fgetstr (FILE *f, dynamic_string *s, char eos);
|
||||
@@ -1,242 +0,0 @@
|
||||
/* filemode.c -- make a string describing file modes
|
||||
Copyright (C) 1985, 1990, 1993, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if !S_IRUSR
|
||||
# if S_IREAD
|
||||
# define S_IRUSR S_IREAD
|
||||
# else
|
||||
# define S_IRUSR 00400
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !S_IWUSR
|
||||
# if S_IWRITE
|
||||
# define S_IWUSR S_IWRITE
|
||||
# else
|
||||
# define S_IWUSR 00200
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !S_IXUSR
|
||||
# if S_IEXEC
|
||||
# define S_IXUSR S_IEXEC
|
||||
# else
|
||||
# define S_IXUSR 00100
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef STAT_MACROS_BROKEN
|
||||
#undef S_ISBLK
|
||||
#undef S_ISCHR
|
||||
#undef S_ISDIR
|
||||
#undef S_ISFIFO
|
||||
#undef S_ISLNK
|
||||
#undef S_ISMPB
|
||||
#undef S_ISMPC
|
||||
#undef S_ISNWK
|
||||
#undef S_ISREG
|
||||
#undef S_ISSOCK
|
||||
#endif /* STAT_MACROS_BROKEN. */
|
||||
|
||||
#if !defined(S_ISBLK) && defined(S_IFBLK)
|
||||
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
|
||||
#endif
|
||||
#if !defined(S_ISCHR) && defined(S_IFCHR)
|
||||
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
|
||||
#endif
|
||||
#if !defined(S_ISDIR) && defined(S_IFDIR)
|
||||
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
#if !defined(S_ISREG) && defined(S_IFREG)
|
||||
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
#if !defined(S_ISFIFO) && defined(S_IFIFO)
|
||||
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
|
||||
#endif
|
||||
#if !defined(S_ISLNK) && defined(S_IFLNK)
|
||||
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
||||
#endif
|
||||
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
|
||||
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
|
||||
#endif
|
||||
#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
|
||||
#define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
|
||||
#define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
|
||||
#endif
|
||||
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
|
||||
#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
|
||||
#endif
|
||||
|
||||
/* Return a character indicating the type of file described by
|
||||
file mode BITS:
|
||||
'd' for directories
|
||||
'b' for block special files
|
||||
'c' for character special files
|
||||
'm' for multiplexor files
|
||||
'l' for symbolic links
|
||||
's' for sockets
|
||||
'p' for fifos
|
||||
'-' for regular files
|
||||
'?' for any other file type. */
|
||||
|
||||
static char
|
||||
ftypelet (long bits)
|
||||
{
|
||||
#ifdef S_ISBLK
|
||||
if (S_ISBLK (bits))
|
||||
return 'b';
|
||||
#endif
|
||||
if (S_ISCHR (bits))
|
||||
return 'c';
|
||||
if (S_ISDIR (bits))
|
||||
return 'd';
|
||||
if (S_ISREG (bits))
|
||||
return '-';
|
||||
#ifdef S_ISFIFO
|
||||
if (S_ISFIFO (bits))
|
||||
return 'p';
|
||||
#endif
|
||||
#ifdef S_ISLNK
|
||||
if (S_ISLNK (bits))
|
||||
return 'l';
|
||||
#endif
|
||||
#ifdef S_ISSOCK
|
||||
if (S_ISSOCK (bits))
|
||||
return 's';
|
||||
#endif
|
||||
#ifdef S_ISMPC
|
||||
if (S_ISMPC (bits))
|
||||
return 'm';
|
||||
#endif
|
||||
#ifdef S_ISNWK
|
||||
if (S_ISNWK (bits))
|
||||
return 'n';
|
||||
#endif
|
||||
return '?';
|
||||
}
|
||||
|
||||
/* Look at read, write, and execute bits in BITS and set
|
||||
flags in CHARS accordingly. */
|
||||
|
||||
static void
|
||||
rwx (unsigned short bits, char *chars)
|
||||
{
|
||||
chars[0] = (bits & S_IRUSR) ? 'r' : '-';
|
||||
chars[1] = (bits & S_IWUSR) ? 'w' : '-';
|
||||
chars[2] = (bits & S_IXUSR) ? 'x' : '-';
|
||||
}
|
||||
|
||||
/* Set the 's' and 't' flags in file attributes string CHARS,
|
||||
according to the file mode BITS. */
|
||||
|
||||
static void
|
||||
setst (unsigned short bits, char *chars)
|
||||
{
|
||||
#ifdef S_ISUID
|
||||
if (bits & S_ISUID)
|
||||
{
|
||||
if (chars[3] != 'x')
|
||||
/* Set-uid, but not executable by owner. */
|
||||
chars[3] = 'S';
|
||||
else
|
||||
chars[3] = 's';
|
||||
}
|
||||
#endif
|
||||
#ifdef S_ISGID
|
||||
if (bits & S_ISGID)
|
||||
{
|
||||
if (chars[6] != 'x')
|
||||
/* Set-gid, but not executable by group. */
|
||||
chars[6] = 'S';
|
||||
else
|
||||
chars[6] = 's';
|
||||
}
|
||||
#endif
|
||||
#ifdef S_ISVTX
|
||||
if (bits & S_ISVTX)
|
||||
{
|
||||
if (chars[9] != 'x')
|
||||
/* Sticky, but not executable by others. */
|
||||
chars[9] = 'T';
|
||||
else
|
||||
chars[9] = 't';
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Like filemodestring (see below), but only the relevant part of the
|
||||
`struct stat' is given as an argument. */
|
||||
|
||||
void
|
||||
mode_string (unsigned short mode, char *str)
|
||||
{
|
||||
str[0] = ftypelet ((long) mode);
|
||||
rwx ((mode & 0700) << 0, &str[1]);
|
||||
rwx ((mode & 0070) << 3, &str[4]);
|
||||
rwx ((mode & 0007) << 6, &str[7]);
|
||||
setst (mode, str);
|
||||
}
|
||||
|
||||
/* filemodestring - fill in string STR with an ls-style ASCII
|
||||
representation of the st_mode field of file stats block STATP.
|
||||
10 characters are stored in STR; no terminating null is added.
|
||||
The characters stored in STR are:
|
||||
|
||||
0 File type. 'd' for directory, 'c' for character
|
||||
special, 'b' for block special, 'm' for multiplex,
|
||||
'l' for symbolic link, 's' for socket, 'p' for fifo,
|
||||
'-' for regular, '?' for any other file type
|
||||
|
||||
1 'r' if the owner may read, '-' otherwise.
|
||||
|
||||
2 'w' if the owner may write, '-' otherwise.
|
||||
|
||||
3 'x' if the owner may execute, 's' if the file is
|
||||
set-user-id, '-' otherwise.
|
||||
'S' if the file is set-user-id, but the execute
|
||||
bit isn't set.
|
||||
|
||||
4 'r' if group members may read, '-' otherwise.
|
||||
|
||||
5 'w' if group members may write, '-' otherwise.
|
||||
|
||||
6 'x' if group members may execute, 's' if the file is
|
||||
set-group-id, '-' otherwise.
|
||||
'S' if it is set-group-id but not executable.
|
||||
|
||||
7 'r' if any user may read, '-' otherwise.
|
||||
|
||||
8 'w' if any user may write, '-' otherwise.
|
||||
|
||||
9 'x' if any user may execute, 't' if the file is "sticky"
|
||||
(will be retained in swap space after execution), '-'
|
||||
otherwise.
|
||||
'T' if the file is sticky but not executable. */
|
||||
|
||||
void
|
||||
filemodestring (struct stat *statp, char *str)
|
||||
{
|
||||
mode_string (statp->st_mode, str);
|
||||
}
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/* filetypes.h - deal with POSIX annoyances
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Include sys/types.h and sys/stat.h before this file. */
|
||||
|
||||
#ifndef S_ISREG /* Doesn't have POSIX.1 stat stuff. */
|
||||
#define mode_t unsigned short
|
||||
#endif
|
||||
|
||||
/* Define the POSIX macros for systems that lack them. */
|
||||
#if !defined(S_ISBLK) && defined(S_IFBLK)
|
||||
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
|
||||
#endif
|
||||
#if !defined(S_ISCHR) && defined(S_IFCHR)
|
||||
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
|
||||
#endif
|
||||
#if !defined(S_ISDIR) && defined(S_IFDIR)
|
||||
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
#if !defined(S_ISREG) && defined(S_IFREG)
|
||||
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
#if !defined(S_ISFIFO) && defined(S_IFIFO)
|
||||
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
|
||||
#endif
|
||||
#if !defined(S_ISLNK) && defined(S_IFLNK)
|
||||
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
||||
#endif
|
||||
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
|
||||
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
|
||||
#endif
|
||||
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX network special */
|
||||
#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
|
||||
#endif
|
||||
|
||||
/* Define the file type bits used in cpio archives.
|
||||
They have the same values as the S_IF bits in traditional Unix. */
|
||||
|
||||
#define CP_IFMT 0170000 /* Mask for all file type bits. */
|
||||
|
||||
#if defined(S_ISBLK)
|
||||
#define CP_IFBLK 0060000
|
||||
#endif
|
||||
#if defined(S_ISCHR)
|
||||
#define CP_IFCHR 0020000
|
||||
#endif
|
||||
#if defined(S_ISDIR)
|
||||
#define CP_IFDIR 0040000
|
||||
#endif
|
||||
#if defined(S_ISREG)
|
||||
#define CP_IFREG 0100000
|
||||
#endif
|
||||
#if defined(S_ISFIFO)
|
||||
#define CP_IFIFO 0010000
|
||||
#endif
|
||||
#if defined(S_ISLNK)
|
||||
#define CP_IFLNK 0120000
|
||||
#endif
|
||||
#if defined(S_ISSOCK)
|
||||
#define CP_IFSOCK 0140000
|
||||
#endif
|
||||
#if defined(S_ISNWK)
|
||||
#define CP_IFNWK 0110000
|
||||
#endif
|
||||
|
||||
#ifndef S_ISLNK
|
||||
#define lstat stat
|
||||
#endif
|
||||
int lstat ();
|
||||
int stat ();
|
||||
@@ -1,206 +0,0 @@
|
||||
/* idcache.c -- map user and group IDs, cached for speed
|
||||
Copyright (C) 1985, 1988, 1989, 1990, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
|
||||
#include <string.h>
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifndef _POSIX_VERSION
|
||||
struct passwd *getpwuid ();
|
||||
struct passwd *getpwnam ();
|
||||
struct group *getgrgid ();
|
||||
struct group *getgrnam ();
|
||||
#endif
|
||||
|
||||
char *xmalloc ();
|
||||
char *xstrdup ();
|
||||
|
||||
struct userid
|
||||
{
|
||||
union
|
||||
{
|
||||
uid_t u;
|
||||
gid_t g;
|
||||
} id;
|
||||
char *name;
|
||||
struct userid *next;
|
||||
};
|
||||
|
||||
static struct userid *user_alist;
|
||||
|
||||
/* The members of this list have names not in the local passwd file. */
|
||||
static struct userid *nouser_alist;
|
||||
|
||||
/* Translate UID to a login name or a stringified number,
|
||||
with cache. */
|
||||
|
||||
char *
|
||||
getuser (uid_t uid)
|
||||
{
|
||||
register struct userid *tail;
|
||||
struct passwd *pwent;
|
||||
char usernum_string[20];
|
||||
|
||||
for (tail = user_alist; tail; tail = tail->next)
|
||||
if (tail->id.u == uid)
|
||||
return tail->name;
|
||||
|
||||
pwent = getpwuid (uid);
|
||||
tail = (struct userid *) xmalloc (sizeof (struct userid));
|
||||
tail->id.u = uid;
|
||||
if (pwent == 0)
|
||||
{
|
||||
sprintf (usernum_string, "%u", (unsigned) uid);
|
||||
tail->name = xstrdup (usernum_string);
|
||||
}
|
||||
else
|
||||
tail->name = xstrdup (pwent->pw_name);
|
||||
|
||||
/* Add to the head of the list, so most recently used is first. */
|
||||
tail->next = user_alist;
|
||||
user_alist = tail;
|
||||
return tail->name;
|
||||
}
|
||||
|
||||
/* Translate USER to a UID, with cache.
|
||||
Return NULL if there is no such user.
|
||||
(We also cache which user names have no passwd entry,
|
||||
so we don't keep looking them up.) */
|
||||
|
||||
uid_t *
|
||||
getuidbyname (char *user)
|
||||
{
|
||||
register struct userid *tail;
|
||||
struct passwd *pwent;
|
||||
|
||||
for (tail = user_alist; tail; tail = tail->next)
|
||||
/* Avoid a function call for the most common case. */
|
||||
if (*tail->name == *user && !strcmp (tail->name, user))
|
||||
return &tail->id.u;
|
||||
|
||||
for (tail = nouser_alist; tail; tail = tail->next)
|
||||
/* Avoid a function call for the most common case. */
|
||||
if (*tail->name == *user && !strcmp (tail->name, user))
|
||||
return 0;
|
||||
|
||||
pwent = getpwnam (user);
|
||||
|
||||
tail = (struct userid *) xmalloc (sizeof (struct userid));
|
||||
tail->name = xstrdup (user);
|
||||
|
||||
/* Add to the head of the list, so most recently used is first. */
|
||||
if (pwent)
|
||||
{
|
||||
tail->id.u = pwent->pw_uid;
|
||||
tail->next = user_alist;
|
||||
user_alist = tail;
|
||||
return &tail->id.u;
|
||||
}
|
||||
|
||||
tail->next = nouser_alist;
|
||||
nouser_alist = tail;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use the same struct as for userids. */
|
||||
static struct userid *group_alist;
|
||||
static struct userid *nogroup_alist;
|
||||
|
||||
/* Translate GID to a group name or a stringified number,
|
||||
with cache. */
|
||||
|
||||
char *
|
||||
getgroup (gid_t gid)
|
||||
{
|
||||
register struct userid *tail;
|
||||
struct group *grent;
|
||||
char groupnum_string[20];
|
||||
|
||||
for (tail = group_alist; tail; tail = tail->next)
|
||||
if (tail->id.g == gid)
|
||||
return tail->name;
|
||||
|
||||
grent = getgrgid (gid);
|
||||
tail = (struct userid *) xmalloc (sizeof (struct userid));
|
||||
tail->id.g = gid;
|
||||
if (grent == 0)
|
||||
{
|
||||
sprintf (groupnum_string, "%u", (unsigned int) gid);
|
||||
tail->name = xstrdup (groupnum_string);
|
||||
}
|
||||
else
|
||||
tail->name = xstrdup (grent->gr_name);
|
||||
|
||||
/* Add to the head of the list, so most recently used is first. */
|
||||
tail->next = group_alist;
|
||||
group_alist = tail;
|
||||
return tail->name;
|
||||
}
|
||||
|
||||
/* Translate GROUP to a UID, with cache.
|
||||
Return NULL if there is no such group.
|
||||
(We also cache which group names have no group entry,
|
||||
so we don't keep looking them up.) */
|
||||
|
||||
gid_t *
|
||||
getgidbyname (char *group)
|
||||
{
|
||||
register struct userid *tail;
|
||||
struct group *grent;
|
||||
|
||||
for (tail = group_alist; tail; tail = tail->next)
|
||||
/* Avoid a function call for the most common case. */
|
||||
if (*tail->name == *group && !strcmp (tail->name, group))
|
||||
return &tail->id.g;
|
||||
|
||||
for (tail = nogroup_alist; tail; tail = tail->next)
|
||||
/* Avoid a function call for the most common case. */
|
||||
if (*tail->name == *group && !strcmp (tail->name, group))
|
||||
return 0;
|
||||
|
||||
grent = getgrnam (group);
|
||||
|
||||
tail = (struct userid *) xmalloc (sizeof (struct userid));
|
||||
tail->name = xstrdup (group);
|
||||
|
||||
/* Add to the head of the list, so most recently used is first. */
|
||||
if (grent)
|
||||
{
|
||||
tail->id.g = grent->gr_gid;
|
||||
tail->next = group_alist;
|
||||
group_alist = tail;
|
||||
return &tail->id.g;
|
||||
}
|
||||
|
||||
tail->next = nogroup_alist;
|
||||
nogroup_alist = tail;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,301 +0,0 @@
|
||||
/* makepath.c -- Ensure that a directory path exists.
|
||||
Copyright (C) 1990 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by David MacKenzie <[email protected]> and
|
||||
Jim Meyering <meyering@cs.utexas.edu>. */
|
||||
|
||||
/* This copy of makepath is almost like the fileutils one, but has
|
||||
changes for HPUX CDF's. Maybe the 2 versions of makepath can
|
||||
come together again in the future. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define alloca __builtin_alloca
|
||||
#else
|
||||
#ifdef HAVE_ALLOCA_H
|
||||
#include <alloca.h>
|
||||
#else
|
||||
#ifdef _AIX
|
||||
#pragma alloca
|
||||
#else
|
||||
char *alloca ();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if !defined(S_ISDIR) && defined(S_IFDIR)
|
||||
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#ifdef STDC_HEADERS
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
|
||||
#include <string.h>
|
||||
#ifndef index
|
||||
#define index strchr
|
||||
#endif
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
/* Ensure that the directory ARGPATH exists.
|
||||
Remove any trailing slashes from ARGPATH before calling this function.
|
||||
|
||||
Make any leading directories that don't already exist, with
|
||||
permissions PARENT_MODE.
|
||||
If the last element of ARGPATH does not exist, create it as
|
||||
a new directory with permissions MODE.
|
||||
If OWNER and GROUP are non-negative, make them the UID and GID of
|
||||
created directories.
|
||||
If VERBOSE_FMT_STRING is nonzero, use it as a printf format
|
||||
string for printing a message after successfully making a directory,
|
||||
with the name of the directory that was just made as an argument.
|
||||
|
||||
Return 0 if ARGPATH exists as a directory with the proper
|
||||
ownership and permissions when done, otherwise 1. */
|
||||
|
||||
int
|
||||
make_path (char *argpath,
|
||||
int mode,
|
||||
int parent_mode,
|
||||
uid_t owner,
|
||||
gid_t group,
|
||||
char *verbose_fmt_string)
|
||||
{
|
||||
char *dirpath; /* A copy we can scribble NULs on. */
|
||||
struct stat stats;
|
||||
int retval = 0;
|
||||
int oldmask = umask (0);
|
||||
dirpath = alloca (strlen (argpath) + 1);
|
||||
strcpy (dirpath, argpath);
|
||||
|
||||
if (stat (dirpath, &stats))
|
||||
{
|
||||
char *slash;
|
||||
int tmp_mode; /* Initial perms for leading dirs. */
|
||||
int re_protect; /* Should leading dirs be unwritable? */
|
||||
struct ptr_list
|
||||
{
|
||||
char *dirname_end;
|
||||
struct ptr_list *next;
|
||||
};
|
||||
struct ptr_list *p, *leading_dirs = NULL;
|
||||
|
||||
/* If leading directories shouldn't be writable or executable,
|
||||
or should have set[ug]id or sticky bits set and we are setting
|
||||
their owners, we need to fix their permissions after making them. */
|
||||
if (((parent_mode & 0300) != 0300)
|
||||
|| (owner != (uid_t) -1 && group != (gid_t) -1
|
||||
&& (parent_mode & 07000) != 0))
|
||||
{
|
||||
tmp_mode = 0700;
|
||||
re_protect = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_mode = parent_mode;
|
||||
re_protect = 0;
|
||||
}
|
||||
|
||||
slash = dirpath;
|
||||
while (*slash == '/')
|
||||
slash++;
|
||||
while ((slash = index (slash, '/')))
|
||||
{
|
||||
#ifdef HPUX_CDF
|
||||
int iscdf;
|
||||
iscdf = 0;
|
||||
#endif
|
||||
*slash = '\0';
|
||||
if (stat (dirpath, &stats))
|
||||
{
|
||||
#ifdef HPUX_CDF
|
||||
/* If this component of the pathname ends in `+' and is
|
||||
followed by 2 `/'s, then this is a CDF. We remove the
|
||||
`+' from the name and create the directory. Later
|
||||
we will "hide" the directory. */
|
||||
if ( (*(slash +1) == '/') && (*(slash -1) == '+') )
|
||||
{
|
||||
iscdf = 1;
|
||||
*(slash -1) = '\0';
|
||||
}
|
||||
#endif
|
||||
if (mkdir (dirpath, tmp_mode))
|
||||
{
|
||||
error (0, errno, _("cannot make directory `%s'"), dirpath);
|
||||
umask (oldmask);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (verbose_fmt_string != NULL)
|
||||
error (0, 0, verbose_fmt_string, dirpath);
|
||||
|
||||
if (owner != (uid_t) -1 && group != (gid_t) -1
|
||||
&& chown (dirpath, owner, group)
|
||||
#ifdef AFS
|
||||
&& errno != EPERM
|
||||
#endif
|
||||
)
|
||||
{
|
||||
error (0, errno, "%s", dirpath);
|
||||
retval = 1;
|
||||
}
|
||||
if (re_protect)
|
||||
{
|
||||
struct ptr_list *new = (struct ptr_list *)
|
||||
alloca (sizeof (struct ptr_list));
|
||||
new->dirname_end = slash;
|
||||
new->next = leading_dirs;
|
||||
leading_dirs = new;
|
||||
}
|
||||
#ifdef HPUX_CDF
|
||||
if (iscdf)
|
||||
{
|
||||
/* If this is a CDF, "hide" the directory by setting
|
||||
its hidden/setuid bit. Also add the `+' back to
|
||||
its name (since once it's "hidden" we must refer
|
||||
to as `name+' instead of `name'). */
|
||||
chmod (dirpath, 04700);
|
||||
*(slash - 1) = '+';
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (!S_ISDIR (stats.st_mode))
|
||||
{
|
||||
error (0, 0, _("`%s' exists but is not a directory"), dirpath);
|
||||
umask (oldmask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
*slash++ = '/';
|
||||
|
||||
/* Avoid unnecessary calls to `stat' when given
|
||||
pathnames containing multiple adjacent slashes. */
|
||||
while (*slash == '/')
|
||||
slash++;
|
||||
}
|
||||
|
||||
/* We're done making leading directories.
|
||||
Make the final component of the path. */
|
||||
|
||||
if (mkdir (dirpath, mode))
|
||||
{
|
||||
/* In some cases, if the final component in dirpath was `.' then we
|
||||
just got an EEXIST error from that last mkdir(). If that's
|
||||
the case, ignore it. */
|
||||
if ( (errno != EEXIST) ||
|
||||
(stat (dirpath, &stats) != 0) ||
|
||||
(!S_ISDIR (stats.st_mode) ) )
|
||||
{
|
||||
error (0, errno, _("cannot make directory `%s'"), dirpath);
|
||||
umask (oldmask);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (verbose_fmt_string != NULL)
|
||||
error (0, 0, verbose_fmt_string, dirpath);
|
||||
|
||||
if (owner != (uid_t) -1 && group != (gid_t) -1)
|
||||
{
|
||||
if (chown (dirpath, owner, group)
|
||||
#ifdef AFS
|
||||
&& errno != EPERM
|
||||
#endif
|
||||
)
|
||||
{
|
||||
error (0, errno, "%s", dirpath);
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
/* chown may have turned off some permission bits we wanted. */
|
||||
if ((mode & 07000) != 0 && chmod (dirpath, mode))
|
||||
{
|
||||
error (0, errno, "%s", dirpath);
|
||||
retval = 1;
|
||||
}
|
||||
|
||||
/* If the mode for leading directories didn't include owner "wx"
|
||||
privileges, we have to reset their protections to the correct
|
||||
value. */
|
||||
for (p = leading_dirs; p != NULL; p = p->next)
|
||||
{
|
||||
*(p->dirname_end) = '\0';
|
||||
#if 0
|
||||
/* cpio always calls make_path with parent mode 0700, so
|
||||
we don't have to do this. If we ever do have to do this,
|
||||
we have to stat the directory first to get the setuid
|
||||
bit so we don't break HP CDF's. */
|
||||
if (chmod (dirpath, parent_mode))
|
||||
{
|
||||
error (0, errno, "%s", dirpath);
|
||||
retval = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We get here if the entire path already exists. */
|
||||
|
||||
if (!S_ISDIR (stats.st_mode))
|
||||
{
|
||||
error (0, 0, _("`%s' exists but is not a directory"), dirpath);
|
||||
umask (oldmask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* chown must precede chmod because on some systems,
|
||||
chown clears the set[ug]id bits for non-superusers,
|
||||
resulting in incorrect permissions.
|
||||
On System V, users can give away files with chown and then not
|
||||
be able to chmod them. So don't give files away. */
|
||||
|
||||
if (owner != (uid_t) -1 && group != (gid_t) -1
|
||||
&& chown (dirpath, owner, group)
|
||||
#ifdef AFS
|
||||
&& errno != EPERM
|
||||
#endif
|
||||
)
|
||||
{
|
||||
error (0, errno, "%s", dirpath);
|
||||
retval = 1;
|
||||
}
|
||||
if (chmod (dirpath, mode))
|
||||
{
|
||||
error (0, errno, "%s", dirpath);
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
|
||||
umask (oldmask);
|
||||
return retval;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
#define SAFE_STAT(path,pbuf) stat(path,pbuf)
|
||||
@@ -1,515 +0,0 @@
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/* tar.c - read in write tar headers for cpio
|
||||
Copyright (C) 1992, 2001, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "filetypes.h"
|
||||
#include "cpiohdr.h"
|
||||
#include "dstring.h"
|
||||
#include "extern.h"
|
||||
#include <rmt.h>
|
||||
#include "tarhdr.h"
|
||||
|
||||
/* Stash the tar linkname in static storage. */
|
||||
|
||||
static char *
|
||||
stash_tar_linkname (char *linkname)
|
||||
{
|
||||
static char hold_tar_linkname[TARLINKNAMESIZE + 1];
|
||||
|
||||
strncpy (hold_tar_linkname, linkname, TARLINKNAMESIZE);
|
||||
hold_tar_linkname[TARLINKNAMESIZE] = '\0';
|
||||
return hold_tar_linkname;
|
||||
}
|
||||
|
||||
/* Try to split a long file name into prefix and suffix parts separated
|
||||
by a slash. Return the length of the prefix (not counting the slash). */
|
||||
|
||||
static size_t
|
||||
split_long_name (const char *name, size_t length)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (length > TARPREFIXSIZE)
|
||||
length = TARPREFIXSIZE+2;
|
||||
for (i = length - 1; i > 0; i--)
|
||||
if (name[i] == '/')
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Stash the tar filename and optional prefix in static storage. */
|
||||
|
||||
static char *
|
||||
stash_tar_filename (char *prefix, char *filename)
|
||||
{
|
||||
static char hold_tar_filename[TARNAMESIZE + TARPREFIXSIZE + 2];
|
||||
if (prefix == NULL || *prefix == '\0')
|
||||
{
|
||||
strncpy (hold_tar_filename, filename, TARNAMESIZE);
|
||||
hold_tar_filename[TARNAMESIZE] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy (hold_tar_filename, prefix, TARPREFIXSIZE);
|
||||
hold_tar_filename[TARPREFIXSIZE] = '\0';
|
||||
strcat (hold_tar_filename, "/");
|
||||
strncat (hold_tar_filename, filename, TARNAMESIZE);
|
||||
hold_tar_filename[TARPREFIXSIZE + TARNAMESIZE] = '\0';
|
||||
}
|
||||
return hold_tar_filename;
|
||||
}
|
||||
|
||||
/* Convert a number into a string of octal digits.
|
||||
Convert long VALUE into a DIGITS-digit field at WHERE,
|
||||
including a trailing space and room for a NUL. DIGITS==3 means
|
||||
1 digit, a space, and room for a NUL.
|
||||
|
||||
We assume the trailing NUL is already there and don't fill it in.
|
||||
This fact is used by start_header and finish_header, so don't change it!
|
||||
|
||||
This is be equivalent to:
|
||||
sprintf (where, "%*lo ", digits - 2, value);
|
||||
except that sprintf fills in the trailing NUL and we don't. */
|
||||
|
||||
static void
|
||||
to_oct (register long value, register int digits, register char *where)
|
||||
{
|
||||
--digits; /* Leave the trailing NUL slot alone. */
|
||||
|
||||
/* Produce the digits -- at least one. */
|
||||
do
|
||||
{
|
||||
where[--digits] = '0' + (char) (value & 7); /* One octal digit. */
|
||||
value >>= 3;
|
||||
}
|
||||
while (digits > 0 && value != 0);
|
||||
|
||||
/* Add leading zeroes, if necessary. */
|
||||
while (digits > 0)
|
||||
where[--digits] = '0';
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Compute and return a checksum for TAR_HDR,
|
||||
counting the checksum bytes as if they were spaces. */
|
||||
|
||||
unsigned long
|
||||
tar_checksum (struct tar_header *tar_hdr)
|
||||
{
|
||||
unsigned long sum = 0;
|
||||
char *p = (char *) tar_hdr;
|
||||
char *q = p + TARRECORDSIZE;
|
||||
int i;
|
||||
|
||||
while (p < tar_hdr->chksum)
|
||||
sum += *p++ & 0xff;
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
sum += ' ';
|
||||
++p;
|
||||
}
|
||||
while (p < q)
|
||||
sum += *p++ & 0xff;
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* Write out header FILE_HDR, including the file name, to file
|
||||
descriptor OUT_DES. */
|
||||
|
||||
void
|
||||
write_out_tar_header (struct new_cpio_header *file_hdr, int out_des)
|
||||
{
|
||||
int name_len;
|
||||
union tar_record tar_rec;
|
||||
struct tar_header *tar_hdr = (struct tar_header *) &tar_rec;
|
||||
|
||||
bzero ((char *) &tar_rec, TARRECORDSIZE);
|
||||
|
||||
/* process_copy_out must ensure that file_hdr->c_name is short enough,
|
||||
or we will lose here. */
|
||||
|
||||
name_len = strlen (file_hdr->c_name);
|
||||
if (name_len <= TARNAMESIZE)
|
||||
{
|
||||
strncpy (tar_hdr->name, file_hdr->c_name, name_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fit as much as we can into `name', the rest into `prefix'. */
|
||||
int prefix_len = split_long_name (file_hdr->c_name, name_len);
|
||||
|
||||
strncpy (tar_hdr->prefix, file_hdr->c_name, prefix_len);
|
||||
strncpy (tar_hdr->name, file_hdr->c_name + prefix_len + 1,
|
||||
name_len - prefix_len - 1);
|
||||
}
|
||||
|
||||
/* Ustar standard (POSIX.1-1988) requires the mode to contain only 3 octal
|
||||
digits */
|
||||
to_oct (file_hdr->c_mode & MODE_ALL, 8, tar_hdr->mode);
|
||||
to_oct (file_hdr->c_uid, 8, tar_hdr->uid);
|
||||
to_oct (file_hdr->c_gid, 8, tar_hdr->gid);
|
||||
to_oct (file_hdr->c_filesize, 12, tar_hdr->size);
|
||||
to_oct (file_hdr->c_mtime, 12, tar_hdr->mtime);
|
||||
|
||||
switch (file_hdr->c_mode & CP_IFMT)
|
||||
{
|
||||
case CP_IFREG:
|
||||
if (file_hdr->c_tar_linkname)
|
||||
{
|
||||
/* process_copy_out makes sure that c_tar_linkname is shorter
|
||||
than TARLINKNAMESIZE. */
|
||||
strncpy (tar_hdr->linkname, file_hdr->c_tar_linkname,
|
||||
TARLINKNAMESIZE);
|
||||
tar_hdr->typeflag = LNKTYPE;
|
||||
to_oct (0, 12, tar_hdr->size);
|
||||
}
|
||||
else
|
||||
tar_hdr->typeflag = REGTYPE;
|
||||
break;
|
||||
case CP_IFDIR:
|
||||
tar_hdr->typeflag = DIRTYPE;
|
||||
break;
|
||||
case CP_IFCHR:
|
||||
tar_hdr->typeflag = CHRTYPE;
|
||||
break;
|
||||
case CP_IFBLK:
|
||||
tar_hdr->typeflag = BLKTYPE;
|
||||
break;
|
||||
#ifdef CP_IFIFO
|
||||
case CP_IFIFO:
|
||||
tar_hdr->typeflag = FIFOTYPE;
|
||||
break;
|
||||
#endif /* CP_IFIFO */
|
||||
#ifdef CP_IFLNK
|
||||
case CP_IFLNK:
|
||||
tar_hdr->typeflag = SYMTYPE;
|
||||
/* process_copy_out makes sure that c_tar_linkname is shorter
|
||||
than TARLINKNAMESIZE. */
|
||||
strncpy (tar_hdr->linkname, file_hdr->c_tar_linkname,
|
||||
TARLINKNAMESIZE);
|
||||
to_oct (0, 12, tar_hdr->size);
|
||||
break;
|
||||
#endif /* CP_IFLNK */
|
||||
}
|
||||
|
||||
if (archive_format == arf_ustar)
|
||||
{
|
||||
char *name;
|
||||
|
||||
strncpy (tar_hdr->magic, TMAGIC, TMAGLEN);
|
||||
strncpy (tar_hdr->magic + TMAGLEN, TVERSION, TVERSLEN);
|
||||
|
||||
name = getuser (file_hdr->c_uid);
|
||||
if (name)
|
||||
strcpy (tar_hdr->uname, name);
|
||||
name = getgroup (file_hdr->c_gid);
|
||||
if (name)
|
||||
strcpy (tar_hdr->gname, name);
|
||||
|
||||
to_oct (file_hdr->c_rdev_maj, 8, tar_hdr->devmajor);
|
||||
to_oct (file_hdr->c_rdev_min, 8, tar_hdr->devminor);
|
||||
}
|
||||
|
||||
to_oct (tar_checksum (tar_hdr), 8, tar_hdr->chksum);
|
||||
|
||||
tape_buffered_write ((char *) &tar_rec, out_des, TARRECORDSIZE);
|
||||
}
|
||||
|
||||
/* Return nonzero iff all the bytes in BLOCK are NUL.
|
||||
SIZE is the number of bytes to check in BLOCK; it must be a
|
||||
multiple of sizeof (long). */
|
||||
|
||||
int
|
||||
null_block (long *block, int size)
|
||||
{
|
||||
register long *p = block;
|
||||
register int i = size / sizeof (long);
|
||||
|
||||
while (i--)
|
||||
if (*p++)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read a tar header, including the file name, from file descriptor IN_DES
|
||||
into FILE_HDR. */
|
||||
|
||||
void
|
||||
read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
|
||||
{
|
||||
long bytes_skipped = 0;
|
||||
int warned = false;
|
||||
union tar_record tar_rec;
|
||||
struct tar_header *tar_hdr = (struct tar_header *) &tar_rec;
|
||||
uid_t *uidp;
|
||||
gid_t *gidp;
|
||||
|
||||
tape_buffered_read ((char *) &tar_rec, in_des, TARRECORDSIZE);
|
||||
|
||||
/* Check for a block of 0's. */
|
||||
if (null_block ((long *) &tar_rec, TARRECORDSIZE))
|
||||
{
|
||||
#if 0
|
||||
/* Found one block of 512 0's. If the next block is also all 0's
|
||||
then this is the end of the archive. If not, assume the
|
||||
previous block was all corruption and continue reading
|
||||
the archive. */
|
||||
/* Commented out because GNU tar sometimes creates archives with
|
||||
only one block of 0's at the end. This happened for the
|
||||
cpio 2.0 distribution! */
|
||||
tape_buffered_read ((char *) &tar_rec, in_des, TARRECORDSIZE);
|
||||
if (null_block ((long *) &tar_rec, TARRECORDSIZE))
|
||||
#endif
|
||||
{
|
||||
file_hdr->c_name = "TRAILER!!!";
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
bytes_skipped = TARRECORDSIZE;
|
||||
#endif
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
otoa (tar_hdr->chksum, &file_hdr->c_chksum);
|
||||
|
||||
if (file_hdr->c_chksum != tar_checksum (tar_hdr))
|
||||
{
|
||||
/* If the checksum is bad, skip 1 byte and try again. When
|
||||
we try again we do not look for an EOF record (all zeros),
|
||||
because when we start skipping bytes in a corrupted archive
|
||||
the chances are pretty good that we might stumble across
|
||||
2 blocks of 512 zeros (that probably is not really the last
|
||||
record) and it is better to miss the EOF and give the user
|
||||
a "premature EOF" error than to give up too soon on a corrupted
|
||||
archive. */
|
||||
if (!warned)
|
||||
{
|
||||
error (0, 0, _("invalid header: checksum error"));
|
||||
warned = true;
|
||||
}
|
||||
bcopy (((char *) &tar_rec) + 1, (char *) &tar_rec,
|
||||
TARRECORDSIZE - 1);
|
||||
tape_buffered_read (((char *) &tar_rec) + (TARRECORDSIZE - 1), in_des, 1);
|
||||
++bytes_skipped;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (archive_format != arf_ustar)
|
||||
file_hdr->c_name = stash_tar_filename (NULL, tar_hdr->name);
|
||||
else
|
||||
file_hdr->c_name = stash_tar_filename (tar_hdr->prefix, tar_hdr->name);
|
||||
file_hdr->c_nlink = 1;
|
||||
otoa (tar_hdr->mode, &file_hdr->c_mode);
|
||||
file_hdr->c_mode = file_hdr->c_mode & 07777;
|
||||
/* Debian hack: This version of cpio uses the -n flag also to extract
|
||||
tar archives using the numeric UID/GID instead of the user/group
|
||||
names in /etc/passwd and /etc/groups. (98/10/15) -BEM */
|
||||
if (archive_format == arf_ustar && !numeric_uid
|
||||
&& (uidp = getuidbyname (tar_hdr->uname)))
|
||||
file_hdr->c_uid = *uidp;
|
||||
else
|
||||
otoa (tar_hdr->uid, &file_hdr->c_uid);
|
||||
|
||||
if (archive_format == arf_ustar && !numeric_uid
|
||||
&& (gidp = getgidbyname (tar_hdr->gname)))
|
||||
file_hdr->c_gid = *gidp;
|
||||
else
|
||||
otoa (tar_hdr->gid, &file_hdr->c_gid);
|
||||
otoa (tar_hdr->size, &file_hdr->c_filesize);
|
||||
otoa (tar_hdr->mtime, &file_hdr->c_mtime);
|
||||
otoa (tar_hdr->devmajor, (unsigned long *) &file_hdr->c_rdev_maj);
|
||||
otoa (tar_hdr->devminor, (unsigned long *) &file_hdr->c_rdev_min);
|
||||
file_hdr->c_tar_linkname = NULL;
|
||||
|
||||
switch (tar_hdr->typeflag)
|
||||
{
|
||||
case REGTYPE:
|
||||
case CONTTYPE: /* For now, punt. */
|
||||
default:
|
||||
file_hdr->c_mode |= CP_IFREG;
|
||||
break;
|
||||
case DIRTYPE:
|
||||
file_hdr->c_mode |= CP_IFDIR;
|
||||
break;
|
||||
case CHRTYPE:
|
||||
file_hdr->c_mode |= CP_IFCHR;
|
||||
/* If a POSIX tar header has a valid linkname it's always supposed
|
||||
to set typeflag to be LNKTYPE. System V.4 tar seems to
|
||||
be broken, and for device files with multiple links it
|
||||
puts the name of the link into linkname, but leaves typeflag
|
||||
as CHRTYPE, BLKTYPE, FIFOTYPE, etc. */
|
||||
file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
|
||||
|
||||
/* Does POSIX say that the filesize must be 0 for devices? We
|
||||
assume so, but HPUX's POSIX tar sets it to be 1 which causes
|
||||
us problems (when reading an archive we assume we can always
|
||||
skip to the next file by skipping filesize bytes). For
|
||||
now at least, it's easier to clear filesize for devices,
|
||||
rather than check everywhere we skip in copyin.c. */
|
||||
file_hdr->c_filesize = 0;
|
||||
break;
|
||||
case BLKTYPE:
|
||||
file_hdr->c_mode |= CP_IFBLK;
|
||||
file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
|
||||
file_hdr->c_filesize = 0;
|
||||
break;
|
||||
#ifdef CP_IFIFO
|
||||
case FIFOTYPE:
|
||||
file_hdr->c_mode |= CP_IFIFO;
|
||||
file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
|
||||
file_hdr->c_filesize = 0;
|
||||
break;
|
||||
#endif
|
||||
case SYMTYPE:
|
||||
#ifdef CP_IFLNK
|
||||
file_hdr->c_mode |= CP_IFLNK;
|
||||
file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
|
||||
file_hdr->c_filesize = 0;
|
||||
break;
|
||||
/* Else fall through. */
|
||||
#endif
|
||||
case LNKTYPE:
|
||||
file_hdr->c_mode |= CP_IFREG;
|
||||
file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
|
||||
file_hdr->c_filesize = 0;
|
||||
break;
|
||||
|
||||
case AREGTYPE:
|
||||
/* Old tar format; if the last char in filename is '/' then it is
|
||||
a directory, otherwise it's a regular file. */
|
||||
if (file_hdr->c_name[strlen (file_hdr->c_name) - 1] == '/')
|
||||
file_hdr->c_mode |= CP_IFDIR;
|
||||
else
|
||||
file_hdr->c_mode |= CP_IFREG;
|
||||
break;
|
||||
case 'x': case 'g':
|
||||
/* Ignore pax 'x' and 'g' extension entries. */
|
||||
/* Skip body of this entry. */
|
||||
while (file_hdr->c_filesize > 0) {
|
||||
tape_buffered_read(((char *) &tar_rec), in_des, TARRECORDSIZE);
|
||||
if (file_hdr->c_filesize > TARRECORDSIZE)
|
||||
file_hdr->c_filesize -= TARRECORDSIZE;
|
||||
else
|
||||
file_hdr->c_filesize = 0;
|
||||
}
|
||||
/* Read next header and return that instead. */
|
||||
read_in_tar_header(file_hdr, in_des);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (bytes_skipped > 0)
|
||||
warn_junk_bytes (bytes_skipped);
|
||||
}
|
||||
|
||||
/* Convert the string of octal digits S into a number and store
|
||||
it in *N. Return nonzero if the whole string was converted,
|
||||
zero if there was something after the number.
|
||||
Skip leading and trailing spaces. */
|
||||
|
||||
int
|
||||
otoa (char *s, unsigned long *n)
|
||||
{
|
||||
unsigned long val = 0;
|
||||
|
||||
while (*s == ' ')
|
||||
++s;
|
||||
while (*s >= '0' && *s <= '7')
|
||||
val = 8 * val + *s++ - '0';
|
||||
while (*s == ' ')
|
||||
++s;
|
||||
*n = val;
|
||||
return *s == '\0';
|
||||
}
|
||||
|
||||
/* Return
|
||||
2 if BUF is a valid POSIX tar header (the checksum is correct
|
||||
and it has the "ustar" magic string),
|
||||
1 if BUF is a valid old tar header (the checksum is correct),
|
||||
0 otherwise. */
|
||||
|
||||
int
|
||||
is_tar_header (char *buf)
|
||||
{
|
||||
struct tar_header *tar_hdr = (struct tar_header *) buf;
|
||||
unsigned long chksum;
|
||||
|
||||
otoa (tar_hdr->chksum, &chksum);
|
||||
|
||||
if (chksum != tar_checksum (tar_hdr))
|
||||
return 0;
|
||||
|
||||
/* GNU tar 1.10 and previous set the magic field to be "ustar " instead
|
||||
of "ustar\0". Only look at the first 5 characters of the magic
|
||||
field so we can recognize old GNU tar ustar archives. */
|
||||
if (!strncmp (tar_hdr->magic, TMAGIC, TMAGLEN - 1))
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return true if the filename is too long to fit in a tar header.
|
||||
For old tar headers, if the filename's length is less than or equal
|
||||
to 100 then it will fit, otherwise it will not. For POSIX tar headers,
|
||||
if the filename's length is less than or equal to 100 then it
|
||||
will definitely fit, and if it is greater than 256 then it
|
||||
will definitely not fit. If the length is between 100 and 256,
|
||||
then the filename will fit only if it is possible to break it
|
||||
into a 155 character "prefix" and 100 character "name". There
|
||||
must be a slash between the "prefix" and the "name", although
|
||||
the slash is not stored or counted in either the "prefix" or
|
||||
the "name", and there must be at least one character in both
|
||||
the "prefix" and the "name". If it is not possible to break down
|
||||
the filename like this then it will not fit. */
|
||||
|
||||
int
|
||||
is_tar_filename_too_long (char *name)
|
||||
{
|
||||
int whole_name_len;
|
||||
int prefix_name_len;
|
||||
char *p;
|
||||
|
||||
whole_name_len = strlen (name);
|
||||
if (whole_name_len <= TARNAMESIZE)
|
||||
return false;
|
||||
|
||||
if (archive_format != arf_ustar)
|
||||
return true;
|
||||
|
||||
if (whole_name_len > TARNAMESIZE + TARPREFIXSIZE + 1)
|
||||
return true;
|
||||
|
||||
/* See whether we can split up the name into acceptably-sized
|
||||
`prefix' and `name' (`p') pieces. */
|
||||
prefix_name_len = split_long_name (name, whole_name_len);
|
||||
|
||||
/* Interestingly, a name consisting of a slash followed by
|
||||
TARNAMESIZE characters can't be stored, because the prefix
|
||||
would be empty, and thus ignored. */
|
||||
if (prefix_name_len == 0
|
||||
|| whole_name_len - prefix_name_len - 1 > TARNAMESIZE)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
/* Extended tar format from POSIX.1.
|
||||
Copyright (C) 1992 Free Software Foundation, Inc.
|
||||
Written by David J. MacKenzie.
|
||||
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; see the file COPYING.LIB. If
|
||||
not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _TAR_H
|
||||
|
||||
#define _TAR_H 1
|
||||
|
||||
|
||||
/* A tar archive consists of 512-byte blocks.
|
||||
Each file in the archive has a header block followed by 0+ data blocks.
|
||||
Two blocks of NUL bytes indicate the end of the archive. */
|
||||
|
||||
/* The fields of header blocks:
|
||||
All strings are stored as ISO 646 (approximately ASCII) strings.
|
||||
|
||||
Fields are numeric unless otherwise noted below; numbers are ISO 646
|
||||
representations of octal numbers, with leading zeros as needed.
|
||||
|
||||
linkname is only valid when typeflag==LNKTYPE. It doesn't use prefix;
|
||||
files that are links to pathnames >100 chars long can not be stored
|
||||
in a tar archive.
|
||||
|
||||
If typeflag=={LNKTYPE,SYMTYPE,DIRTYPE} then size must be 0.
|
||||
|
||||
devmajor and devminor are only valid for typeflag=={BLKTYPE,CHRTYPE}.
|
||||
|
||||
chksum contains the sum of all 512 bytes in the header block,
|
||||
treating each byte as an 8-bit unsigned value and treating the
|
||||
8 bytes of chksum as blank characters.
|
||||
|
||||
uname and gname are used in preference to uid and gid, if those
|
||||
names exist locally.
|
||||
|
||||
Field Name Byte Offset Length in Bytes Field Type
|
||||
name 0 100 NUL-terminated if NUL fits
|
||||
mode 100 8
|
||||
uid 108 8
|
||||
gid 116 8
|
||||
size 124 12
|
||||
mtime 136 12
|
||||
chksum 148 8
|
||||
typeflag 156 1 see below
|
||||
linkname 157 100 NUL-terminated if NUL fits
|
||||
magic 257 6 must be TMAGIC (NUL term.)
|
||||
version 263 2 must be TVERSION
|
||||
uname 265 32 NUL-terminated
|
||||
gname 297 32 NUL-terminated
|
||||
devmajor 329 8
|
||||
devminor 337 8
|
||||
prefix 345 155 NUL-terminated if NUL fits
|
||||
|
||||
If the first character of prefix is '\0', the file name is name;
|
||||
otherwise, it is prefix/name. Files whose pathnames don't fit in that
|
||||
length can not be stored in a tar archive. */
|
||||
|
||||
/* The bits in mode: */
|
||||
#define TSUID 04000
|
||||
#define TSGID 02000
|
||||
#define TSVTX 01000
|
||||
#define TUREAD 00400
|
||||
#define TUWRITE 00200
|
||||
#define TUEXEC 00100
|
||||
#define TGREAD 00040
|
||||
#define TGWRITE 00020
|
||||
#define TGEXEC 00010
|
||||
#define TOREAD 00004
|
||||
#define TOWRITE 00002
|
||||
#define TOEXEC 00001
|
||||
|
||||
/* The values for typeflag:
|
||||
Values 'A'-'Z' are reserved for custom implementations.
|
||||
All other values are reserved for future POSIX.1 revisions. */
|
||||
|
||||
#define REGTYPE '0' /* Regular file (preferred code). */
|
||||
#define AREGTYPE '\0' /* Regular file (alternate code). */
|
||||
#define LNKTYPE '1' /* Hard link. */
|
||||
#define SYMTYPE '2' /* Symbolic link (hard if not supported). */
|
||||
#define CHRTYPE '3' /* Character special. */
|
||||
#define BLKTYPE '4' /* Block special. */
|
||||
#define DIRTYPE '5' /* Directory. */
|
||||
#define FIFOTYPE '6' /* Named pipe. */
|
||||
#define CONTTYPE '7' /* Contiguous file */
|
||||
/* (regular file if not supported). */
|
||||
|
||||
/* Contents of magic field and its length. */
|
||||
#define TMAGIC "ustar"
|
||||
#define TMAGLEN 6
|
||||
|
||||
/* Contents of the version field and its length. */
|
||||
#define TVERSION "00"
|
||||
#define TVERSLEN 2
|
||||
|
||||
|
||||
#endif /* tar.h */
|
||||
@@ -1,62 +0,0 @@
|
||||
/* Extended tar header from POSIX.1.
|
||||
Copyright (C) 1992 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _TARHDR_H
|
||||
|
||||
#define _TARHDR_H 1
|
||||
|
||||
#include <tar.h>
|
||||
|
||||
/* Size of `name' field. */
|
||||
#define TARNAMESIZE 100
|
||||
|
||||
/* Size of `linkname' field. */
|
||||
#define TARLINKNAMESIZE 100
|
||||
|
||||
/* Size of `prefix' field. */
|
||||
#define TARPREFIXSIZE 155
|
||||
|
||||
/* Size of entire tar header. */
|
||||
#define TARRECORDSIZE 512
|
||||
|
||||
struct tar_header
|
||||
{
|
||||
char name[TARNAMESIZE];
|
||||
char mode[8];
|
||||
char uid[8];
|
||||
char gid[8];
|
||||
char size[12];
|
||||
char mtime[12];
|
||||
char chksum[8];
|
||||
char typeflag;
|
||||
char linkname[TARLINKNAMESIZE];
|
||||
char magic[6];
|
||||
char version[2];
|
||||
char uname[32];
|
||||
char gname[32];
|
||||
char devmajor[8];
|
||||
char devminor[8];
|
||||
char prefix[TARPREFIXSIZE];
|
||||
};
|
||||
|
||||
union tar_record
|
||||
{
|
||||
struct tar_header header;
|
||||
char buffer[TARRECORDSIZE];
|
||||
};
|
||||
|
||||
#endif /* tarhdr.h */
|
||||
@@ -1,259 +0,0 @@
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/* userspec.c -- Parse a user and group string.
|
||||
Copyright (C) 1989, 1990, 1991, 1992, 2001, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by David MacKenzie <[email protected]>. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define alloca __builtin_alloca
|
||||
#else
|
||||
#ifdef HAVE_ALLOCA_H
|
||||
#include <alloca.h>
|
||||
#else
|
||||
#ifdef _AIX
|
||||
#pragma alloca
|
||||
#else
|
||||
char *alloca ();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#if !HAVE_DECL_GETPWNAM
|
||||
extern struct passwd *getpwnam (const char *name);
|
||||
#endif
|
||||
#if !HAVE_DECL_GETGRNAM
|
||||
extern struct group *getgrnam (const char *name);
|
||||
#endif
|
||||
#if !HAVE_DECL_GETGRGID
|
||||
extern struct group *getgrgid (gid_t gid);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ENDPWENT
|
||||
# define endpwent()
|
||||
#endif
|
||||
#ifndef HAVE_ENDGRENT
|
||||
# define endgrent()
|
||||
#endif
|
||||
|
||||
/* Perform the equivalent of the statement `dest = strdup (src);',
|
||||
but obtaining storage via alloca instead of from the heap. */
|
||||
|
||||
#define V_STRDUP(dest, src) \
|
||||
do \
|
||||
{ \
|
||||
int _len = strlen ((src)); \
|
||||
(dest) = (char *) alloca (_len + 1); \
|
||||
strcpy (dest, src); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Return nonzero if STR represents an unsigned decimal integer,
|
||||
otherwise return 0. */
|
||||
|
||||
static int
|
||||
cpio_isnumber (const char *str)
|
||||
{
|
||||
for (; *str; str++)
|
||||
if (!isdigit (*str))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Extract from NAME, which has the form "[user][:.][group]",
|
||||
a USERNAME, UID U, GROUPNAME, and GID G.
|
||||
Either user or group, or both, must be present.
|
||||
If the group is omitted but the ":" or "." separator is given,
|
||||
use the given user's login group.
|
||||
|
||||
USERNAME and GROUPNAME will be in newly malloc'd memory.
|
||||
Either one might be NULL instead, indicating that it was not
|
||||
given and the corresponding numeric ID was left unchanged.
|
||||
|
||||
Return NULL if successful, a static error message string if not. */
|
||||
|
||||
const char *
|
||||
parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
|
||||
char **username_arg, char **groupname_arg)
|
||||
{
|
||||
static const char *tired = "virtual memory exhausted";
|
||||
const char *error_msg;
|
||||
char *spec; /* A copy we can write on. */
|
||||
struct passwd *pwd;
|
||||
struct group *grp;
|
||||
char *g, *u, *separator;
|
||||
char *groupname;
|
||||
|
||||
error_msg = NULL;
|
||||
*username_arg = *groupname_arg = NULL;
|
||||
groupname = NULL;
|
||||
|
||||
V_STRDUP (spec, spec_arg);
|
||||
|
||||
/* Find the separator if there is one. */
|
||||
separator = index (spec, ':');
|
||||
if (separator == NULL)
|
||||
separator = index (spec, '.');
|
||||
|
||||
/* Replace separator with a NUL. */
|
||||
if (separator != NULL)
|
||||
*separator = '\0';
|
||||
|
||||
/* Set U and G to non-zero length strings corresponding to user and
|
||||
group specifiers or to NULL. */
|
||||
u = (*spec == '\0' ? NULL : spec);
|
||||
|
||||
g = (separator == NULL || *(separator + 1) == '\0'
|
||||
? NULL
|
||||
: separator + 1);
|
||||
|
||||
if (u == NULL && g == NULL)
|
||||
return "can not omit both user and group";
|
||||
|
||||
if (u != NULL)
|
||||
{
|
||||
pwd = getpwnam (u);
|
||||
if (pwd == NULL)
|
||||
{
|
||||
|
||||
if (!cpio_isnumber (u))
|
||||
error_msg = _("invalid user");
|
||||
else
|
||||
{
|
||||
int use_login_group;
|
||||
use_login_group = (separator != NULL && g == NULL);
|
||||
if (use_login_group)
|
||||
error_msg = _("cannot get the login group of a numeric UID");
|
||||
else
|
||||
*uid = atoi (u);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*uid = pwd->pw_uid;
|
||||
if (g == NULL && separator != NULL)
|
||||
{
|
||||
/* A separator was given, but a group was not specified,
|
||||
so get the login group. */
|
||||
*gid = pwd->pw_gid;
|
||||
grp = getgrgid (pwd->pw_gid);
|
||||
if (grp == NULL)
|
||||
{
|
||||
/* This is enough room to hold the unsigned decimal
|
||||
representation of any 32-bit quantity and the trailing
|
||||
zero byte. */
|
||||
char uint_buf[21];
|
||||
sprintf (uint_buf, "%u", (unsigned) (pwd->pw_gid));
|
||||
V_STRDUP (groupname, uint_buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
V_STRDUP (groupname, grp->gr_name);
|
||||
}
|
||||
endgrent ();
|
||||
}
|
||||
}
|
||||
endpwent ();
|
||||
}
|
||||
|
||||
if (g != NULL && error_msg == NULL)
|
||||
{
|
||||
/* Explicit group. */
|
||||
grp = getgrnam (g);
|
||||
if (grp == NULL)
|
||||
{
|
||||
if (!cpio_isnumber (g))
|
||||
error_msg = _("invalid group");
|
||||
else
|
||||
*gid = atoi (g);
|
||||
}
|
||||
else
|
||||
*gid = grp->gr_gid;
|
||||
endgrent (); /* Save a file descriptor. */
|
||||
|
||||
if (error_msg == NULL)
|
||||
V_STRDUP (groupname, g);
|
||||
}
|
||||
|
||||
if (error_msg == NULL)
|
||||
{
|
||||
if (u != NULL)
|
||||
{
|
||||
*username_arg = strdup (u);
|
||||
if (*username_arg == NULL)
|
||||
error_msg = tired;
|
||||
}
|
||||
|
||||
if (groupname != NULL && error_msg == NULL)
|
||||
{
|
||||
*groupname_arg = strdup (groupname);
|
||||
if (*groupname_arg == NULL)
|
||||
{
|
||||
if (*username_arg != NULL)
|
||||
{
|
||||
free (*username_arg);
|
||||
*username_arg = NULL;
|
||||
}
|
||||
error_msg = tired;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return error_msg;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#define NULL_CHECK(s) ((s) == NULL ? "(null)" : (s))
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
const char *e;
|
||||
char *username, *groupname;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
char *tmp;
|
||||
|
||||
tmp = strdup (argv[i]);
|
||||
e = parse_user_spec (tmp, &uid, &gid, &username, &groupname);
|
||||
free (tmp);
|
||||
printf ("%s: %u %u %s %s %s\n",
|
||||
argv[i],
|
||||
(unsigned int) uid,
|
||||
(unsigned int) gid,
|
||||
NULL_CHECK (username),
|
||||
NULL_CHECK (groupname),
|
||||
NULL_CHECK (e));
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -118,11 +118,18 @@ int main FUNCTION((argc, argv), int argc AND char *argv[])
|
||||
struct opie opie;
|
||||
int rval, n = 499, i, mode = MODE_DEFAULT, force = 0;
|
||||
char seed[OPIE_SEED_MAX+1];
|
||||
char *username;
|
||||
uid_t ruid;
|
||||
struct passwd *pp;
|
||||
|
||||
memset(seed, 0, sizeof(seed));
|
||||
|
||||
if (!(pp = getpwnam(getlogin()))) {
|
||||
ruid = getuid();
|
||||
username = getlogin();
|
||||
pp = getpwnam(username);
|
||||
if (username == NULL || pp == NULL || pp->pw_uid != ruid)
|
||||
pp = getpwuid(ruid);
|
||||
if (pp == NULL) {
|
||||
fprintf(stderr, "Who are you?");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -145,6 +145,7 @@ sm_flush(fp, timeout)
|
||||
return SM_IO_EOF;
|
||||
}
|
||||
SM_IO_WR_TIMEOUT(fp, fd, *timeout);
|
||||
t = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -192,7 +192,7 @@ extern const char SmFileMagic[];
|
||||
else \
|
||||
{ \
|
||||
(time)->tv_sec = (val) / 1000; \
|
||||
(time)->tv_usec = ((val) - ((time)->tv_sec * 1000)) * 10; \
|
||||
(time)->tv_usec = ((val) - ((time)->tv_sec * 1000)) * 1000; \
|
||||
} \
|
||||
if ((val) == SM_TIME_FOREVER) \
|
||||
{ \
|
||||
@@ -276,7 +276,7 @@ extern const char SmFileMagic[];
|
||||
else \
|
||||
{ \
|
||||
sm_io_to.tv_sec = (to) / 1000; \
|
||||
sm_io_to.tv_usec = ((to) - (sm_io_to.tv_sec * 1000)) * 10; \
|
||||
sm_io_to.tv_usec = ((to) - (sm_io_to.tv_sec * 1000)) * 1000; \
|
||||
} \
|
||||
if (FD_SETSIZE > 0 && (fd) >= FD_SETSIZE) \
|
||||
{ \
|
||||
@@ -289,8 +289,11 @@ extern const char SmFileMagic[];
|
||||
FD_SET((fd), &sm_io_x_mask); \
|
||||
if (gettimeofday(&sm_io_to_before, NULL) < 0) \
|
||||
return SM_IO_EOF; \
|
||||
sm_io_to_sel = select((fd) + 1, NULL, &sm_io_to_mask, &sm_io_x_mask, \
|
||||
&sm_io_to); \
|
||||
do \
|
||||
{ \
|
||||
sm_io_to_sel = select((fd) + 1, NULL, &sm_io_to_mask, \
|
||||
&sm_io_x_mask, &sm_io_to); \
|
||||
} while (sm_io_to_sel < 0 && errno == EINTR); \
|
||||
if (sm_io_to_sel < 0) \
|
||||
{ \
|
||||
/* something went wrong, errno set */ \
|
||||
@@ -305,10 +308,9 @@ extern const char SmFileMagic[];
|
||||
/* else loop again */ \
|
||||
if (gettimeofday(&sm_io_to_after, NULL) < 0) \
|
||||
return SM_IO_EOF; \
|
||||
timersub(&sm_io_to_before, &sm_io_to_after, &sm_io_to_diff); \
|
||||
timersub(&sm_io_to, &sm_io_to_diff, &sm_io_to); \
|
||||
(to) -= (sm_io_to.tv_sec * 1000); \
|
||||
(to) -= (sm_io_to.tv_usec / 10); \
|
||||
timersub(&sm_io_to_after, &sm_io_to_before, &sm_io_to_diff); \
|
||||
(to) -= (sm_io_to_diff.tv_sec * 1000); \
|
||||
(to) -= (sm_io_to_diff.tv_usec / 1000); \
|
||||
if ((to) < 0) \
|
||||
(to) = 0; \
|
||||
}
|
||||
|
||||
@@ -76,8 +76,11 @@ static int sm_lflush __P((SM_FILE_T *, int *));
|
||||
FD_SET((fd), &sm_io_x_mask); \
|
||||
if (gettimeofday(&sm_io_to_before, NULL) < 0) \
|
||||
return SM_IO_EOF; \
|
||||
(sel_ret) = select((fd) + 1, &sm_io_to_mask, NULL, \
|
||||
&sm_io_x_mask, (to)); \
|
||||
do \
|
||||
{ \
|
||||
(sel_ret) = select((fd) + 1, &sm_io_to_mask, NULL, \
|
||||
&sm_io_x_mask, (to)); \
|
||||
} while ((sel_ret) < 0 && errno == EINTR); \
|
||||
if ((sel_ret) < 0) \
|
||||
{ \
|
||||
/* something went wrong, errno set */ \
|
||||
@@ -94,7 +97,7 @@ static int sm_lflush __P((SM_FILE_T *, int *));
|
||||
/* calulate wall-clock time used */ \
|
||||
if (gettimeofday(&sm_io_to_after, NULL) < 0) \
|
||||
return SM_IO_EOF; \
|
||||
timersub(&sm_io_to_before, &sm_io_to_after, &sm_io_to_diff); \
|
||||
timersub(&sm_io_to_after, &sm_io_to_before, &sm_io_to_diff); \
|
||||
timersub((to), &sm_io_to_diff, (to)); \
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
SM_RCSID("@(#)$Id: collect.c,v 8.261 2005/02/16 23:38:51 ca Exp $")
|
||||
|
||||
static void collecttimeout __P((int));
|
||||
static void eatfrom __P((char *volatile, ENVELOPE *));
|
||||
static void collect_doheader __P((ENVELOPE *));
|
||||
static SM_FILE_T *collect_dfopen __P((ENVELOPE *));
|
||||
@@ -263,10 +262,6 @@ collect_dfopen(e)
|
||||
** If data file cannot be created, the process is terminated.
|
||||
*/
|
||||
|
||||
static jmp_buf CtxCollectTimeout;
|
||||
static bool volatile CollectProgress;
|
||||
static SM_EVENT *volatile CollectTimeout = NULL;
|
||||
|
||||
/* values for input state machine */
|
||||
#define IS_NORM 0 /* middle of line */
|
||||
#define IS_BOL 1 /* beginning of line */
|
||||
@@ -288,27 +283,31 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
|
||||
register ENVELOPE *e;
|
||||
bool rsetsize;
|
||||
{
|
||||
register SM_FILE_T *volatile df;
|
||||
volatile bool ignrdot;
|
||||
volatile int dbto;
|
||||
register char *volatile bp;
|
||||
volatile int c;
|
||||
volatile bool inputerr;
|
||||
register SM_FILE_T *df;
|
||||
bool ignrdot;
|
||||
int dbto;
|
||||
register char *bp;
|
||||
int c;
|
||||
bool inputerr;
|
||||
bool headeronly;
|
||||
char *volatile buf;
|
||||
volatile int buflen;
|
||||
volatile int istate;
|
||||
volatile int mstate;
|
||||
volatile int hdrslen;
|
||||
volatile int numhdrs;
|
||||
volatile int afd;
|
||||
unsigned char *volatile pbp;
|
||||
char *buf;
|
||||
int buflen;
|
||||
int istate;
|
||||
int mstate;
|
||||
int hdrslen;
|
||||
int numhdrs;
|
||||
int afd;
|
||||
unsigned char *pbp;
|
||||
unsigned char peekbuf[8];
|
||||
char bufbuf[MAXLINE];
|
||||
|
||||
df = NULL;
|
||||
ignrdot = smtpmode ? false : IgnrDot;
|
||||
dbto = smtpmode ? (int) TimeOuts.to_datablock : 0;
|
||||
|
||||
/* timeout for I/O functions is in milliseconds */
|
||||
dbto = smtpmode ? ((int) TimeOuts.to_datablock * 1000)
|
||||
: SM_TIME_FOREVER;
|
||||
sm_io_setinfo(fp, SM_IO_WHAT_TIMEOUT, &dbto);
|
||||
c = SM_IO_EOF;
|
||||
inputerr = false;
|
||||
headeronly = hdrp != NULL;
|
||||
@@ -320,7 +319,6 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
|
||||
pbp = peekbuf;
|
||||
istate = IS_BOL;
|
||||
mstate = SaveFrom ? MS_HEADER : MS_UFROM;
|
||||
CollectProgress = false;
|
||||
|
||||
/*
|
||||
** Tell ARPANET to go ahead.
|
||||
@@ -341,32 +339,6 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
|
||||
** the larger picture (e.g., header versus body).
|
||||
*/
|
||||
|
||||
if (dbto != 0)
|
||||
{
|
||||
/* handle possible input timeout */
|
||||
if (setjmp(CtxCollectTimeout) != 0)
|
||||
{
|
||||
if (LogLevel > 2)
|
||||
sm_syslog(LOG_NOTICE, e->e_id,
|
||||
"timeout waiting for input from %s during message collect",
|
||||
CURHOSTNAME);
|
||||
errno = 0;
|
||||
if (smtpmode)
|
||||
{
|
||||
/*
|
||||
** Override e_message in usrerr() as this
|
||||
** is the reason for failure that should
|
||||
** be logged for undelivered recipients.
|
||||
*/
|
||||
|
||||
e->e_message = NULL;
|
||||
}
|
||||
usrerr("451 4.4.1 timeout waiting for input during message collect");
|
||||
goto readerr;
|
||||
}
|
||||
CollectTimeout = sm_setevent(dbto, collecttimeout, dbto);
|
||||
}
|
||||
|
||||
if (rsetsize)
|
||||
e->e_msgsize = 0;
|
||||
for (;;)
|
||||
@@ -390,9 +362,26 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
|
||||
sm_io_clearerr(fp);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* timeout? */
|
||||
if (c == SM_IO_EOF && errno == EAGAIN
|
||||
&& smtpmode)
|
||||
{
|
||||
/*
|
||||
** Override e_message in
|
||||
** usrerr() as this is the
|
||||
** reason for failure that
|
||||
** should be logged for
|
||||
** undelivered recipients.
|
||||
*/
|
||||
|
||||
e->e_message = NULL;
|
||||
errno = 0;
|
||||
inputerr = true;
|
||||
goto readabort;
|
||||
}
|
||||
break;
|
||||
}
|
||||
CollectProgress = true;
|
||||
if (TrafficLogFile != NULL && !headeronly)
|
||||
{
|
||||
if (istate == IS_BOL)
|
||||
@@ -538,6 +527,18 @@ bufferchar:
|
||||
buflen *= 2;
|
||||
else
|
||||
buflen += MEMCHUNKSIZE;
|
||||
if (buflen <= 0)
|
||||
{
|
||||
sm_syslog(LOG_NOTICE, e->e_id,
|
||||
"header overflow from %s during message collect",
|
||||
CURHOSTNAME);
|
||||
errno = 0;
|
||||
e->e_flags |= EF_CLRQUEUE;
|
||||
e->e_status = "5.6.0";
|
||||
usrerrenh(e->e_status,
|
||||
"552 Headers too large");
|
||||
goto discard;
|
||||
}
|
||||
buf = xalloc(buflen);
|
||||
memmove(buf, obuf, bp - obuf);
|
||||
bp = &buf[bp - obuf];
|
||||
@@ -581,6 +582,7 @@ bufferchar:
|
||||
usrerrenh(e->e_status,
|
||||
"552 Headers too large (%d max)",
|
||||
MaxHeadersLength);
|
||||
discard:
|
||||
mstate = MS_DISCARD;
|
||||
}
|
||||
}
|
||||
@@ -620,6 +622,24 @@ nextstate:
|
||||
sm_io_clearerr(fp);
|
||||
errno = 0;
|
||||
c = sm_io_getc(fp, SM_TIME_DEFAULT);
|
||||
|
||||
/* timeout? */
|
||||
if (c == SM_IO_EOF && errno == EAGAIN
|
||||
&& smtpmode)
|
||||
{
|
||||
/*
|
||||
** Override e_message in
|
||||
** usrerr() as this is the
|
||||
** reason for failure that
|
||||
** should be logged for
|
||||
** undelivered recipients.
|
||||
*/
|
||||
|
||||
e->e_message = NULL;
|
||||
errno = 0;
|
||||
inputerr = true;
|
||||
goto readabort;
|
||||
}
|
||||
} while (c == SM_IO_EOF && errno == EINTR);
|
||||
if (c != SM_IO_EOF)
|
||||
(void) sm_io_ungetc(fp, SM_TIME_DEFAULT, c);
|
||||
@@ -629,8 +649,12 @@ nextstate:
|
||||
continue;
|
||||
}
|
||||
|
||||
/* trim off trailing CRLF or NL */
|
||||
SM_ASSERT(bp > buf);
|
||||
|
||||
/* guaranteed by isheader(buf) */
|
||||
SM_ASSERT(*(bp - 1) != '\n' || bp > buf + 1);
|
||||
|
||||
/* trim off trailing CRLF or NL */
|
||||
if (*--bp != '\n' || *--bp != '\r')
|
||||
bp++;
|
||||
*bp = '\0';
|
||||
@@ -696,10 +720,6 @@ readerr:
|
||||
inputerr = true;
|
||||
}
|
||||
|
||||
/* reset global timer */
|
||||
if (CollectTimeout != NULL)
|
||||
sm_clrevent(CollectTimeout);
|
||||
|
||||
if (headeronly)
|
||||
return;
|
||||
|
||||
@@ -786,6 +806,7 @@ readerr:
|
||||
}
|
||||
|
||||
/* An EOF when running SMTP is an error */
|
||||
readabort:
|
||||
if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
|
||||
{
|
||||
char *host;
|
||||
@@ -808,13 +829,14 @@ readerr:
|
||||
problem, host,
|
||||
shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
|
||||
if (sm_io_eof(fp))
|
||||
usrerr("451 4.4.1 collect: %s on connection from %s, from=%s",
|
||||
usrerr("421 4.4.1 collect: %s on connection from %s, from=%s",
|
||||
problem, host,
|
||||
shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
|
||||
else
|
||||
syserr("451 4.4.1 collect: %s on connection from %s, from=%s",
|
||||
syserr("421 4.4.1 collect: %s on connection from %s, from=%s",
|
||||
problem, host,
|
||||
shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
|
||||
flush_errors(true);
|
||||
|
||||
/* don't return an error indication */
|
||||
e->e_to = NULL;
|
||||
@@ -907,39 +929,6 @@ readerr:
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
collecttimeout(timeout)
|
||||
int timeout;
|
||||
{
|
||||
int save_errno = errno;
|
||||
|
||||
/*
|
||||
** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
|
||||
** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
|
||||
** DOING.
|
||||
*/
|
||||
|
||||
if (CollectProgress)
|
||||
{
|
||||
/* reset the timeout */
|
||||
CollectTimeout = sm_sigsafe_setevent(timeout, collecttimeout,
|
||||
timeout);
|
||||
CollectProgress = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* event is done */
|
||||
CollectTimeout = NULL;
|
||||
}
|
||||
|
||||
/* if no progress was made or problem resetting event, die now */
|
||||
if (CollectTimeout == NULL)
|
||||
{
|
||||
errno = ETIMEDOUT;
|
||||
longjmp(CtxCollectTimeout, 1);
|
||||
}
|
||||
errno = save_errno;
|
||||
}
|
||||
/*
|
||||
** DFERROR -- signal error on writing the data file.
|
||||
**
|
||||
|
||||
@@ -5310,8 +5310,8 @@ sm_syslog(level, id, fmt, va_alist)
|
||||
va_dcl
|
||||
#endif /* __STDC__ */
|
||||
{
|
||||
static char *buf = NULL;
|
||||
static size_t bufsize;
|
||||
char *buf;
|
||||
size_t bufsize;
|
||||
char *begin, *end;
|
||||
int save_errno;
|
||||
int seq = 1;
|
||||
@@ -5335,11 +5335,8 @@ sm_syslog(level, id, fmt, va_alist)
|
||||
else
|
||||
idlen = strlen(id) + SyslogPrefixLen;
|
||||
|
||||
if (buf == NULL)
|
||||
{
|
||||
buf = buf0;
|
||||
bufsize = sizeof buf0;
|
||||
}
|
||||
buf = buf0;
|
||||
bufsize = sizeof buf0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@@ -5381,8 +5378,8 @@ sm_syslog(level, id, fmt, va_alist)
|
||||
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
|
||||
"%s: %s\n", id, newstring);
|
||||
#endif /* LOG */
|
||||
if (buf == buf0)
|
||||
buf = NULL;
|
||||
if (buf != buf0)
|
||||
sm_free(buf);
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
@@ -5446,8 +5443,8 @@ sm_syslog(level, id, fmt, va_alist)
|
||||
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
|
||||
"%s[%d]: %s\n", id, seq, begin);
|
||||
#endif /* LOG */
|
||||
if (buf == buf0)
|
||||
buf = NULL;
|
||||
if (buf != buf0)
|
||||
sm_free(buf);
|
||||
errno = save_errno;
|
||||
}
|
||||
/*
|
||||
|
||||
+88
-156
@@ -3257,16 +3257,33 @@ do_transfer:
|
||||
}
|
||||
else if (!clever)
|
||||
{
|
||||
bool ok;
|
||||
|
||||
/*
|
||||
** Format and send message.
|
||||
*/
|
||||
|
||||
putfromline(mci, e);
|
||||
(*e->e_puthdr)(mci, e->e_header, e, M87F_OUTER);
|
||||
(*e->e_putbody)(mci, e, NULL);
|
||||
rcode = EX_OK;
|
||||
errno = 0;
|
||||
ok = putfromline(mci, e);
|
||||
if (ok)
|
||||
ok = (*e->e_puthdr)(mci, e->e_header, e, M87F_OUTER);
|
||||
if (ok)
|
||||
ok = (*e->e_putbody)(mci, e, NULL);
|
||||
|
||||
/* get the exit status */
|
||||
/*
|
||||
** Ignore an I/O error that was caused by EPIPE.
|
||||
** Some broken mailers don't read the entire body
|
||||
** but just exit() thus causing an I/O error.
|
||||
*/
|
||||
|
||||
if (!ok && (sm_io_error(mci->mci_out) && errno == EPIPE))
|
||||
ok = true;
|
||||
|
||||
/* (always) get the exit status */
|
||||
rcode = endmailer(mci, e, pv);
|
||||
if (!ok)
|
||||
rcode = EX_TEMPFAIL;
|
||||
if (rcode == EX_TEMPFAIL && SmtpError[0] == '\0')
|
||||
{
|
||||
/*
|
||||
@@ -4430,13 +4447,13 @@ logdelivery(m, mci, dsn, status, ctladdr, xstart, e)
|
||||
** e -- the envelope.
|
||||
**
|
||||
** Returns:
|
||||
** none
|
||||
** true iff line was written successfully
|
||||
**
|
||||
** Side Effects:
|
||||
** outputs some text to fp.
|
||||
*/
|
||||
|
||||
void
|
||||
bool
|
||||
putfromline(mci, e)
|
||||
register MCI *mci;
|
||||
ENVELOPE *e;
|
||||
@@ -4446,7 +4463,7 @@ putfromline(mci, e)
|
||||
char xbuf[MAXLINE];
|
||||
|
||||
if (bitnset(M_NHDR, mci->mci_mailer->m_flags))
|
||||
return;
|
||||
return true;
|
||||
|
||||
mci->mci_flags |= MCIF_INHEADER;
|
||||
|
||||
@@ -4487,8 +4504,9 @@ putfromline(mci, e)
|
||||
}
|
||||
}
|
||||
expand(template, buf, sizeof buf, e);
|
||||
putxline(buf, strlen(buf), mci, PXLF_HEADER);
|
||||
return putxline(buf, strlen(buf), mci, PXLF_HEADER);
|
||||
}
|
||||
|
||||
/*
|
||||
** PUTBODY -- put the body of a message.
|
||||
**
|
||||
@@ -4499,7 +4517,7 @@ putfromline(mci, e)
|
||||
** not be permitted in the resulting message.
|
||||
**
|
||||
** Returns:
|
||||
** none.
|
||||
** true iff message was written successfully
|
||||
**
|
||||
** Side Effects:
|
||||
** The message is written onto fp.
|
||||
@@ -4510,13 +4528,15 @@ putfromline(mci, e)
|
||||
#define OS_CR 1 /* read a carriage return */
|
||||
#define OS_INLINE 2 /* putting rest of line */
|
||||
|
||||
void
|
||||
bool
|
||||
putbody(mci, e, separator)
|
||||
register MCI *mci;
|
||||
register ENVELOPE *e;
|
||||
char *separator;
|
||||
{
|
||||
bool dead = false;
|
||||
bool ioerr = false;
|
||||
int save_errno;
|
||||
char buf[MAXLINE];
|
||||
#if MIME8TO7
|
||||
char *boundaries[MAXMIMENESTING + 1];
|
||||
@@ -4546,10 +4566,12 @@ putbody(mci, e, separator)
|
||||
{
|
||||
if (bitset(MCIF_INHEADER, mci->mci_flags))
|
||||
{
|
||||
putline("", mci);
|
||||
if (!putline("", mci))
|
||||
goto writeerr;
|
||||
mci->mci_flags &= ~MCIF_INHEADER;
|
||||
}
|
||||
putline("<<< No Message Collected >>>", mci);
|
||||
if (!putline("<<< No Message Collected >>>", mci))
|
||||
goto writeerr;
|
||||
goto endofmessage;
|
||||
}
|
||||
|
||||
@@ -4578,26 +4600,31 @@ putbody(mci, e, separator)
|
||||
*/
|
||||
|
||||
/* make sure it looks like a MIME message */
|
||||
if (hvalue("MIME-Version", e->e_header) == NULL)
|
||||
putline("MIME-Version: 1.0", mci);
|
||||
if (hvalue("MIME-Version", e->e_header) == NULL &&
|
||||
!putline("MIME-Version: 1.0", mci))
|
||||
goto writeerr;
|
||||
|
||||
if (hvalue("Content-Type", e->e_header) == NULL)
|
||||
{
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
"Content-Type: text/plain; charset=%s",
|
||||
defcharset(e));
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
|
||||
/* now do the hard work */
|
||||
boundaries[0] = NULL;
|
||||
mci->mci_flags |= MCIF_INHEADER;
|
||||
(void) mime8to7(mci, e->e_header, e, boundaries, M87F_OUTER);
|
||||
if (mime8to7(mci, e->e_header, e, boundaries, M87F_OUTER, 0) ==
|
||||
SM_IO_EOF)
|
||||
goto writeerr;
|
||||
}
|
||||
# if MIME7TO8
|
||||
else if (bitset(MCIF_CVT7TO8, mci->mci_flags))
|
||||
{
|
||||
(void) mime7to8(mci, e->e_header, e);
|
||||
if (!mime7to8(mci, e->e_header, e))
|
||||
goto writeerr;
|
||||
}
|
||||
# endif /* MIME7TO8 */
|
||||
else if (MaxMimeHeaderLength > 0 || MaxMimeFieldLength > 0)
|
||||
@@ -4619,8 +4646,9 @@ putbody(mci, e, separator)
|
||||
if (bitset(EF_DONT_MIME, e->e_flags))
|
||||
SuprErrs = true;
|
||||
|
||||
(void) mime8to7(mci, e->e_header, e, boundaries,
|
||||
M87F_OUTER|M87F_NO8TO7);
|
||||
if (mime8to7(mci, e->e_header, e, boundaries,
|
||||
M87F_OUTER|M87F_NO8TO7, 0) == SM_IO_EOF)
|
||||
goto writeerr;
|
||||
|
||||
/* restore SuprErrs */
|
||||
SuprErrs = oldsuprerrs;
|
||||
@@ -4640,7 +4668,8 @@ putbody(mci, e, separator)
|
||||
|
||||
if (bitset(MCIF_INHEADER, mci->mci_flags))
|
||||
{
|
||||
putline("", mci);
|
||||
if (!putline("", mci))
|
||||
goto writeerr;
|
||||
mci->mci_flags &= ~MCIF_INHEADER;
|
||||
}
|
||||
|
||||
@@ -4731,11 +4760,6 @@ putbody(mci, e, separator)
|
||||
dead = true;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
for (xp = buf; xp < bp; xp++)
|
||||
@@ -4748,11 +4772,6 @@ putbody(mci, e, separator)
|
||||
dead = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
}
|
||||
}
|
||||
if (dead)
|
||||
continue;
|
||||
@@ -4763,11 +4782,6 @@ putbody(mci, e, separator)
|
||||
mci->mci_mailer->m_eol)
|
||||
== SM_IO_EOF)
|
||||
break;
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
}
|
||||
pos = 0;
|
||||
}
|
||||
else
|
||||
@@ -4801,11 +4815,6 @@ putbody(mci, e, separator)
|
||||
mci->mci_mailer->m_eol)
|
||||
== SM_IO_EOF)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
}
|
||||
|
||||
if (TrafficLogFile != NULL)
|
||||
{
|
||||
@@ -4867,11 +4876,6 @@ putch:
|
||||
dead = true;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
}
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
@@ -4887,11 +4891,6 @@ putch:
|
||||
dead = true;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
}
|
||||
|
||||
if (TrafficLogFile != NULL)
|
||||
{
|
||||
@@ -4917,11 +4916,6 @@ putch:
|
||||
mci->mci_mailer->m_eol)
|
||||
== SM_IO_EOF)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
}
|
||||
pos = 0;
|
||||
ostate = OS_HEAD;
|
||||
}
|
||||
@@ -4939,11 +4933,6 @@ putch:
|
||||
dead = true;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
}
|
||||
pos++;
|
||||
ostate = OS_INLINE;
|
||||
}
|
||||
@@ -4970,11 +4959,6 @@ putch:
|
||||
dead = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
}
|
||||
}
|
||||
pos += bp - buf;
|
||||
}
|
||||
@@ -4984,11 +4968,9 @@ putch:
|
||||
(void) sm_io_fputs(TrafficLogFile,
|
||||
SM_TIME_DEFAULT,
|
||||
mci->mci_mailer->m_eol);
|
||||
(void) sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT,
|
||||
mci->mci_mailer->m_eol);
|
||||
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
if (sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT,
|
||||
mci->mci_mailer->m_eol) == SM_IO_EOF)
|
||||
goto writeerr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4998,6 +4980,7 @@ putch:
|
||||
qid_printqueue(e->e_dfqgrp, e->e_dfqdir),
|
||||
DATAFL_LETTER, e->e_id);
|
||||
ExitStat = EX_IOERR;
|
||||
ioerr = true;
|
||||
}
|
||||
|
||||
endofmessage:
|
||||
@@ -5012,23 +4995,35 @@ endofmessage:
|
||||
** offset to match.
|
||||
*/
|
||||
|
||||
save_errno = errno;
|
||||
if (e->e_dfp != NULL)
|
||||
(void) bfrewind(e->e_dfp);
|
||||
|
||||
/* some mailers want extra blank line at end of message */
|
||||
if (!dead && bitnset(M_BLANKEND, mci->mci_mailer->m_flags) &&
|
||||
buf[0] != '\0' && buf[0] != '\n')
|
||||
putline("", mci);
|
||||
|
||||
(void) sm_io_flush(mci->mci_out, SM_TIME_DEFAULT);
|
||||
if (sm_io_error(mci->mci_out) && errno != EPIPE)
|
||||
{
|
||||
syserr("putbody: write error");
|
||||
ExitStat = EX_IOERR;
|
||||
if (!putline("", mci))
|
||||
goto writeerr;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
if (!dead &&
|
||||
(sm_io_flush(mci->mci_out, SM_TIME_DEFAULT) == SM_IO_EOF ||
|
||||
(sm_io_error(mci->mci_out) && errno != EPIPE)))
|
||||
{
|
||||
save_errno = errno;
|
||||
syserr("putbody: write error");
|
||||
ExitStat = EX_IOERR;
|
||||
ioerr = true;
|
||||
}
|
||||
|
||||
errno = save_errno;
|
||||
return !dead && !ioerr;
|
||||
|
||||
writeerr:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** MAILFILE -- Send a message to a file.
|
||||
**
|
||||
@@ -5559,14 +5554,14 @@ mailfile(filename, mailer, ctladdr, sfflags, e)
|
||||
}
|
||||
#endif /* MIME7TO8 */
|
||||
|
||||
putfromline(&mcibuf, e);
|
||||
(*e->e_puthdr)(&mcibuf, e->e_header, e, M87F_OUTER);
|
||||
(*e->e_putbody)(&mcibuf, e, NULL);
|
||||
putline("\n", &mcibuf);
|
||||
if (sm_io_flush(f, SM_TIME_DEFAULT) != 0 ||
|
||||
if (!putfromline(&mcibuf, e) ||
|
||||
!(*e->e_puthdr)(&mcibuf, e->e_header, e, M87F_OUTER) ||
|
||||
!(*e->e_putbody)(&mcibuf, e, NULL) ||
|
||||
!putline("\n", &mcibuf) ||
|
||||
(sm_io_flush(f, SM_TIME_DEFAULT) != 0 ||
|
||||
(SuperSafe != SAFE_NO &&
|
||||
fsync(sm_io_getinfo(f, SM_IO_WHAT_FD, NULL)) < 0) ||
|
||||
sm_io_error(f))
|
||||
sm_io_error(f)))
|
||||
{
|
||||
setstat(EX_IOERR);
|
||||
#if !NOFTRUNCATE
|
||||
@@ -6128,86 +6123,23 @@ starttls(m, mci, e)
|
||||
ssl_retry:
|
||||
if ((result = SSL_connect(clt_ssl)) <= 0)
|
||||
{
|
||||
int i;
|
||||
bool timedout;
|
||||
time_t left;
|
||||
time_t now = curtime();
|
||||
struct timeval tv;
|
||||
int i, ssl_err;
|
||||
|
||||
/* what to do in this case? */
|
||||
i = SSL_get_error(clt_ssl, result);
|
||||
ssl_err = SSL_get_error(clt_ssl, result);
|
||||
i = tls_retry(clt_ssl, rfd, wfd, tlsstart,
|
||||
TimeOuts.to_starttls, ssl_err, "client");
|
||||
if (i > 0)
|
||||
goto ssl_retry;
|
||||
|
||||
/*
|
||||
** For SSL_ERROR_WANT_{READ,WRITE}:
|
||||
** There is not a complete SSL record available yet
|
||||
** or there is only a partial SSL record removed from
|
||||
** the network (socket) buffer into the SSL buffer.
|
||||
** The SSL_connect will only succeed when a full
|
||||
** SSL record is available (assuming a "real" error
|
||||
** doesn't happen). To handle when a "real" error
|
||||
** does happen the select is set for exceptions too.
|
||||
** The connection may be re-negotiated during this time
|
||||
** so both read and write "want errors" need to be handled.
|
||||
** A select() exception loops back so that a proper SSL
|
||||
** error message can be gotten.
|
||||
*/
|
||||
|
||||
left = TimeOuts.to_starttls - (now - tlsstart);
|
||||
timedout = left <= 0;
|
||||
if (!timedout)
|
||||
{
|
||||
tv.tv_sec = left;
|
||||
tv.tv_usec = 0;
|
||||
}
|
||||
|
||||
if (!timedout && FD_SETSIZE > 0 &&
|
||||
(rfd >= FD_SETSIZE ||
|
||||
(i == SSL_ERROR_WANT_WRITE && wfd >= FD_SETSIZE)))
|
||||
{
|
||||
if (LogLevel > 5)
|
||||
{
|
||||
sm_syslog(LOG_ERR, e->e_id,
|
||||
"STARTTLS=client, error: fd %d/%d too large",
|
||||
rfd, wfd);
|
||||
if (LogLevel > 8)
|
||||
tlslogerr("client");
|
||||
}
|
||||
errno = EINVAL;
|
||||
goto tlsfail;
|
||||
}
|
||||
if (!timedout && i == SSL_ERROR_WANT_READ)
|
||||
{
|
||||
fd_set ssl_maskr, ssl_maskx;
|
||||
|
||||
FD_ZERO(&ssl_maskr);
|
||||
FD_SET(rfd, &ssl_maskr);
|
||||
FD_ZERO(&ssl_maskx);
|
||||
FD_SET(rfd, &ssl_maskx);
|
||||
if (select(rfd + 1, &ssl_maskr, NULL, &ssl_maskx, &tv)
|
||||
> 0)
|
||||
goto ssl_retry;
|
||||
}
|
||||
if (!timedout && i == SSL_ERROR_WANT_WRITE)
|
||||
{
|
||||
fd_set ssl_maskw, ssl_maskx;
|
||||
|
||||
FD_ZERO(&ssl_maskw);
|
||||
FD_SET(wfd, &ssl_maskw);
|
||||
FD_ZERO(&ssl_maskx);
|
||||
FD_SET(rfd, &ssl_maskx);
|
||||
if (select(wfd + 1, NULL, &ssl_maskw, &ssl_maskx, &tv)
|
||||
> 0)
|
||||
goto ssl_retry;
|
||||
}
|
||||
if (LogLevel > 5)
|
||||
{
|
||||
sm_syslog(LOG_ERR, e->e_id,
|
||||
"STARTTLS=client, error: connect failed=%d, SSL_error=%d, timedout=%d, errno=%d",
|
||||
result, i, (int) timedout, errno);
|
||||
sm_syslog(LOG_WARNING, NOQID,
|
||||
"STARTTLS=client, error: connect failed=%d, SSL_error=%d, errno=%d, retry=%d",
|
||||
result, ssl_err, errno, i);
|
||||
if (LogLevel > 8)
|
||||
tlslogerr("client");
|
||||
}
|
||||
tlsfail:
|
||||
|
||||
SSL_free(clt_ssl);
|
||||
clt_ssl = NULL;
|
||||
return EX_SOFTWARE;
|
||||
|
||||
@@ -19,7 +19,7 @@ SM_RCSID("@(#)$Id: headers.c,v 8.287 2004/12/03 18:29:51 ca Exp $")
|
||||
static HDR *allocheader __P((char *, char *, int, SM_RPOOL_T *));
|
||||
static size_t fix_mime_header __P((HDR *, ENVELOPE *));
|
||||
static int priencode __P((char *));
|
||||
static void put_vanilla_header __P((HDR *, char *, MCI *));
|
||||
static bool put_vanilla_header __P((HDR *, char *, MCI *));
|
||||
|
||||
/*
|
||||
** SETUPHEADERS -- initialize headers in symbol table
|
||||
@@ -994,7 +994,6 @@ logsender(e, msgid)
|
||||
char *name;
|
||||
register char *sbp;
|
||||
register char *p;
|
||||
int l;
|
||||
char hbuf[MAXNAME + 1];
|
||||
char sbuf[MAXLINE + 1];
|
||||
char mbuf[MAXNAME + 1];
|
||||
@@ -1003,6 +1002,8 @@ logsender(e, msgid)
|
||||
/* XXX do we still need this? sm_syslog() replaces control chars */
|
||||
if (msgid != NULL)
|
||||
{
|
||||
size_t l;
|
||||
|
||||
l = strlen(msgid);
|
||||
if (l > sizeof mbuf - 1)
|
||||
l = sizeof mbuf - 1;
|
||||
@@ -1542,13 +1543,13 @@ crackaddr(addr, e)
|
||||
** flags -- MIME conversion flags.
|
||||
**
|
||||
** Returns:
|
||||
** none.
|
||||
** success
|
||||
**
|
||||
** Side Effects:
|
||||
** none.
|
||||
*/
|
||||
|
||||
void
|
||||
bool
|
||||
putheader(mci, hdr, e, flags)
|
||||
register MCI *mci;
|
||||
HDR *hdr;
|
||||
@@ -1683,7 +1684,8 @@ putheader(mci, hdr, e, flags)
|
||||
{
|
||||
if (tTd(34, 11))
|
||||
sm_dprintf("\n");
|
||||
put_vanilla_header(h, p, mci);
|
||||
if (!put_vanilla_header(h, p, mci))
|
||||
goto writeerr;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1742,7 +1744,8 @@ putheader(mci, hdr, e, flags)
|
||||
/* no other recipient headers: truncate value */
|
||||
(void) sm_strlcpyn(obuf, sizeof obuf, 2,
|
||||
h->h_field, ":");
|
||||
putline(obuf, mci);
|
||||
if (!putline(obuf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1761,7 +1764,8 @@ putheader(mci, hdr, e, flags)
|
||||
}
|
||||
else
|
||||
{
|
||||
put_vanilla_header(h, p, mci);
|
||||
if (!put_vanilla_header(h, p, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1778,18 +1782,25 @@ putheader(mci, hdr, e, flags)
|
||||
!bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, mci->mci_flags) &&
|
||||
hvalue("MIME-Version", e->e_header) == NULL)
|
||||
{
|
||||
putline("MIME-Version: 1.0", mci);
|
||||
if (!putline("MIME-Version: 1.0", mci))
|
||||
goto writeerr;
|
||||
if (hvalue("Content-Type", e->e_header) == NULL)
|
||||
{
|
||||
(void) sm_snprintf(obuf, sizeof obuf,
|
||||
"Content-Type: text/plain; charset=%s",
|
||||
defcharset(e));
|
||||
putline(obuf, mci);
|
||||
if (!putline(obuf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL)
|
||||
putline("Content-Transfer-Encoding: 8bit", mci);
|
||||
if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL
|
||||
&& !putline("Content-Transfer-Encoding: 8bit", mci))
|
||||
goto writeerr;
|
||||
}
|
||||
#endif /* MIME8TO7 */
|
||||
return true;
|
||||
|
||||
writeerr:
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
** PUT_VANILLA_HEADER -- output a fairly ordinary header
|
||||
@@ -1800,10 +1811,10 @@ putheader(mci, hdr, e, flags)
|
||||
** mci -- the connection info for output
|
||||
**
|
||||
** Returns:
|
||||
** none.
|
||||
** success
|
||||
*/
|
||||
|
||||
static void
|
||||
static bool
|
||||
put_vanilla_header(h, v, mci)
|
||||
HDR *h;
|
||||
char *v;
|
||||
@@ -1834,7 +1845,8 @@ put_vanilla_header(h, v, mci)
|
||||
l = SPACELEFT(obuf, obp) - 1;
|
||||
|
||||
(void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v);
|
||||
putxline(obuf, strlen(obuf), mci, putflags);
|
||||
if (!putxline(obuf, strlen(obuf), mci, putflags))
|
||||
goto writeerr;
|
||||
v += l + 1;
|
||||
obp = obuf;
|
||||
if (*v != ' ' && *v != '\t')
|
||||
@@ -1844,7 +1856,10 @@ put_vanilla_header(h, v, mci)
|
||||
/* XXX This is broken for SPACELEFT()==0 */
|
||||
(void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
|
||||
(int) (SPACELEFT(obuf, obp) - 1), v);
|
||||
putxline(obuf, strlen(obuf), mci, putflags);
|
||||
return putxline(obuf, strlen(obuf), mci, putflags);
|
||||
|
||||
writeerr:
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
** COMMAIZE -- output a header field, making a comma-translated list.
|
||||
@@ -1857,13 +1872,13 @@ put_vanilla_header(h, v, mci)
|
||||
** e -- the envelope containing the message.
|
||||
**
|
||||
** Returns:
|
||||
** none.
|
||||
** success
|
||||
**
|
||||
** Side Effects:
|
||||
** outputs "p" to file "fp".
|
||||
*/
|
||||
|
||||
void
|
||||
bool
|
||||
commaize(h, p, oldstyle, mci, e)
|
||||
register HDR *h;
|
||||
register char *p;
|
||||
@@ -2002,13 +2017,6 @@ commaize(h, p, oldstyle, mci, e)
|
||||
}
|
||||
name = denlstring(name, false, true);
|
||||
|
||||
/*
|
||||
** record data progress so DNS timeouts
|
||||
** don't cause DATA timeouts
|
||||
*/
|
||||
|
||||
DataProgress = true;
|
||||
|
||||
/* output the name with nice formatting */
|
||||
opos += strlen(name);
|
||||
if (!firstone)
|
||||
@@ -2016,7 +2024,8 @@ commaize(h, p, oldstyle, mci, e)
|
||||
if (opos > omax && !firstone)
|
||||
{
|
||||
(void) sm_strlcpy(obp, ",\n", SPACELEFT(obuf, obp));
|
||||
putxline(obuf, strlen(obuf), mci, putflags);
|
||||
if (!putxline(obuf, strlen(obuf), mci, putflags))
|
||||
goto writeerr;
|
||||
obp = obuf;
|
||||
(void) sm_strlcpy(obp, " ", sizeof obuf);
|
||||
opos = strlen(obp);
|
||||
@@ -2038,8 +2047,12 @@ commaize(h, p, oldstyle, mci, e)
|
||||
*obp = '\0';
|
||||
else
|
||||
obuf[sizeof obuf - 1] = '\0';
|
||||
putxline(obuf, strlen(obuf), mci, putflags);
|
||||
return putxline(obuf, strlen(obuf), mci, putflags);
|
||||
|
||||
writeerr:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** COPYHEADER -- copy header list
|
||||
**
|
||||
|
||||
+111
-47
@@ -80,12 +80,14 @@ static bool MapNLtoCRLF;
|
||||
** boundaries -- the currently pending message boundaries.
|
||||
** NULL if we are processing the outer portion.
|
||||
** flags -- to tweak processing.
|
||||
** level -- recursion level.
|
||||
**
|
||||
** Returns:
|
||||
** An indicator of what terminated the message part:
|
||||
** MBT_FINAL -- the final boundary
|
||||
** MBT_INTERMED -- an intermediate boundary
|
||||
** MBT_NOTSEP -- an end of file
|
||||
** SM_IO_EOF -- I/O error occurred
|
||||
*/
|
||||
|
||||
struct args
|
||||
@@ -95,12 +97,13 @@ struct args
|
||||
};
|
||||
|
||||
int
|
||||
mime8to7(mci, header, e, boundaries, flags)
|
||||
mime8to7(mci, header, e, boundaries, flags, level)
|
||||
register MCI *mci;
|
||||
HDR *header;
|
||||
register ENVELOPE *e;
|
||||
char **boundaries;
|
||||
int flags;
|
||||
int level;
|
||||
{
|
||||
register char *p;
|
||||
int linelen;
|
||||
@@ -121,6 +124,18 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
char pvpbuf[MAXLINE];
|
||||
extern unsigned char MimeTokenTab[256];
|
||||
|
||||
if (level > MAXMIMENESTING)
|
||||
{
|
||||
if (!bitset(EF_TOODEEP, e->e_flags))
|
||||
{
|
||||
if (tTd(43, 4))
|
||||
sm_dprintf("mime8to7: too deep, level=%d\n",
|
||||
level);
|
||||
usrerr("mime8to7: recursion level %d exceeded",
|
||||
level);
|
||||
e->e_flags |= EF_DONT_MIME|EF_TOODEEP;
|
||||
}
|
||||
}
|
||||
if (tTd(43, 1))
|
||||
{
|
||||
sm_dprintf("mime8to7: flags = %x, boundaries =", flags);
|
||||
@@ -241,7 +256,9 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
*/
|
||||
|
||||
if (sm_strcasecmp(type, "multipart") == 0 &&
|
||||
(!bitset(M87F_NO8BIT, flags) || bitset(M87F_NO8TO7, flags)))
|
||||
(!bitset(M87F_NO8BIT, flags) || bitset(M87F_NO8TO7, flags)) &&
|
||||
!bitset(EF_TOODEEP, e->e_flags)
|
||||
)
|
||||
{
|
||||
|
||||
if (sm_strcasecmp(subtype, "digest") == 0)
|
||||
@@ -285,10 +302,13 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
}
|
||||
if (i >= MAXMIMENESTING)
|
||||
{
|
||||
usrerr("mime8to7: multipart nesting boundary too deep");
|
||||
if (tTd(43, 4))
|
||||
sm_dprintf("mime8to7: too deep, i=%d\n", i);
|
||||
if (!bitset(EF_TOODEEP, e->e_flags))
|
||||
usrerr("mime8to7: multipart nesting boundary too deep");
|
||||
|
||||
/* avoid bounce loops */
|
||||
e->e_flags |= EF_DONT_MIME;
|
||||
e->e_flags |= EF_DONT_MIME|EF_TOODEEP;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -298,7 +318,8 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
mci->mci_flags |= MCIF_INMIME;
|
||||
|
||||
/* skip the early "comment" prologue */
|
||||
putline("", mci);
|
||||
if (!putline("", mci))
|
||||
goto writeerr;
|
||||
mci->mci_flags &= ~MCIF_INHEADER;
|
||||
bt = MBT_FINAL;
|
||||
while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof buf)
|
||||
@@ -307,8 +328,9 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
bt = mimeboundary(buf, boundaries);
|
||||
if (bt != MBT_NOTSEP)
|
||||
break;
|
||||
putxline(buf, strlen(buf), mci,
|
||||
PXLF_MAPFROM|PXLF_STRIP8BIT);
|
||||
if (!putxline(buf, strlen(buf), mci,
|
||||
PXLF_MAPFROM|PXLF_STRIP8BIT))
|
||||
goto writeerr;
|
||||
if (tTd(43, 99))
|
||||
sm_dprintf(" ...%s", buf);
|
||||
}
|
||||
@@ -319,19 +341,25 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
auto HDR *hdr = NULL;
|
||||
|
||||
(void) sm_strlcpyn(buf, sizeof buf, 2, "--", bbuf);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
if (tTd(43, 35))
|
||||
sm_dprintf(" ...%s\n", buf);
|
||||
collect(e->e_dfp, false, &hdr, e, false);
|
||||
if (tTd(43, 101))
|
||||
putline("+++after collect", mci);
|
||||
putheader(mci, hdr, e, flags);
|
||||
if (!putheader(mci, hdr, e, flags))
|
||||
goto writeerr;
|
||||
if (tTd(43, 101))
|
||||
putline("+++after putheader", mci);
|
||||
bt = mime8to7(mci, hdr, e, boundaries, flags);
|
||||
bt = mime8to7(mci, hdr, e, boundaries, flags,
|
||||
level + 1);
|
||||
if (bt == SM_IO_EOF)
|
||||
goto writeerr;
|
||||
}
|
||||
(void) sm_strlcpyn(buf, sizeof buf, 3, "--", bbuf, "--");
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
if (tTd(43, 35))
|
||||
sm_dprintf(" ...%s\n", buf);
|
||||
boundaries[i] = NULL;
|
||||
@@ -344,8 +372,9 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
bt = mimeboundary(buf, boundaries);
|
||||
if (bt != MBT_NOTSEP)
|
||||
break;
|
||||
putxline(buf, strlen(buf), mci,
|
||||
PXLF_MAPFROM|PXLF_STRIP8BIT);
|
||||
if (!putxline(buf, strlen(buf), mci,
|
||||
PXLF_MAPFROM|PXLF_STRIP8BIT))
|
||||
goto writeerr;
|
||||
if (tTd(43, 99))
|
||||
sm_dprintf(" ...%s", buf);
|
||||
}
|
||||
@@ -365,7 +394,8 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
|
||||
if (sm_strcasecmp(type, "message") == 0)
|
||||
{
|
||||
if (!wordinclass(subtype, 's'))
|
||||
if (!wordinclass(subtype, 's') ||
|
||||
bitset(EF_TOODEEP, e->e_flags))
|
||||
{
|
||||
flags |= M87F_NO8BIT;
|
||||
}
|
||||
@@ -373,19 +403,23 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
{
|
||||
auto HDR *hdr = NULL;
|
||||
|
||||
putline("", mci);
|
||||
if (!putline("", mci))
|
||||
goto writeerr;
|
||||
|
||||
mci->mci_flags |= MCIF_INMIME;
|
||||
collect(e->e_dfp, false, &hdr, e, false);
|
||||
if (tTd(43, 101))
|
||||
putline("+++after collect", mci);
|
||||
putheader(mci, hdr, e, flags);
|
||||
if (!putheader(mci, hdr, e, flags))
|
||||
goto writeerr;
|
||||
if (tTd(43, 101))
|
||||
putline("+++after putheader", mci);
|
||||
if (hvalue("MIME-Version", hdr) == NULL &&
|
||||
!bitset(M87F_NO8TO7, flags))
|
||||
putline("MIME-Version: 1.0", mci);
|
||||
bt = mime8to7(mci, hdr, e, boundaries, flags);
|
||||
!bitset(M87F_NO8TO7, flags) &&
|
||||
!putline("MIME-Version: 1.0", mci))
|
||||
goto writeerr;
|
||||
bt = mime8to7(mci, hdr, e, boundaries, flags,
|
||||
level + 1);
|
||||
mci->mci_flags &= ~MCIF_INMIME;
|
||||
return bt;
|
||||
}
|
||||
@@ -480,11 +514,13 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
"Content-Transfer-Encoding: %.200s", cte);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
if (tTd(43, 36))
|
||||
sm_dprintf(" ...%s\n", buf);
|
||||
}
|
||||
putline("", mci);
|
||||
if (!putline("", mci))
|
||||
goto writeerr;
|
||||
mci->mci_flags &= ~MCIF_INHEADER;
|
||||
while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof buf)
|
||||
!= NULL)
|
||||
@@ -492,7 +528,8 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
bt = mimeboundary(buf, boundaries);
|
||||
if (bt != MBT_NOTSEP)
|
||||
break;
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
if (sm_io_eof(e->e_dfp))
|
||||
bt = MBT_FINAL;
|
||||
@@ -505,12 +542,13 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
|
||||
if (tTd(43, 36))
|
||||
sm_dprintf(" ...Content-Transfer-Encoding: base64\n");
|
||||
putline("Content-Transfer-Encoding: base64", mci);
|
||||
if (!putline("Content-Transfer-Encoding: base64", mci))
|
||||
goto writeerr;
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
"X-MIME-Autoconverted: from 8bit to base64 by %s id %s",
|
||||
MyHostName, e->e_id);
|
||||
putline(buf, mci);
|
||||
putline("", mci);
|
||||
if (!putline(buf, mci) || !putline("", mci))
|
||||
goto writeerr;
|
||||
mci->mci_flags &= ~MCIF_INHEADER;
|
||||
while ((c1 = mime_getchar_crlf(e->e_dfp, boundaries, &bt)) !=
|
||||
SM_IO_EOF)
|
||||
@@ -518,7 +556,8 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
if (linelen > 71)
|
||||
{
|
||||
*bp = '\0';
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
linelen = 0;
|
||||
bp = buf;
|
||||
}
|
||||
@@ -548,7 +587,8 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
*bp++ = Base64Code[c2 & 0x3f];
|
||||
}
|
||||
*bp = '\0';
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -571,12 +611,14 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
|
||||
if (tTd(43, 36))
|
||||
sm_dprintf(" ...Content-Transfer-Encoding: quoted-printable\n");
|
||||
putline("Content-Transfer-Encoding: quoted-printable", mci);
|
||||
if (!putline("Content-Transfer-Encoding: quoted-printable",
|
||||
mci))
|
||||
goto writeerr;
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
"X-MIME-Autoconverted: from 8bit to quoted-printable by %s id %s",
|
||||
MyHostName, e->e_id);
|
||||
putline(buf, mci);
|
||||
putline("", mci);
|
||||
if (!putline(buf, mci) || !putline("", mci))
|
||||
goto writeerr;
|
||||
mci->mci_flags &= ~MCIF_INHEADER;
|
||||
fromstate = 0;
|
||||
c2 = '\n';
|
||||
@@ -598,7 +640,8 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
*bp++ = Base16Code['.' & 0x0f];
|
||||
}
|
||||
*bp = '\0';
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
linelen = fromstate = 0;
|
||||
bp = buf;
|
||||
c2 = c1;
|
||||
@@ -627,7 +670,8 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
c2 = '\n';
|
||||
*bp++ = '=';
|
||||
*bp = '\0';
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
linelen = fromstate = 0;
|
||||
bp = buf;
|
||||
if (c2 == '.')
|
||||
@@ -665,13 +709,17 @@ mime8to7(mci, header, e, boundaries, flags)
|
||||
if (linelen > 0 || boundaries[0] != NULL)
|
||||
{
|
||||
*bp = '\0';
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
|
||||
}
|
||||
if (tTd(43, 3))
|
||||
sm_dprintf("\t\t\tmime8to7=>%s (basic)\n", MimeBoundaryNames[bt]);
|
||||
return bt;
|
||||
|
||||
writeerr:
|
||||
return SM_IO_EOF;
|
||||
}
|
||||
/*
|
||||
** MIME_GETCHAR -- get a character for MIME processing
|
||||
@@ -958,7 +1006,7 @@ static int mime_fromqp __P((unsigned char *, unsigned char **, int));
|
||||
** e -- envelope.
|
||||
**
|
||||
** Returns:
|
||||
** none.
|
||||
** true iff body was written successfully
|
||||
*/
|
||||
|
||||
static char index_64[128] =
|
||||
@@ -975,7 +1023,7 @@ static char index_64[128] =
|
||||
|
||||
# define CHAR64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)])
|
||||
|
||||
void
|
||||
bool
|
||||
mime7to8(mci, header, e)
|
||||
register MCI *mci;
|
||||
HDR *header;
|
||||
@@ -1008,25 +1056,31 @@ mime7to8(mci, header, e)
|
||||
{
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
"Content-Transfer-Encoding: %s", p);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
putline("", mci);
|
||||
if (!putline("", mci))
|
||||
goto writeerr;
|
||||
mci->mci_flags &= ~MCIF_INHEADER;
|
||||
while (sm_io_fgets(e->e_dfp, SM_TIME_DEFAULT, buf, sizeof buf)
|
||||
!= NULL)
|
||||
putline(buf, mci);
|
||||
return;
|
||||
{
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
cataddr(pvp, NULL, buf, sizeof buf, '\0');
|
||||
cte = sm_rpool_strdup_x(e->e_rpool, buf);
|
||||
|
||||
mci->mci_flags |= MCIF_INHEADER;
|
||||
putline("Content-Transfer-Encoding: 8bit", mci);
|
||||
if (!putline("Content-Transfer-Encoding: 8bit", mci))
|
||||
goto writeerr;
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
"X-MIME-Autoconverted: from %.200s to 8bit by %s id %s",
|
||||
cte, MyHostName, e->e_id);
|
||||
putline(buf, mci);
|
||||
putline("", mci);
|
||||
if (!putline(buf, mci) || !putline("", mci))
|
||||
goto writeerr;
|
||||
mci->mci_flags &= ~MCIF_INHEADER;
|
||||
|
||||
/*
|
||||
@@ -1090,7 +1144,8 @@ mime7to8(mci, header, e)
|
||||
if (*fbufp++ == '\n' || fbufp >= &fbuf[MAXLINE]) \
|
||||
{ \
|
||||
CHK_EOL; \
|
||||
putxline((char *) fbuf, fbufp - fbuf, mci, pxflags); \
|
||||
if (!putxline((char *) fbuf, fbufp - fbuf, mci, pxflags)) \
|
||||
goto writeerr; \
|
||||
pxflags &= ~PXLF_NOADDEOL; \
|
||||
fbufp = fbuf; \
|
||||
} \
|
||||
@@ -1127,8 +1182,11 @@ again:
|
||||
continue;
|
||||
|
||||
if (fbufp - fbuf > 0)
|
||||
putxline((char *) fbuf, fbufp - fbuf - 1, mci,
|
||||
pxflags);
|
||||
{
|
||||
if (!putxline((char *) fbuf, fbufp - fbuf - 1,
|
||||
mci, pxflags))
|
||||
goto writeerr;
|
||||
}
|
||||
fbufp = fbuf;
|
||||
if (off >= 0 && buf[off] != '\0')
|
||||
{
|
||||
@@ -1144,7 +1202,8 @@ again:
|
||||
if (fbufp > fbuf)
|
||||
{
|
||||
*fbufp = '\0';
|
||||
putxline((char *) fbuf, fbufp - fbuf, mci, pxflags);
|
||||
if (!putxline((char *) fbuf, fbufp - fbuf, mci, pxflags))
|
||||
goto writeerr;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1154,10 +1213,15 @@ again:
|
||||
** but so is auto-converting MIME in the first place.
|
||||
*/
|
||||
|
||||
putline("", mci);
|
||||
if (!putline("", mci))
|
||||
goto writeerr;
|
||||
|
||||
if (tTd(43, 3))
|
||||
sm_dprintf("\t\t\tmime7to8 => %s to 8bit done\n", cte);
|
||||
return true;
|
||||
|
||||
writeerr:
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
** The following is based on Borenstein's "codes.c" module, with simplifying
|
||||
|
||||
@@ -1337,7 +1337,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
|
||||
/* $&{x} replacement */
|
||||
char *mval = macvalue(rp[1], e);
|
||||
char **xpvp;
|
||||
int trsize = 0;
|
||||
size_t trsize = 0;
|
||||
static size_t pvpb1_size = 0;
|
||||
static char **pvpb1 = NULL;
|
||||
char pvpbuf[PSBUFSIZE];
|
||||
@@ -1352,7 +1352,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
|
||||
/* save the remainder of the input */
|
||||
for (xpvp = pvp; *xpvp != NULL; xpvp++)
|
||||
trsize += sizeof *xpvp;
|
||||
if ((size_t) trsize > pvpb1_size)
|
||||
if (trsize > pvpb1_size)
|
||||
{
|
||||
if (pvpb1 != NULL)
|
||||
sm_free(pvpb1);
|
||||
@@ -1407,7 +1407,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
|
||||
{
|
||||
char **hbrvp;
|
||||
char **xpvp;
|
||||
int trsize;
|
||||
size_t trsize;
|
||||
char *replac;
|
||||
int endtoken;
|
||||
STAB *map;
|
||||
@@ -1509,7 +1509,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
|
||||
*++arg_rvp = NULL;
|
||||
|
||||
/* save the remainder of the input string */
|
||||
trsize = (int) (avp - rvp + 1) * sizeof *rvp;
|
||||
trsize = (avp - rvp + 1) * sizeof *rvp;
|
||||
memmove((char *) pvpb1, (char *) rvp, trsize);
|
||||
|
||||
/* look it up */
|
||||
@@ -2949,7 +2949,7 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid)
|
||||
char *logid;
|
||||
{
|
||||
char *volatile buf;
|
||||
int bufsize;
|
||||
size_t bufsize;
|
||||
int saveexitstat;
|
||||
int volatile rstat = EX_OK;
|
||||
char **pvp;
|
||||
@@ -3163,7 +3163,7 @@ rscap(rwset, p1, p2, e, pvp, pvpbuf, size)
|
||||
int size;
|
||||
{
|
||||
char *volatile buf;
|
||||
int bufsize;
|
||||
size_t bufsize;
|
||||
int volatile rstat = EX_OK;
|
||||
int rsno;
|
||||
bool saveQuickAbort = QuickAbort;
|
||||
|
||||
+160
-95
@@ -15,7 +15,7 @@
|
||||
|
||||
SM_RCSID("@(#)$Id: savemail.c,v 8.304 2004/10/06 21:36:06 ca Exp $")
|
||||
|
||||
static void errbody __P((MCI *, ENVELOPE *, char *));
|
||||
static bool errbody __P((MCI *, ENVELOPE *, char *));
|
||||
static bool pruneroute __P((char *));
|
||||
|
||||
/*
|
||||
@@ -432,12 +432,13 @@ savemail(e, sendbody)
|
||||
p = macvalue('g', e);
|
||||
macdefine(&e->e_macro, A_PERM, 'g', e->e_sender);
|
||||
|
||||
putfromline(&mcibuf, e);
|
||||
(*e->e_puthdr)(&mcibuf, e->e_header, e, M87F_OUTER);
|
||||
(*e->e_putbody)(&mcibuf, e, NULL);
|
||||
putline("\n", &mcibuf); /* XXX EOL from FileMailer? */
|
||||
(void) sm_io_flush(fp, SM_TIME_DEFAULT);
|
||||
if (sm_io_error(fp) ||
|
||||
if (!putfromline(&mcibuf, e) ||
|
||||
!(*e->e_puthdr)(&mcibuf, e->e_header, e,
|
||||
M87F_OUTER) ||
|
||||
!(*e->e_putbody)(&mcibuf, e, NULL) ||
|
||||
!putline("\n", &mcibuf) ||
|
||||
sm_io_flush(fp, SM_TIME_DEFAULT) == SM_IO_EOF ||
|
||||
sm_io_error(fp) ||
|
||||
sm_io_close(fp, SM_TIME_DEFAULT) < 0)
|
||||
state = ESM_PANIC;
|
||||
else
|
||||
@@ -732,14 +733,14 @@ returntosender(msg, returnq, flags, e)
|
||||
** separator -- any possible MIME separator (unused).
|
||||
**
|
||||
** Returns:
|
||||
** none
|
||||
** success
|
||||
**
|
||||
** Side Effects:
|
||||
** Outputs the body of an error message.
|
||||
*/
|
||||
|
||||
/* ARGSUSED2 */
|
||||
static void
|
||||
static bool
|
||||
errbody(mci, e, separator)
|
||||
register MCI *mci;
|
||||
register ENVELOPE *e;
|
||||
@@ -757,14 +758,16 @@ errbody(mci, e, separator)
|
||||
|
||||
if (bitset(MCIF_INHEADER, mci->mci_flags))
|
||||
{
|
||||
putline("", mci);
|
||||
if (!putline("", mci))
|
||||
goto writeerr;
|
||||
mci->mci_flags &= ~MCIF_INHEADER;
|
||||
}
|
||||
if (e->e_parent == NULL)
|
||||
{
|
||||
syserr("errbody: null parent");
|
||||
putline(" ----- Original message lost -----\n", mci);
|
||||
return;
|
||||
if (!putline(" ----- Original message lost -----\n", mci))
|
||||
goto writeerr;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -773,11 +776,12 @@ errbody(mci, e, separator)
|
||||
|
||||
if (e->e_msgboundary != NULL)
|
||||
{
|
||||
putline("This is a MIME-encapsulated message", mci);
|
||||
putline("", mci);
|
||||
(void) sm_strlcpyn(buf, sizeof buf, 2, "--", e->e_msgboundary);
|
||||
putline(buf, mci);
|
||||
putline("", mci);
|
||||
if (!putline("This is a MIME-encapsulated message", mci) ||
|
||||
!putline("", mci) ||
|
||||
!putline(buf, mci) ||
|
||||
!putline("", mci))
|
||||
goto writeerr;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -799,31 +803,36 @@ errbody(mci, e, separator)
|
||||
if (!pm_notify && q == NULL &&
|
||||
!bitset(EF_FATALERRS|EF_SENDRECEIPT, e->e_parent->e_flags))
|
||||
{
|
||||
putline(" **********************************************",
|
||||
mci);
|
||||
putline(" ** THIS IS A WARNING MESSAGE ONLY **",
|
||||
mci);
|
||||
putline(" ** YOU DO NOT NEED TO RESEND YOUR MESSAGE **",
|
||||
mci);
|
||||
putline(" **********************************************",
|
||||
mci);
|
||||
putline("", mci);
|
||||
if (!putline(" **********************************************",
|
||||
mci) ||
|
||||
!putline(" ** THIS IS A WARNING MESSAGE ONLY **",
|
||||
mci) ||
|
||||
!putline(" ** YOU DO NOT NEED TO RESEND YOUR MESSAGE **",
|
||||
mci) ||
|
||||
!putline(" **********************************************",
|
||||
mci) ||
|
||||
!putline("", mci))
|
||||
goto writeerr;
|
||||
}
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
"The original message was received at %s",
|
||||
arpadate(ctime(&e->e_parent->e_ctime)));
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
expand("from \201_", buf, sizeof buf, e->e_parent);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
|
||||
/* include id in postmaster copies */
|
||||
if (pm_notify && e->e_parent->e_id != NULL)
|
||||
{
|
||||
(void) sm_strlcpyn(buf, sizeof buf, 2, "with id ",
|
||||
e->e_parent->e_id);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
putline("", mci);
|
||||
if (!putline("", mci))
|
||||
goto writeerr;
|
||||
|
||||
/*
|
||||
** Output error message header (if specified and available).
|
||||
@@ -849,17 +858,19 @@ errbody(mci, e, separator)
|
||||
{
|
||||
translate_dollars(buf);
|
||||
expand(buf, buf, sizeof buf, e);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
(void) sm_io_close(xfile, SM_TIME_DEFAULT);
|
||||
putline("\n", mci);
|
||||
if (!putline("\n", mci))
|
||||
goto writeerr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
expand(ErrMsgFile, buf, sizeof buf, e);
|
||||
putline(buf, mci);
|
||||
putline("", mci);
|
||||
if (!putline(buf, mci) || !putline("", mci))
|
||||
goto writeerr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -877,21 +888,24 @@ errbody(mci, e, separator)
|
||||
|
||||
if (printheader)
|
||||
{
|
||||
putline(" ----- The following addresses had permanent fatal errors -----",
|
||||
mci);
|
||||
if (!putline(" ----- The following addresses had permanent fatal errors -----",
|
||||
mci))
|
||||
goto writeerr;
|
||||
printheader = false;
|
||||
}
|
||||
|
||||
(void) sm_strlcpy(buf, shortenstring(q->q_paddr, MAXSHORTSTR),
|
||||
sizeof buf);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
if (q->q_rstatus != NULL)
|
||||
{
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
" (reason: %s)",
|
||||
shortenstring(exitstat(q->q_rstatus),
|
||||
MAXSHORTSTR));
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
if (q->q_alias != NULL)
|
||||
{
|
||||
@@ -899,11 +913,12 @@ errbody(mci, e, separator)
|
||||
" (expanded from: %s)",
|
||||
shortenstring(q->q_alias->q_paddr,
|
||||
MAXSHORTSTR));
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
}
|
||||
if (!printheader)
|
||||
putline("", mci);
|
||||
if (!printheader && !putline("", mci))
|
||||
goto writeerr;
|
||||
|
||||
/* transient non-fatal errors */
|
||||
printheader = true;
|
||||
@@ -917,25 +932,28 @@ errbody(mci, e, separator)
|
||||
|
||||
if (printheader)
|
||||
{
|
||||
putline(" ----- The following addresses had transient non-fatal errors -----",
|
||||
mci);
|
||||
if (!putline(" ----- The following addresses had transient non-fatal errors -----",
|
||||
mci))
|
||||
goto writeerr;
|
||||
printheader = false;
|
||||
}
|
||||
|
||||
(void) sm_strlcpy(buf, shortenstring(q->q_paddr, MAXSHORTSTR),
|
||||
sizeof buf);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
if (q->q_alias != NULL)
|
||||
{
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
" (expanded from: %s)",
|
||||
shortenstring(q->q_alias->q_paddr,
|
||||
MAXSHORTSTR));
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
}
|
||||
if (!printheader)
|
||||
putline("", mci);
|
||||
if (!printheader && !putline("", mci))
|
||||
goto writeerr;
|
||||
|
||||
/* successful delivery notifications */
|
||||
printheader = true;
|
||||
@@ -968,25 +986,28 @@ errbody(mci, e, separator)
|
||||
|
||||
if (printheader)
|
||||
{
|
||||
putline(" ----- The following addresses had successful delivery notifications -----",
|
||||
mci);
|
||||
if (!putline(" ----- The following addresses had successful delivery notifications -----",
|
||||
mci))
|
||||
goto writeerr;
|
||||
printheader = false;
|
||||
}
|
||||
|
||||
(void) sm_snprintf(buf, sizeof buf, "%s (%s)",
|
||||
shortenstring(q->q_paddr, MAXSHORTSTR), p);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
if (q->q_alias != NULL)
|
||||
{
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
" (expanded from: %s)",
|
||||
shortenstring(q->q_alias->q_paddr,
|
||||
MAXSHORTSTR));
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
}
|
||||
if (!printheader)
|
||||
putline("", mci);
|
||||
if (!printheader && !putline("", mci))
|
||||
goto writeerr;
|
||||
|
||||
/*
|
||||
** Output transcript of errors
|
||||
@@ -995,8 +1016,9 @@ errbody(mci, e, separator)
|
||||
(void) sm_io_flush(smioout, SM_TIME_DEFAULT);
|
||||
if (e->e_parent->e_xfp == NULL)
|
||||
{
|
||||
putline(" ----- Transcript of session is unavailable -----\n",
|
||||
mci);
|
||||
if (!putline(" ----- Transcript of session is unavailable -----\n",
|
||||
mci))
|
||||
goto writeerr;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1007,11 +1029,12 @@ errbody(mci, e, separator)
|
||||
while (sm_io_fgets(e->e_parent->e_xfp, SM_TIME_DEFAULT, buf,
|
||||
sizeof buf) != NULL)
|
||||
{
|
||||
if (printheader)
|
||||
putline(" ----- Transcript of session follows -----\n",
|
||||
mci);
|
||||
if (printheader && !putline(" ----- Transcript of session follows -----\n",
|
||||
mci))
|
||||
goto writeerr;
|
||||
printheader = false;
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
}
|
||||
errno = 0;
|
||||
@@ -1023,11 +1046,12 @@ errbody(mci, e, separator)
|
||||
|
||||
if (e->e_msgboundary != NULL)
|
||||
{
|
||||
putline("", mci);
|
||||
(void) sm_strlcpyn(buf, sizeof buf, 2, "--", e->e_msgboundary);
|
||||
putline(buf, mci);
|
||||
putline("Content-Type: message/delivery-status", mci);
|
||||
putline("", mci);
|
||||
if (!putline("", mci) ||
|
||||
!putline(buf, mci) ||
|
||||
!putline("Content-Type: message/delivery-status", mci) ||
|
||||
!putline("", mci))
|
||||
goto writeerr;
|
||||
|
||||
/*
|
||||
** Output per-message information.
|
||||
@@ -1039,13 +1063,15 @@ errbody(mci, e, separator)
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
"Original-Envelope-Id: %.800s",
|
||||
xuntextify(e->e_parent->e_envid));
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
|
||||
/* Reporting-MTA: is us (required) */
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
"Reporting-MTA: dns; %.800s", MyHostName);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
|
||||
/* DSN-Gateway: not relevant since we are not translating */
|
||||
|
||||
@@ -1059,13 +1085,15 @@ errbody(mci, e, separator)
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
"Received-From-MTA: %s; %.800s",
|
||||
p, RealHostName);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
|
||||
/* Arrival-Date: -- when it arrived here */
|
||||
(void) sm_strlcpyn(buf, sizeof buf, 2, "Arrival-Date: ",
|
||||
arpadate(ctime(&e->e_parent->e_ctime)));
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
|
||||
/* Deliver-By-Date: -- when it should have been delivered */
|
||||
if (IS_DLVR_BY(e->e_parent))
|
||||
@@ -1076,7 +1104,8 @@ errbody(mci, e, separator)
|
||||
(void) sm_strlcpyn(buf, sizeof buf, 2,
|
||||
"Deliver-By-Date: ",
|
||||
arpadate(ctime(&dbyd)));
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1119,7 +1148,8 @@ errbody(mci, e, separator)
|
||||
else
|
||||
continue;
|
||||
|
||||
putline("", mci);
|
||||
if (!putline("", mci))
|
||||
goto writeerr;
|
||||
|
||||
/* Original-Recipient: -- passed from on high */
|
||||
if (q->q_orcpt != NULL)
|
||||
@@ -1127,7 +1157,8 @@ errbody(mci, e, separator)
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
"Original-Recipient: %.800s",
|
||||
q->q_orcpt);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
|
||||
/* Figure out actual recipient */
|
||||
@@ -1176,7 +1207,8 @@ errbody(mci, e, separator)
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
"Final-Recipient: %s",
|
||||
q->q_finalrcpt);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
|
||||
/* X-Actual-Recipient: -- the real problem address */
|
||||
@@ -1190,13 +1222,15 @@ errbody(mci, e, separator)
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
"X-Actual-Recipient: %s",
|
||||
actual);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
|
||||
/* Action: -- what happened? */
|
||||
(void) sm_strlcpyn(buf, sizeof buf, 2, "Action: ",
|
||||
action);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
|
||||
/* Status: -- what _really_ happened? */
|
||||
if (q->q_status != NULL)
|
||||
@@ -1208,7 +1242,8 @@ errbody(mci, e, separator)
|
||||
else
|
||||
p = "2.0.0";
|
||||
(void) sm_strlcpyn(buf, sizeof buf, 2, "Status: ", p);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
|
||||
/* Remote-MTA: -- who was I talking to? */
|
||||
if (q->q_statmta != NULL)
|
||||
@@ -1222,7 +1257,8 @@ errbody(mci, e, separator)
|
||||
p = &buf[strlen(buf) - 1];
|
||||
if (*p == '.')
|
||||
*p = '\0';
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
|
||||
/* Diagnostic-Code: -- actual result from other end */
|
||||
@@ -1234,7 +1270,8 @@ errbody(mci, e, separator)
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
"Diagnostic-Code: %s; %.800s",
|
||||
p, q->q_rstatus);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
|
||||
/* Last-Attempt-Date: -- fine granularity */
|
||||
@@ -1243,7 +1280,8 @@ errbody(mci, e, separator)
|
||||
(void) sm_strlcpyn(buf, sizeof buf, 2,
|
||||
"Last-Attempt-Date: ",
|
||||
arpadate(ctime(&q->q_statdate)));
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
|
||||
/* Will-Retry-Until: -- for delayed messages only */
|
||||
if (QS_IS_QUEUEUP(q->q_state))
|
||||
@@ -1255,7 +1293,8 @@ errbody(mci, e, separator)
|
||||
(void) sm_strlcpyn(buf, sizeof buf, 2,
|
||||
"Will-Retry-Until: ",
|
||||
arpadate(ctime(&xdate)));
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1265,7 +1304,8 @@ errbody(mci, e, separator)
|
||||
** Output text of original message
|
||||
*/
|
||||
|
||||
putline("", mci);
|
||||
if (!putline("", mci))
|
||||
goto writeerr;
|
||||
if (bitset(EF_HAS_DF, e->e_parent->e_flags))
|
||||
{
|
||||
sendbody = !bitset(EF_NO_BODY_RETN, e->e_parent->e_flags) &&
|
||||
@@ -1273,21 +1313,27 @@ errbody(mci, e, separator)
|
||||
|
||||
if (e->e_msgboundary == NULL)
|
||||
{
|
||||
if (sendbody)
|
||||
putline(" ----- Original message follows -----\n", mci);
|
||||
else
|
||||
putline(" ----- Message header follows -----\n", mci);
|
||||
if (!putline(
|
||||
sendbody
|
||||
? " ----- Original message follows -----\n"
|
||||
: " ----- Message header follows -----\n",
|
||||
mci))
|
||||
{
|
||||
goto writeerr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(void) sm_strlcpyn(buf, sizeof buf, 2, "--",
|
||||
e->e_msgboundary);
|
||||
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
(void) sm_strlcpyn(buf, sizeof buf, 2, "Content-Type: ",
|
||||
sendbody ? "message/rfc822"
|
||||
: "text/rfc822-headers");
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
|
||||
p = hvalue("Content-Transfer-Encoding",
|
||||
e->e_parent->e_header);
|
||||
@@ -1301,43 +1347,62 @@ errbody(mci, e, separator)
|
||||
(void) sm_snprintf(buf, sizeof buf,
|
||||
"Content-Transfer-Encoding: %s",
|
||||
p);
|
||||
putline(buf, mci);
|
||||
if (!putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
}
|
||||
putline("", mci);
|
||||
if (!putline("", mci))
|
||||
goto writeerr;
|
||||
save_errno = errno;
|
||||
putheader(mci, e->e_parent->e_header, e->e_parent, M87F_OUTER);
|
||||
if (!putheader(mci, e->e_parent->e_header, e->e_parent,
|
||||
M87F_OUTER))
|
||||
goto writeerr;
|
||||
errno = save_errno;
|
||||
if (sendbody)
|
||||
putbody(mci, e->e_parent, e->e_msgboundary);
|
||||
{
|
||||
if (!putbody(mci, e->e_parent, e->e_msgboundary))
|
||||
goto writeerr;
|
||||
}
|
||||
else if (e->e_msgboundary == NULL)
|
||||
{
|
||||
putline("", mci);
|
||||
putline(" ----- Message body suppressed -----", mci);
|
||||
if (!putline("", mci) ||
|
||||
!putline(" ----- Message body suppressed -----",
|
||||
mci))
|
||||
{
|
||||
goto writeerr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (e->e_msgboundary == NULL)
|
||||
{
|
||||
putline(" ----- No message was collected -----\n", mci);
|
||||
if (!putline(" ----- No message was collected -----\n", mci))
|
||||
goto writeerr;
|
||||
}
|
||||
|
||||
if (e->e_msgboundary != NULL)
|
||||
{
|
||||
putline("", mci);
|
||||
(void) sm_strlcpyn(buf, sizeof buf, 3, "--", e->e_msgboundary,
|
||||
"--");
|
||||
putline(buf, mci);
|
||||
if (!putline("", mci) || !putline(buf, mci))
|
||||
goto writeerr;
|
||||
}
|
||||
putline("", mci);
|
||||
(void) sm_io_flush(mci->mci_out, SM_TIME_DEFAULT);
|
||||
if (!putline("", mci) ||
|
||||
sm_io_flush(mci->mci_out, SM_TIME_DEFAULT) == SM_IO_EOF)
|
||||
goto writeerr;
|
||||
|
||||
/*
|
||||
** Cleanup and exit
|
||||
*/
|
||||
|
||||
if (errno != 0)
|
||||
{
|
||||
writeerr:
|
||||
syserr("errbody: I/O error");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
** SMTPTODSN -- convert SMTP to DSN status code
|
||||
**
|
||||
|
||||
@@ -809,13 +809,13 @@ extern struct hdrinfo HdrInfo[];
|
||||
/* functions */
|
||||
extern void addheader __P((char *, char *, int, ENVELOPE *));
|
||||
extern unsigned long chompheader __P((char *, int, HDR **, ENVELOPE *));
|
||||
extern void commaize __P((HDR *, char *, bool, MCI *, ENVELOPE *));
|
||||
extern bool commaize __P((HDR *, char *, bool, MCI *, ENVELOPE *));
|
||||
extern HDR *copyheader __P((HDR *, SM_RPOOL_T *));
|
||||
extern void eatheader __P((ENVELOPE *, bool, bool));
|
||||
extern char *hvalue __P((char *, HDR *));
|
||||
extern void insheader __P((int, char *, char *, int, ENVELOPE *));
|
||||
extern bool isheader __P((char *));
|
||||
extern void putfromline __P((MCI *, ENVELOPE *));
|
||||
extern bool putfromline __P((MCI *, ENVELOPE *));
|
||||
extern void setupheaders __P((void));
|
||||
|
||||
/*
|
||||
@@ -870,9 +870,9 @@ struct envelope
|
||||
short e_sendmode; /* message send mode */
|
||||
short e_errormode; /* error return mode */
|
||||
short e_timeoutclass; /* message timeout class */
|
||||
void (*e_puthdr)__P((MCI *, HDR *, ENVELOPE *, int));
|
||||
bool (*e_puthdr)__P((MCI *, HDR *, ENVELOPE *, int));
|
||||
/* function to put header of message */
|
||||
void (*e_putbody)__P((MCI *, ENVELOPE *, char *));
|
||||
bool (*e_putbody)__P((MCI *, ENVELOPE *, char *));
|
||||
/* function to put body of message */
|
||||
ENVELOPE *e_parent; /* the message this one encloses */
|
||||
ENVELOPE *e_sibling; /* the next envelope of interest */
|
||||
@@ -942,6 +942,7 @@ struct envelope
|
||||
#define EF_TOOBIG 0x02000000L /* message is too big */
|
||||
#define EF_SPLIT 0x04000000L /* envelope has been split */
|
||||
#define EF_UNSAFE 0x08000000L /* unsafe: read from untrusted source */
|
||||
#define EF_TOODEEP 0x10000000L /* message is nested too deep */
|
||||
|
||||
#define DLVR_NOTIFY 0x01
|
||||
#define DLVR_RETURN 0x02
|
||||
@@ -965,8 +966,8 @@ extern void dropenvelope __P((ENVELOPE *, bool, bool));
|
||||
extern ENVELOPE *newenvelope __P((ENVELOPE *, ENVELOPE *, SM_RPOOL_T *));
|
||||
extern void clrsessenvelope __P((ENVELOPE *));
|
||||
extern void printenvflags __P((ENVELOPE *));
|
||||
extern void putbody __P((MCI *, ENVELOPE *, char *));
|
||||
extern void putheader __P((MCI *, HDR *, ENVELOPE *, int));
|
||||
extern bool putbody __P((MCI *, ENVELOPE *, char *));
|
||||
extern bool putheader __P((MCI *, HDR *, ENVELOPE *, int));
|
||||
|
||||
/*
|
||||
** Message priority classes.
|
||||
@@ -1650,8 +1651,8 @@ EXTERN unsigned long PrivacyFlags; /* privacy flags */
|
||||
#define M87F_NO8TO7 0x0004 /* don't do 8->7 bit conversions */
|
||||
|
||||
/* functions */
|
||||
extern void mime7to8 __P((MCI *, HDR *, ENVELOPE *));
|
||||
extern int mime8to7 __P((MCI *, HDR *, ENVELOPE *, char **, int));
|
||||
extern bool mime7to8 __P((MCI *, HDR *, ENVELOPE *));
|
||||
extern int mime8to7 __P((MCI *, HDR *, ENVELOPE *, char **, int, int));
|
||||
|
||||
/*
|
||||
** Flags passed to returntosender.
|
||||
@@ -2145,7 +2146,6 @@ EXTERN bool ColonOkInAddr; /* single colon legal in address */
|
||||
#if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_)
|
||||
EXTERN bool ConfigFileRead; /* configuration file has been read */
|
||||
#endif /* !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) */
|
||||
EXTERN bool volatile DataProgress; /* have we sent anything since last check */
|
||||
EXTERN bool DisConnected; /* running with OutChannel redirect to transcript file */
|
||||
EXTERN bool DontExpandCnames; /* do not $[...$] expand CNAMEs */
|
||||
EXTERN bool DontInitGroups; /* avoid initgroups() because of NIS cost */
|
||||
@@ -2519,8 +2519,8 @@ extern void printopenfds __P((bool));
|
||||
extern void printqueue __P((void));
|
||||
extern void printrules __P((void));
|
||||
extern pid_t prog_open __P((char **, int *, ENVELOPE *));
|
||||
extern void putline __P((char *, MCI *));
|
||||
extern void putxline __P((char *, size_t, MCI *, int));
|
||||
extern bool putline __P((char *, MCI *));
|
||||
extern bool putxline __P((char *, size_t, MCI *, int));
|
||||
extern void queueup_macros __P((int, SM_FILE_T *, ENVELOPE *));
|
||||
extern void readcf __P((char *, bool, ENVELOPE *));
|
||||
extern SIGFUNC_DECL reapchild __P((int));
|
||||
|
||||
+181
-41
@@ -540,6 +540,125 @@ tls_close(fp)
|
||||
/* maximum number of retries for TLS related I/O due to handshakes */
|
||||
# define MAX_TLS_IOS 4
|
||||
|
||||
/*
|
||||
** TLS_RETRY -- check whether a failed SSL operation can be retried
|
||||
**
|
||||
** Parameters:
|
||||
** ssl -- TLS structure
|
||||
** rfd -- read fd
|
||||
** wfd -- write fd
|
||||
** tlsstart -- start time of TLS operation
|
||||
** timeout -- timeout for TLS operation
|
||||
** err -- SSL error
|
||||
** where -- description of operation
|
||||
**
|
||||
** Results:
|
||||
** >0 on success
|
||||
** 0 on timeout
|
||||
** <0 on error
|
||||
*/
|
||||
|
||||
int
|
||||
tls_retry(ssl, rfd, wfd, tlsstart, timeout, err, where)
|
||||
SSL *ssl;
|
||||
int rfd;
|
||||
int wfd;
|
||||
time_t tlsstart;
|
||||
int timeout;
|
||||
int err;
|
||||
const char *where;
|
||||
{
|
||||
int ret;
|
||||
time_t left;
|
||||
time_t now = curtime();
|
||||
struct timeval tv;
|
||||
|
||||
ret = -1;
|
||||
|
||||
/*
|
||||
** For SSL_ERROR_WANT_{READ,WRITE}:
|
||||
** There is not a complete SSL record available yet
|
||||
** or there is only a partial SSL record removed from
|
||||
** the network (socket) buffer into the SSL buffer.
|
||||
** The SSL_connect will only succeed when a full
|
||||
** SSL record is available (assuming a "real" error
|
||||
** doesn't happen). To handle when a "real" error
|
||||
** does happen the select is set for exceptions too.
|
||||
** The connection may be re-negotiated during this time
|
||||
** so both read and write "want errors" need to be handled.
|
||||
** A select() exception loops back so that a proper SSL
|
||||
** error message can be gotten.
|
||||
*/
|
||||
|
||||
left = timeout - (now - tlsstart);
|
||||
if (left <= 0)
|
||||
return 0; /* timeout */
|
||||
tv.tv_sec = left;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (LogLevel > 14)
|
||||
{
|
||||
sm_syslog(LOG_INFO, NOQID,
|
||||
"STARTTLS=%s, info: fds=%d/%d, err=%d",
|
||||
where, rfd, wfd, err);
|
||||
}
|
||||
|
||||
if (FD_SETSIZE > 0 &&
|
||||
((err == SSL_ERROR_WANT_READ && rfd >= FD_SETSIZE) ||
|
||||
(err == SSL_ERROR_WANT_WRITE && wfd >= FD_SETSIZE)))
|
||||
{
|
||||
if (LogLevel > 5)
|
||||
{
|
||||
sm_syslog(LOG_ERR, NOQID,
|
||||
"STARTTLS=%s, error: fd %d/%d too large",
|
||||
where, rfd, wfd);
|
||||
if (LogLevel > 8)
|
||||
tlslogerr(where);
|
||||
}
|
||||
errno = EINVAL;
|
||||
}
|
||||
else if (err == SSL_ERROR_WANT_READ)
|
||||
{
|
||||
fd_set ssl_maskr, ssl_maskx;
|
||||
|
||||
FD_ZERO(&ssl_maskr);
|
||||
FD_SET(rfd, &ssl_maskr);
|
||||
FD_ZERO(&ssl_maskx);
|
||||
FD_SET(rfd, &ssl_maskx);
|
||||
do
|
||||
{
|
||||
ret = select(rfd + 1, &ssl_maskr, NULL, &ssl_maskx,
|
||||
&tv);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
if (ret < 0 && errno > 0)
|
||||
ret = -errno;
|
||||
}
|
||||
else if (err == SSL_ERROR_WANT_WRITE)
|
||||
{
|
||||
fd_set ssl_maskw, ssl_maskx;
|
||||
|
||||
FD_ZERO(&ssl_maskw);
|
||||
FD_SET(wfd, &ssl_maskw);
|
||||
FD_ZERO(&ssl_maskx);
|
||||
FD_SET(rfd, &ssl_maskx);
|
||||
do
|
||||
{
|
||||
ret = select(wfd + 1, NULL, &ssl_maskw, &ssl_maskx,
|
||||
&tv);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
if (ret < 0 && errno > 0)
|
||||
ret = -errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* errno to force refill() etc to stop (see IS_IO_ERROR()) */
|
||||
#ifdef ETIMEDOUT
|
||||
# define SM_ERR_TIMEOUT ETIMEDOUT
|
||||
#else /* ETIMEDOUT */
|
||||
# define SM_ERR_TIMEOUT EIO
|
||||
#endif /* ETIMEDOUT */
|
||||
|
||||
/*
|
||||
** TLS_READ -- read secured information for the caller
|
||||
**
|
||||
@@ -561,38 +680,42 @@ tls_read(fp, buf, size)
|
||||
char *buf;
|
||||
size_t size;
|
||||
{
|
||||
int r;
|
||||
static int again = MAX_TLS_IOS;
|
||||
int r, rfd, wfd, try, ssl_err;
|
||||
struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
|
||||
time_t tlsstart;
|
||||
char *err;
|
||||
|
||||
try = 99;
|
||||
err = NULL;
|
||||
tlsstart = curtime();
|
||||
|
||||
retry:
|
||||
r = SSL_read(so->con, (char *) buf, size);
|
||||
|
||||
if (r > 0)
|
||||
{
|
||||
again = MAX_TLS_IOS;
|
||||
return r;
|
||||
}
|
||||
|
||||
err = NULL;
|
||||
switch (SSL_get_error(so->con, r))
|
||||
switch (ssl_err = SSL_get_error(so->con, r))
|
||||
{
|
||||
case SSL_ERROR_NONE:
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
again = MAX_TLS_IOS;
|
||||
break;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
if (--again <= 0)
|
||||
err = "read W BLOCK";
|
||||
else
|
||||
errno = EAGAIN;
|
||||
break;
|
||||
err = "read W BLOCK";
|
||||
/* FALLTHROUGH */
|
||||
case SSL_ERROR_WANT_READ:
|
||||
if (--again <= 0)
|
||||
if (err == NULL)
|
||||
err = "read R BLOCK";
|
||||
else
|
||||
errno = EAGAIN;
|
||||
rfd = SSL_get_rfd(so->con);
|
||||
wfd = SSL_get_wfd(so->con);
|
||||
try = tls_retry(so->con, rfd, wfd, tlsstart,
|
||||
TimeOuts.to_datablock, ssl_err, "read");
|
||||
if (try > 0)
|
||||
goto retry;
|
||||
errno = SM_ERR_TIMEOUT;
|
||||
break;
|
||||
|
||||
case SSL_ERROR_WANT_X509_LOOKUP:
|
||||
err = "write X BLOCK";
|
||||
break;
|
||||
@@ -625,15 +748,22 @@ tls_read(fp, buf, size)
|
||||
int save_errno;
|
||||
|
||||
save_errno = (errno == 0) ? EIO : errno;
|
||||
again = MAX_TLS_IOS;
|
||||
if (LogLevel > 9)
|
||||
if (try == 0 && save_errno == SM_ERR_TIMEOUT)
|
||||
{
|
||||
if (LogLevel > 7)
|
||||
sm_syslog(LOG_WARNING, NOQID,
|
||||
"STARTTLS: read error=timeout");
|
||||
}
|
||||
else if (LogLevel > 8)
|
||||
sm_syslog(LOG_WARNING, NOQID,
|
||||
"STARTTLS: read error=%s (%d), errno=%d, get_error=%s",
|
||||
"STARTTLS: read error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
|
||||
err, r, errno,
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
ERR_error_string(ERR_get_error(), NULL), try,
|
||||
ssl_err);
|
||||
else if (LogLevel > 7)
|
||||
sm_syslog(LOG_WARNING, NOQID,
|
||||
"STARTTLS: read error=%s (%d)", err, r);
|
||||
"STARTTLS: read error=%s (%d), retry=%d, ssl_err=%d",
|
||||
err, r, errno, try, ssl_err);
|
||||
errno = save_errno;
|
||||
}
|
||||
return r;
|
||||
@@ -660,36 +790,39 @@ tls_write(fp, buf, size)
|
||||
const char *buf;
|
||||
size_t size;
|
||||
{
|
||||
int r;
|
||||
static int again = MAX_TLS_IOS;
|
||||
int r, rfd, wfd, try, ssl_err;
|
||||
struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
|
||||
time_t tlsstart;
|
||||
char *err;
|
||||
|
||||
try = 99;
|
||||
err = NULL;
|
||||
tlsstart = curtime();
|
||||
|
||||
retry:
|
||||
r = SSL_write(so->con, (char *) buf, size);
|
||||
|
||||
if (r > 0)
|
||||
{
|
||||
again = MAX_TLS_IOS;
|
||||
return r;
|
||||
}
|
||||
err = NULL;
|
||||
switch (SSL_get_error(so->con, r))
|
||||
switch (ssl_err = SSL_get_error(so->con, r))
|
||||
{
|
||||
case SSL_ERROR_NONE:
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
again = MAX_TLS_IOS;
|
||||
break;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
if (--again <= 0)
|
||||
err = "write W BLOCK";
|
||||
else
|
||||
errno = EAGAIN;
|
||||
break;
|
||||
err = "read W BLOCK";
|
||||
/* FALLTHROUGH */
|
||||
case SSL_ERROR_WANT_READ:
|
||||
if (--again <= 0)
|
||||
err = "write R BLOCK";
|
||||
else
|
||||
errno = EAGAIN;
|
||||
if (err == NULL)
|
||||
err = "read R BLOCK";
|
||||
rfd = SSL_get_rfd(so->con);
|
||||
wfd = SSL_get_wfd(so->con);
|
||||
try = tls_retry(so->con, rfd, wfd, tlsstart,
|
||||
DATA_PROGRESS_TIMEOUT, ssl_err, "write");
|
||||
if (try > 0)
|
||||
goto retry;
|
||||
errno = SM_ERR_TIMEOUT;
|
||||
break;
|
||||
case SSL_ERROR_WANT_X509_LOOKUP:
|
||||
err = "write X BLOCK";
|
||||
@@ -722,15 +855,22 @@ tls_write(fp, buf, size)
|
||||
int save_errno;
|
||||
|
||||
save_errno = (errno == 0) ? EIO : errno;
|
||||
again = MAX_TLS_IOS;
|
||||
if (LogLevel > 9)
|
||||
if (try == 0 && save_errno == SM_ERR_TIMEOUT)
|
||||
{
|
||||
if (LogLevel > 7)
|
||||
sm_syslog(LOG_WARNING, NOQID,
|
||||
"STARTTLS: write error=timeout");
|
||||
}
|
||||
else if (LogLevel > 8)
|
||||
sm_syslog(LOG_WARNING, NOQID,
|
||||
"STARTTLS: write error=%s (%d), errno=%d, get_error=%s",
|
||||
"STARTTLS: write error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
|
||||
err, r, errno,
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
ERR_error_string(ERR_get_error(), NULL), try,
|
||||
ssl_err);
|
||||
else if (LogLevel > 7)
|
||||
sm_syslog(LOG_WARNING, NOQID,
|
||||
"STARTTLS: write error=%s (%d)", err, r);
|
||||
"STARTTLS: write error=%s (%d), errno=%d, retry=%d, ssl_err=%d",
|
||||
err, r, errno, try, ssl_err);
|
||||
errno = save_errno;
|
||||
}
|
||||
return r;
|
||||
|
||||
@@ -17,6 +17,8 @@ extern int sfdcsasl __P((SM_FILE_T **, SM_FILE_T **, sasl_conn_t *));
|
||||
#endif /* SASL */
|
||||
|
||||
# if STARTTLS
|
||||
extern int tls_retry __P((SSL *, int, int, time_t, int, int,
|
||||
const char *));
|
||||
extern int sfdctls __P((SM_FILE_T **, SM_FILE_T **, SSL *));
|
||||
# endif /* STARTTLS */
|
||||
|
||||
|
||||
@@ -504,7 +504,6 @@ smtp(nullserver, d_flags, e)
|
||||
#endif /* SASL */
|
||||
int r;
|
||||
#if STARTTLS
|
||||
int fdfl;
|
||||
int rfd, wfd;
|
||||
volatile bool tls_active = false;
|
||||
volatile bool smtps = bitnset(D_SMTPS, d_flags);
|
||||
@@ -1693,97 +1692,26 @@ smtp(nullserver, d_flags, e)
|
||||
# define SSL_ACC(s) SSL_accept(s)
|
||||
|
||||
tlsstart = curtime();
|
||||
fdfl = fcntl(rfd, F_GETFL);
|
||||
if (fdfl != -1)
|
||||
fcntl(rfd, F_SETFL, fdfl|O_NONBLOCK);
|
||||
ssl_retry:
|
||||
if ((r = SSL_ACC(srv_ssl)) <= 0)
|
||||
{
|
||||
int i;
|
||||
bool timedout;
|
||||
time_t left;
|
||||
time_t now = curtime();
|
||||
struct timeval tv;
|
||||
int i, ssl_err;
|
||||
|
||||
/* what to do in this case? */
|
||||
i = SSL_get_error(srv_ssl, r);
|
||||
ssl_err = SSL_get_error(srv_ssl, r);
|
||||
i = tls_retry(srv_ssl, rfd, wfd, tlsstart,
|
||||
TimeOuts.to_starttls, ssl_err,
|
||||
"server");
|
||||
if (i > 0)
|
||||
goto ssl_retry;
|
||||
|
||||
/*
|
||||
** For SSL_ERROR_WANT_{READ,WRITE}:
|
||||
** There is no SSL record available yet
|
||||
** or there is only a partial SSL record
|
||||
** removed from the network (socket) buffer
|
||||
** into the SSL buffer. The SSL_accept will
|
||||
** only succeed when a full SSL record is
|
||||
** available (assuming a "real" error
|
||||
** doesn't happen). To handle when a "real"
|
||||
** error does happen the select is set for
|
||||
** exceptions too.
|
||||
** The connection may be re-negotiated
|
||||
** during this time so both read and write
|
||||
** "want errors" need to be handled.
|
||||
** A select() exception loops back so that
|
||||
** a proper SSL error message can be gotten.
|
||||
*/
|
||||
|
||||
left = TimeOuts.to_starttls - (now - tlsstart);
|
||||
timedout = left <= 0;
|
||||
if (!timedout)
|
||||
{
|
||||
tv.tv_sec = left;
|
||||
tv.tv_usec = 0;
|
||||
}
|
||||
|
||||
if (!timedout && FD_SETSIZE > 0 &&
|
||||
(rfd >= FD_SETSIZE ||
|
||||
(i == SSL_ERROR_WANT_WRITE &&
|
||||
wfd >= FD_SETSIZE)))
|
||||
{
|
||||
if (LogLevel > 5)
|
||||
{
|
||||
sm_syslog(LOG_ERR, NOQID,
|
||||
"STARTTLS=server, error: fd %d/%d too large",
|
||||
rfd, wfd);
|
||||
if (LogLevel > 8)
|
||||
tlslogerr("server");
|
||||
}
|
||||
goto tlsfail;
|
||||
}
|
||||
|
||||
/* XXX what about SSL_pending() ? */
|
||||
if (!timedout && i == SSL_ERROR_WANT_READ)
|
||||
{
|
||||
fd_set ssl_maskr, ssl_maskx;
|
||||
|
||||
FD_ZERO(&ssl_maskr);
|
||||
FD_SET(rfd, &ssl_maskr);
|
||||
FD_ZERO(&ssl_maskx);
|
||||
FD_SET(rfd, &ssl_maskx);
|
||||
if (select(rfd + 1, &ssl_maskr, NULL,
|
||||
&ssl_maskx, &tv) > 0)
|
||||
goto ssl_retry;
|
||||
}
|
||||
if (!timedout && i == SSL_ERROR_WANT_WRITE)
|
||||
{
|
||||
fd_set ssl_maskw, ssl_maskx;
|
||||
|
||||
FD_ZERO(&ssl_maskw);
|
||||
FD_SET(wfd, &ssl_maskw);
|
||||
FD_ZERO(&ssl_maskx);
|
||||
FD_SET(rfd, &ssl_maskx);
|
||||
if (select(wfd + 1, NULL, &ssl_maskw,
|
||||
&ssl_maskx, &tv) > 0)
|
||||
goto ssl_retry;
|
||||
}
|
||||
if (LogLevel > 5)
|
||||
{
|
||||
sm_syslog(LOG_WARNING, NOQID,
|
||||
"STARTTLS=server, error: accept failed=%d, SSL_error=%d, timedout=%d, errno=%d",
|
||||
r, i, (int) timedout, errno);
|
||||
"STARTTLS=server, error: accept failed=%d, SSL_error=%d, errno=%d, retry=%d",
|
||||
r, ssl_err, errno, i);
|
||||
if (LogLevel > 8)
|
||||
tlslogerr("server");
|
||||
}
|
||||
tlsfail:
|
||||
tls_ok_srv = false;
|
||||
SSL_free(srv_ssl);
|
||||
srv_ssl = NULL;
|
||||
@@ -1798,9 +1726,6 @@ tlsfail:
|
||||
goto doquit;
|
||||
}
|
||||
|
||||
if (fdfl != -1)
|
||||
fcntl(rfd, F_SETFL, fdfl);
|
||||
|
||||
/* ignore return code for now, it's in {verify} */
|
||||
(void) tls_get_info(srv_ssl, true,
|
||||
CurSmtpClient,
|
||||
|
||||
@@ -18,7 +18,6 @@ SM_RCSID("@(#)$Id: usersmtp.c,v 8.463 2005/03/16 00:36:09 ca Exp $")
|
||||
#include <sysexits.h>
|
||||
|
||||
|
||||
static void datatimeout __P((int));
|
||||
static void esmtp_check __P((char *, bool, MAILER *, MCI *, ENVELOPE *));
|
||||
static void helo_options __P((char *, bool, MAILER *, MCI *, ENVELOPE *));
|
||||
static int smtprcptstat __P((ADDRESS *, MAILER *, MCI *, ENVELOPE *));
|
||||
@@ -2491,9 +2490,6 @@ smtprcptstat(to, m, mci, e)
|
||||
** exit status corresponding to DATA command.
|
||||
*/
|
||||
|
||||
static jmp_buf CtxDataTimeout;
|
||||
static SM_EVENT *volatile DataTimeout = NULL;
|
||||
|
||||
int
|
||||
smtpdata(m, mci, e, ctladdr, xstart)
|
||||
MAILER *m;
|
||||
@@ -2629,43 +2625,22 @@ smtpdata(m, mci, e, ctladdr, xstart)
|
||||
** factor. The main thing is that it should not be infinite.
|
||||
*/
|
||||
|
||||
if (setjmp(CtxDataTimeout) != 0)
|
||||
{
|
||||
mci->mci_errno = errno;
|
||||
mci->mci_state = MCIS_ERROR;
|
||||
mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
|
||||
|
||||
/*
|
||||
** If putbody() couldn't finish due to a timeout,
|
||||
** rewind it here in the timeout handler. See
|
||||
** comments at the end of putbody() for reasoning.
|
||||
*/
|
||||
|
||||
if (e->e_dfp != NULL)
|
||||
(void) bfrewind(e->e_dfp);
|
||||
|
||||
errno = mci->mci_errno;
|
||||
syserr("451 4.4.1 timeout writing message to %s", CurHostName);
|
||||
smtpquit(m, mci, e);
|
||||
return EX_TEMPFAIL;
|
||||
}
|
||||
|
||||
if (tTd(18, 101))
|
||||
{
|
||||
/* simulate a DATA timeout */
|
||||
timeout = 1;
|
||||
timeout = 10;
|
||||
}
|
||||
else
|
||||
timeout = DATA_PROGRESS_TIMEOUT;
|
||||
|
||||
DataTimeout = sm_setevent(timeout, datatimeout, 0);
|
||||
timeout = DATA_PROGRESS_TIMEOUT * 1000;
|
||||
sm_io_setinfo(mci->mci_out, SM_IO_WHAT_TIMEOUT, &timeout);
|
||||
|
||||
|
||||
/*
|
||||
** Output the actual message.
|
||||
*/
|
||||
|
||||
(*e->e_puthdr)(mci, e->e_header, e, M87F_OUTER);
|
||||
if (!(*e->e_puthdr)(mci, e->e_header, e, M87F_OUTER))
|
||||
goto writeerr;
|
||||
|
||||
if (tTd(18, 101))
|
||||
{
|
||||
@@ -2673,14 +2648,13 @@ smtpdata(m, mci, e, ctladdr, xstart)
|
||||
(void) sleep(2);
|
||||
}
|
||||
|
||||
(*e->e_putbody)(mci, e, NULL);
|
||||
if (!(*e->e_putbody)(mci, e, NULL))
|
||||
goto writeerr;
|
||||
|
||||
/*
|
||||
** Cleanup after sending message.
|
||||
*/
|
||||
|
||||
if (DataTimeout != NULL)
|
||||
sm_clrevent(DataTimeout);
|
||||
|
||||
#if PIPELINING
|
||||
}
|
||||
@@ -2720,7 +2694,9 @@ smtpdata(m, mci, e, ctladdr, xstart)
|
||||
}
|
||||
|
||||
/* terminate the message */
|
||||
(void) sm_io_fprintf(mci->mci_out, SM_TIME_DEFAULT, ".%s", m->m_eol);
|
||||
if (sm_io_fprintf(mci->mci_out, SM_TIME_DEFAULT, ".%s", m->m_eol) ==
|
||||
SM_IO_EOF)
|
||||
goto writeerr;
|
||||
if (TrafficLogFile != NULL)
|
||||
(void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT,
|
||||
"%05d >>> .\n", (int) CurrentPid);
|
||||
@@ -2771,51 +2747,27 @@ smtpdata(m, mci, e, ctladdr, xstart)
|
||||
shortenstring(SmtpReplyBuffer, 403));
|
||||
}
|
||||
return rstat;
|
||||
}
|
||||
|
||||
static void
|
||||
datatimeout(ignore)
|
||||
int ignore;
|
||||
{
|
||||
int save_errno = errno;
|
||||
writeerr:
|
||||
mci->mci_errno = errno;
|
||||
mci->mci_state = MCIS_ERROR;
|
||||
mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
|
||||
|
||||
/*
|
||||
** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
|
||||
** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
|
||||
** DOING.
|
||||
** If putbody() couldn't finish due to a timeout,
|
||||
** rewind it here in the timeout handler. See
|
||||
** comments at the end of putbody() for reasoning.
|
||||
*/
|
||||
|
||||
if (DataProgress)
|
||||
{
|
||||
time_t timeout;
|
||||
if (e->e_dfp != NULL)
|
||||
(void) bfrewind(e->e_dfp);
|
||||
|
||||
/* check back again later */
|
||||
if (tTd(18, 101))
|
||||
{
|
||||
/* simulate a DATA timeout */
|
||||
timeout = 1;
|
||||
}
|
||||
else
|
||||
timeout = DATA_PROGRESS_TIMEOUT;
|
||||
|
||||
/* reset the timeout */
|
||||
DataTimeout = sm_sigsafe_setevent(timeout, datatimeout, 0);
|
||||
DataProgress = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* event is done */
|
||||
DataTimeout = NULL;
|
||||
}
|
||||
|
||||
/* if no progress was made or problem resetting event, die now */
|
||||
if (DataTimeout == NULL)
|
||||
{
|
||||
errno = ETIMEDOUT;
|
||||
longjmp(CtxDataTimeout, 1);
|
||||
}
|
||||
errno = save_errno;
|
||||
errno = mci->mci_errno;
|
||||
syserr("451 4.4.1 timeout writing message to %s", CurHostName);
|
||||
smtpquit(m, mci, e);
|
||||
return EX_TEMPFAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
** SMTPGETSTAT -- get status code from DATA in LMTP
|
||||
**
|
||||
|
||||
+19
-49
@@ -456,6 +456,8 @@ xalloc(sz)
|
||||
{
|
||||
register char *p;
|
||||
|
||||
SM_REQUIRE(sz >= 0);
|
||||
|
||||
/* some systems can't handle size zero mallocs */
|
||||
if (sz <= 0)
|
||||
sz = 1;
|
||||
@@ -970,18 +972,18 @@ fixcrlf(line, stripnl)
|
||||
** mci -- the mailer connection information.
|
||||
**
|
||||
** Returns:
|
||||
** none
|
||||
** true iff line was written successfully
|
||||
**
|
||||
** Side Effects:
|
||||
** output of l to mci->mci_out.
|
||||
*/
|
||||
|
||||
void
|
||||
bool
|
||||
putline(l, mci)
|
||||
register char *l;
|
||||
register MCI *mci;
|
||||
{
|
||||
putxline(l, strlen(l), mci, PXLF_MAPFROM);
|
||||
return putxline(l, strlen(l), mci, PXLF_MAPFROM);
|
||||
}
|
||||
/*
|
||||
** PUTXLINE -- putline with flags bits.
|
||||
@@ -1000,13 +1002,13 @@ putline(l, mci)
|
||||
** PXLF_NOADDEOL -- don't add an EOL if one wasn't present.
|
||||
**
|
||||
** Returns:
|
||||
** none
|
||||
** true iff line was written successfully
|
||||
**
|
||||
** Side Effects:
|
||||
** output of l to mci->mci_out.
|
||||
*/
|
||||
|
||||
void
|
||||
bool
|
||||
putxline(l, len, mci, pxflags)
|
||||
register char *l;
|
||||
size_t len;
|
||||
@@ -1058,11 +1060,6 @@ putxline(l, len, mci, pxflags)
|
||||
if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT,
|
||||
'.') == SM_IO_EOF)
|
||||
dead = true;
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
}
|
||||
if (TrafficLogFile != NULL)
|
||||
(void) sm_io_putc(TrafficLogFile,
|
||||
SM_TIME_DEFAULT, '.');
|
||||
@@ -1075,11 +1072,6 @@ putxline(l, len, mci, pxflags)
|
||||
if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT,
|
||||
'>') == SM_IO_EOF)
|
||||
dead = true;
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
}
|
||||
if (TrafficLogFile != NULL)
|
||||
(void) sm_io_putc(TrafficLogFile,
|
||||
SM_TIME_DEFAULT,
|
||||
@@ -1091,16 +1083,11 @@ putxline(l, len, mci, pxflags)
|
||||
while (l < q)
|
||||
{
|
||||
if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT,
|
||||
(unsigned char) *l++) == SM_IO_EOF)
|
||||
(unsigned char) *l++) == SM_IO_EOF)
|
||||
{
|
||||
dead = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
}
|
||||
}
|
||||
if (dead)
|
||||
break;
|
||||
@@ -1116,11 +1103,6 @@ putxline(l, len, mci, pxflags)
|
||||
dead = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
}
|
||||
if (TrafficLogFile != NULL)
|
||||
{
|
||||
for (l = l_base; l < q; l++)
|
||||
@@ -1144,11 +1126,9 @@ putxline(l, len, mci, pxflags)
|
||||
{
|
||||
if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '.') ==
|
||||
SM_IO_EOF)
|
||||
break;
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
dead = true;
|
||||
break;
|
||||
}
|
||||
if (TrafficLogFile != NULL)
|
||||
(void) sm_io_putc(TrafficLogFile,
|
||||
@@ -1161,11 +1141,9 @@ putxline(l, len, mci, pxflags)
|
||||
{
|
||||
if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '>') ==
|
||||
SM_IO_EOF)
|
||||
break;
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
dead = true;
|
||||
break;
|
||||
}
|
||||
if (TrafficLogFile != NULL)
|
||||
(void) sm_io_putc(TrafficLogFile,
|
||||
@@ -1183,11 +1161,6 @@ putxline(l, len, mci, pxflags)
|
||||
dead = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
}
|
||||
}
|
||||
if (dead)
|
||||
break;
|
||||
@@ -1198,11 +1171,9 @@ putxline(l, len, mci, pxflags)
|
||||
if ((!bitset(PXLF_NOADDEOL, pxflags) || !noeol) &&
|
||||
sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT,
|
||||
mci->mci_mailer->m_eol) == SM_IO_EOF)
|
||||
break;
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
dead = true;
|
||||
break;
|
||||
}
|
||||
if (l < end && *l == '\n')
|
||||
{
|
||||
@@ -1211,11 +1182,9 @@ putxline(l, len, mci, pxflags)
|
||||
{
|
||||
if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT,
|
||||
' ') == SM_IO_EOF)
|
||||
break;
|
||||
else
|
||||
{
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
dead = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (TrafficLogFile != NULL)
|
||||
@@ -1224,10 +1193,10 @@ putxline(l, len, mci, pxflags)
|
||||
}
|
||||
}
|
||||
|
||||
/* record progress for DATA timeout */
|
||||
DataProgress = true;
|
||||
} while (l < end);
|
||||
return !dead;
|
||||
}
|
||||
|
||||
/*
|
||||
** XUNLINK -- unlink a file, doing logging as appropriate.
|
||||
**
|
||||
@@ -2433,6 +2402,7 @@ str2prt(s)
|
||||
*h++ = 'r';
|
||||
break;
|
||||
default:
|
||||
SM_ASSERT(l >= 2);
|
||||
(void) sm_snprintf(h, l, "%03o",
|
||||
(unsigned int)((unsigned char) c));
|
||||
|
||||
|
||||
@@ -384,17 +384,33 @@ For more information about these matters, see the files named COPYING.\n"));
|
||||
usage (1);
|
||||
}
|
||||
|
||||
static char **tv;
|
||||
static int tv_alloc;
|
||||
static int tv_used;
|
||||
|
||||
static int
|
||||
findtempname (char *tempname)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < tv_used; i++)
|
||||
if (strcmp (tv[i], tempname) == 0)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Return a name for temporary file COUNT. */
|
||||
|
||||
static char *
|
||||
maketempname (int count)
|
||||
{
|
||||
static char *tempbase = NULL;
|
||||
char *tempname;
|
||||
char tempsuffix[10];
|
||||
int fd;
|
||||
|
||||
if (!tempbase)
|
||||
{
|
||||
int fd;
|
||||
tempbase = concat (tempdir, "txidxXXXXXX");
|
||||
|
||||
fd = mkstemp (tempbase);
|
||||
@@ -403,7 +419,52 @@ maketempname (int count)
|
||||
}
|
||||
|
||||
sprintf (tempsuffix, ".%d", count);
|
||||
return concat (tempbase, tempsuffix);
|
||||
tempname = concat (tempbase, tempsuffix);
|
||||
/*
|
||||
* The open logic becomes a bit convoluted. If open(2) fails due to EEXIST,
|
||||
* it's likely because somebody attempted to race us, or because we have
|
||||
* already created this file.
|
||||
*/
|
||||
fd = open (tempname, O_CREAT|O_EXCL|O_WRONLY, 0600);
|
||||
if (fd == -1)
|
||||
{
|
||||
/*
|
||||
* If errno is not EEXIST, then open failed for some other reason, so
|
||||
* we should terminate. If errno == EEXIST AND we didn't create this
|
||||
* file, terminate. Otherwise, it's safe to say that errno == EEXIST
|
||||
* because we already created it, in this event, we can just return.
|
||||
*/
|
||||
if (errno != EEXIST ||
|
||||
(errno == EEXIST && findtempname (tempname) == 0))
|
||||
pfatal_with_name (tempname);
|
||||
return (tempname);
|
||||
}
|
||||
else if (fd > 0)
|
||||
{
|
||||
close (fd);
|
||||
}
|
||||
if (tv == NULL)
|
||||
{
|
||||
tv_alloc = 16;
|
||||
tv = calloc (tv_alloc, sizeof (char *));
|
||||
if (tv == NULL)
|
||||
{
|
||||
fprintf (stderr, "calloc failed\n");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
else if (tv_used == tv_alloc)
|
||||
{
|
||||
tv_alloc += 4;
|
||||
tv = realloc (tv, tv_alloc * sizeof (char *));
|
||||
if (tv == NULL)
|
||||
{
|
||||
fprintf (stderr, "realloc failed");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
tv[tv_used++] = strdup (tempname);
|
||||
return tempname;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loaded 100 of 346 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user