Compare commits

...
110 Commits
Author SHA1 Message Date
Colin Percival 7f9161735d Correct problems with locking, namei leakage, and symlink
creation in the NFS subsystem.

Approved by:	so (cperciva)
Submitted by:	re (hrs)
Errata:		FreeBSD-EN-07:01.nfs
2007-02-14 22:30:33 +00:00
Simon L. B. Nielsen 3adbb43be3 Fix jail rc.d script privilege escalation via symlink attack against
/var/log/console.log and mount points.

Security:	FreeBSD-SA-07:01.jail
Approved by:	so (simon)
2007-01-11 18:19:33 +00:00
Colin Percival bd60f04dc1 Correct a signedness bug which allowed members of the operator
group to read kernel memory.

Security:	FreeBSD-SA-06:25.kmem
Approved by:	so (cperciva)
2006-12-06 09:15:40 +00:00
Simon L. B. Nielsen cb71836b2a Correct multiple vulnerabilities in OpenSSH.
Security:	FreeBSD-SA-06:22.openssh
Approved by:	so (simon)
2006-09-30 19:58:07 +00:00
Colin Percival 12654543b1 Correct problem in the 2006-09-28 patch concerning the handling of
excessively large DH moduli.

Reported by:	Steve Kiernan (Juniper SIRT)
Security:	FreeBSD-SA-06:23.openssl
Approved by:	so (cperciva)
2006-09-29 13:46:41 +00:00
Colin Percival 952181054e 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.

Security:	FreeBSD-SA-06:23.openssl
Approved by:	so (cperciva)
2006-09-28 13:06:23 +00:00
Simon L. B. Nielsen 6de6f7e901 Correct multiple vulnerabilities in gzip(1).
Security:	FreeBSD-SA-06:21.gzip
Approved by:	so (simon)
2006-09-19 14:13:53 +00:00
Simon L. B. Nielsen 9e1260e620 Correct incorrect PKCS#1 v1.5 padding validation in crypto(3). [1]
Correct multiple denial-of-service vulnerabilities in BIND related to
SIG Query Processing and Excessive Recursive Queries. [2]

Security:	FreeBSD-SA-06:19.openssl [1]
Security:	FreeBSD-SA-06:20.bind [2]
Approved by:	so (simon)
2006-09-06 21:23:16 +00:00
Colin Percival 060a6d9a79 Correct buffer overflow in the handling of LCP options in ppp(4)
Security:	FreeBSD-SA-06:18.ppp
Approved by:	so (cperciva)
2006-08-23 22:06:40 +00:00
Colin Percival c7e7298883 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.

Security:	FreeBSD-SA-06:17.sendmail
Approved by:	so (cperciva)
2006-06-14 16:01:20 +00:00
Colin Percival 7f7ea37f6f Enable inadvertantly disabled "securenet" access controls in ypserv. [1]
Correct a bug in the handling of backslash characters in smbfs which can
allow an attacker to escape from a chroot(2). [2]

Approved by:	so (cperciva)
Security:	FreeBSD-SA-06:15.ypserv [1]
Security:	FreeBSD-SA-06:16.smbfs [2]
2006-05-31 22:33:41 +00:00
Colin Percival 0146a3ffc6 MFC: Correct a local information leakage bug affecting AMD FPUs.
Security:	FreeBSD-SA-06:14.fpu
Approved by:	so (cperciva)
2006-04-19 07:03:14 +00:00
Colin Percival 5aad434d14 Add missing code needed for the detection of IPSec packet replays. [1]
Correctly identify the user running opiepasswd(1) when the login name
differs from the account name. [2]

Modify timeout handling logic in sendmail(8) to correct a reported
signal handling race condition. [3]

Approved by:	so (cperciva)
Security:	FreeBSD-SA-06:11.ipsec [1]
Security:	FreeBSD-SA-06:12.opie [2]
Security:	FreeBSD-SA-06:13.sendmail [3]
2006-03-22 16:03:25 +00:00
Simon L. B. Nielsen 968aa2f3c6 Correct a remote kernel panic when processing zero-length RPC records
via TCP. [06:10]

Security:	FreeBSD-SA-06:10.nfs
Approved by:	so (cperciva)
2006-03-01 14:18:46 +00:00
Colin Percival f57226bf4c Make sure buffers in if_bridge are fully initialized before copying
them to userland. [1]

MFC rev. 1.37 of sys/net80211/ieee80211_ioctl.c: Correct a logic error
which could allow too much data to be copied into userland. [2]

MFC rev. 1.16 of sys/contrib/pf/net/pf_norm.c: Correct an error in pf
handling of IP packet fragments which could result in a kernel panic.
[3]

Security:	FreeBSD-SA-06:06.kmem [1] [2]
Security:	FreeBSD-SA-06:07.pf [3]
Approved by:	so (cperciva)
2006-01-25 10:01:26 +00:00
Colin Percival 10753525fc Correct a buffer overflow when scanning for 802.11 wireless networks.
Security:	FreeBSD-SA-06:05.80211
Approved by:	so (cperciva)
2006-01-18 09:03:36 +00:00
Colin Percival bc57f3a142 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]

Security:	FreeBSD-SA-06:01.texindex
Security:	FreeBSD-SA-06:02.ee
Security:	FreeBSD-SA-06:03.cpio
Security:	FreeBSD-SA-06:04.ipfw
Approved by:	so (cperciva)
2006-01-11 08:03:18 +00:00
Xin LI d533a1a065 Merge from RELENG_6 of src/sys/nfsclient/nfs_vnops.c rev 1.258.2.1:
MFC 1.260 (by ps): Fixed a panic that can happen when nfs_lookup() hits
  an error.

Work done by:	Mohan Srinivasan
Approved by:	re (scottl), so (cperciva)
Erratum:	FreeBSD-EN-05:04.nfs
2005-12-19 10:58:57 +00:00
Ken Smith 3d215489fe MFC v1.7
> date: 2005/11/03 00:23:13;  author: kensmith;  state: Exp;  lines: +1 -6
> It had been noticed disc2 was overflowing earlier but committing the
> fix slipped through a crack.  Remove the apache and php packages under
> the assumption someone installing a Web server has network access and
> doesn't *need* the packages on disc2.

Approved by:	re (scottl)
2005-11-03 00:35:25 +00:00
Scott Long da2cd746e7 Welcome to 6.0-RELEASE.
Approved by: re
2005-11-02 02:00:46 +00:00
Scott Long 52b835344d MFC: FreeBSD 6.0
Approved by: re
2005-11-02 00:01:08 +00:00
Scott Long ffdda74401 Grrr, Nov = 11
Approved by:	re
2005-11-01 23:43:49 +00:00
Scott Long d78cc8da72 Note that 6.0-RELEASE is about to happen.
Approved by:	re
2005-11-01 23:40:38 +00:00
Scott Long 957f5ead91 MFC: Tell gcc about FreeBSD 6.
Approved by: re
2005-11-01 23:10:08 +00:00
SUZUKI Shinsuke c0a7104606 MFC 1.59
statically configured IPv6 address is properly added/deleted now

Approved by: re(scottl)
2005-11-01 22:42:05 +00:00
John Baldwin 3d888e5914 MF6: Add a deprecation warning.
Approved by:	re (scottl)
2005-10-31 20:17:14 +00:00
Yoshihiro Takahashi 35738380af MFC: Enable beastie.4th.
Approved by:	re (scottl)
2005-10-30 16:36:00 +00:00
Scott Long e658bb489d MFC
Approved by: re
2005-10-30 14:40:40 +00:00
cvs2svn 21f0307211 This commit was manufactured by cvs2svn to create branch 'RELENG_6_0'. 2005-10-30 05:41:44 +00:00
Kirill Ponomarev 887d355270 MFC: perform.c:1.14 test-pkg_version.sh:1.6
date: 2005/10/10 12:35:30;  author: krion;  state: Exp;  lines: +9 -4
  * pkg_version(1) exits if INDEX files is not found and -I is not
    specified.  The result is that the package will be listed with a '?'
    as if it was not found within the INDEX file, so fix this behaviour.
  * Remove trailing spaces.

  PR:             bin/87136
  Submitted by:   Sean Farley <sean-freebsd at farley dot org>

Approved by:	re
2005-10-29 15:49:01 +00:00
Kirill Ponomarev 6636f48868 MFC: delete/main.c:1.27 info/main.c:1.48
Fix pkg_info(1) and pkg_delete(1) to handle properly packages which
  names start with a digit.

  PR:             bin/76858
  Submitted by:   Matthew D. Fuller <fullermd@over-yonder dot net>

Approved by:	re
2005-10-29 15:27:12 +00:00
Scott Long 66308c6270 MFC rev 1.113
Submitted by delphij
Approved by: re
2005-10-29 15:13:07 +00:00
Scott Long 087ac34ec2 Sync RELENG_6_0 with all of the FFS fixes from Tor.
Submitted by:	tegge
Approved by:	re
2005-10-29 07:00:45 +00:00
Tai-hwa Liang ede84755f3 MFC: (1.16) Fixing a name collision in module declaration by renaming
"firewire" to "if_firewire."  According to the PR originator and Cai's
testing result, this bug prevents a RELENG_6 GENERIC kernel from loading
if_fwip.ko and will panic the kernel if users compile "device fwip" into
their GENERIC kernel.

Approved by:	re (scottl)
2005-10-28 22:52:31 +00:00
Pawel Jakub Dawidek c5e3056011 Fix possible live-lock under heavy load where we can't allocate more
memory for request.
I was sure graid3 should handle such situations well, but green@ reported
it is not and we want to fix it before 6.0.

Submitted by:	green
Approved by:	re (scottl)
2005-10-28 20:27:53 +00:00
John Baldwin abf809c118 MF6: Sync with HEAD updating examples for 6.x.
Approved by:	re (scottl)
2005-10-28 19:24:41 +00:00
John Baldwin 96fb3ac3fc MF6: Add DEFAULTS files for amd64, i386, and pc98.
Approved by:	re (scottl)
2005-10-28 19:22:41 +00:00
John Baldwin 17fc0cbcdb MF6: config -V and support for DEFAULTS.
Approved by:	re (scottl)
2005-10-28 19:20:53 +00:00
John Baldwin 01b1c3795a MF6: Add COMPAT_FREEBSD5.
Approved by:	re (scottl)
2005-10-28 19:20:00 +00:00
Martin Cracauer 95dfc0a1cc Fix this:
kern/87959      cracauer        ext2fs: no cp(1) possible, mmap returns EINVAL

ext2fs was missing vnode_create_vobject.

(Reisefs probably has the same problem but I want to get this in quick
for 6-release)

releng-6 branches commits approved by Scott Long.

Approved by: re
2005-10-28 18:44:26 +00:00
Scott Long 5e4677ca87 MFC: Fix regression in Dell PERC/ROMB systems.
Approved by: re
2005-10-28 16:31:34 +00:00
cvs2svn 218f2e0ec5 This commit was manufactured by cvs2svn to create branch 'RELENG_6_0'. 2005-10-28 15:30:53 +00:00
SUZUKI Shinsuke 527ef1908a MFC Rev 1.60
perform NUD on an IPv6-aware point-to-point interface

Approved by: re(scottl)
2005-10-28 14:38:56 +00:00
Ade Lovett b7217bb7d0 MFC:
Specifically panic() in the case where pmap_insert_entry() fails to
get a new pv under high system load where the available pv entries
have been exhausted before the pagedaemon has a chance to wake up
to reclaim some.

Approved by:	re (scottl)
2005-10-28 06:49:49 +00:00
Xin LI 628f5eef34 MFRELENG_6 1.416.2.4: Some changes to reflect 6.0-STABLE/RELEASE.
Approved by:	re (scottl)
2005-10-28 02:59:51 +00:00
Peter Grehan e6d8fd44a4 MF RELENG_6 r1.34.2.1
> The BCM5401 dspcode load on media changes also applies
  > to the 100/1000 BCM5400 phy. This fixes the problem with
  > the GEM port not syncing up on Sawtooth G4's.
  >
  > Obtained from:  NetBSD
  > Reported by:    Ben Rosengart <ben + freebsd org at narcissus net>

Approved by:    re (scottl)
2005-10-28 01:07:54 +00:00
Stephan Uphoff 5f37fe5bda MFC vfs_cluster.c Revision 1.168
Only set B_RAM (Read ahead mark) on an incore buffers if we can lock it.
This fixes a race condition caused by the unlocked write access to the
b_flags field.

Approved by:    re (scottl)
2005-10-28 01:03:26 +00:00
Ken Smith 18d2ca12a1 MFC of Rev. 1.6.2.1:
> Temporary hack to get the hme network interface on Sun E250 servers to
> work.  The code comment describes the issue, basically an as yet not
> totally understood interrupt routing problem.  This hack is being done
> to RELENG_6 so that the hme interface works on E250's for the release,
> but is not being done in HEAD so more work on the interrupt routing
> issue can be done.
>
> Requested by:	marius

Approved by:	re (scottl)
2005-10-27 20:58:50 +00:00
Joel Dahl 8cb3b5729f MFC r1.59:
Add support for ATI IXP[234]00.

Requested by:	delphij
Approved by:	re (scottl)
2005-10-27 20:47:03 +00:00
Joel Dahl e8d38e80bb MFC r1.1334:
snd_ess needs snd_sbc, so add a note about that.

Requested by:	delphij
Approved by:	re (scottl)
2005-10-27 20:39:37 +00:00
Andrew Thompson 905dbf6afa MFC if_bridge r1.30
> If we have been called from ether_ifdetach() then do not try and clear the
> promisc flag from the member interface, this is a no-op anyway since the
> interface is disappearing. The driver may have already released
> its resources such as miibus and this is likely to panic the kernel.

Approved by:    re (scottl)
2005-10-27 19:43:07 +00:00
Scott Long 71c60dd1de MFC: Sync the mpt driver to pick up license refinement and INVARIANTS error.
Approved by: re
2005-10-27 18:58:37 +00:00
Murray Stokely d26e5dee60 MFC: Use packages-6-release directory for packages, as appropriate.
Approved by:	re
2005-10-27 18:38:48 +00:00
Gleb Smirnoff 020ec29a79 MFC:
- Fix leak of struct nlminfo on process exit.
  - Fix malloc type collision, that made the above problem
    difficult to understand.

  Reported by:	Vladimir Sharun <sharun ukr.net>

Approved by:	re (scottl)
2005-10-27 18:35:19 +00:00
Xin LI 5dd20217a6 MFRELENG_6 1.5.2.3: Update to sync up with latest RELENG_6 documentation.
Approved by:	re (scottl)
2005-10-27 17:54:31 +00:00
Bill Paul d2854f8b92 MFC: add the driver_ndis support files to the wpa_supplicant distribution
for -D ndis support with the NDISulator

Approved by:	re
2005-10-27 17:15:47 +00:00
Bill Paul 0dbb2e0f34 MFC: synchronize the NDISulator with the head and RELENG_5 branches,
add -D ndis support to wpa_supplicant

Approved by:	re
2005-10-27 17:08:57 +00:00
Bill Paul fd47f7362f MFC: add 1 microsecond delay to pci_add_children() bus enumeration loop
Approved by:	re
2005-10-27 16:44:06 +00:00
Søren Schmidt b75aec04ff MFC:
Enclose the delayed attach in Giant so we dont loose the race with other
	drivers trying to attach ATA devices like pccard.
	Dont clear the delayed flag before we are acutally finished.

Approved by: re@ (scottl)
2005-10-27 16:41:39 +00:00
Jung-uk Kim 99c293401c MFRELENG_6: Fix 'grep -Fw' for encodings other than UTF-8 (RH bug #161700).
PR:		87969
Approved by:	re (scottl)
Obtained from:	Fedora (Tim Waugh)
2005-10-27 16:29:02 +00:00
SUZUKI Shinsuke fe1746fb90 MFC rev 1.34
fixed a kernel crash when IPv6 PIM-SM routing is enabled and a PIM register message is received

Approved by: re(scottl)
2005-10-27 14:04:03 +00:00
Peter Wemm 2e2bc37c17 MFC: 1.2: don't set segment registers yet.
Approved by:  re
2005-10-26 22:07:03 +00:00
Christian S.J. Peron 3b30fd6060 MFC notes about ucred based rules and debug.mpsafenet requirements.
Approved by:	re (scottl)
2005-10-26 21:58:42 +00:00
Ariff Abdullah 22ff0d37be Virtual channel default speed should be based on soundcard
capabilities. This solve various mysterious slowdown especially
for fixed-rate ac97 soundcards.

Approved by:	re (scottl), netchild (mentor)
Reviewed by:	andreas
2005-10-26 21:18:41 +00:00
Ariff Abdullah f66ce35e97 Rearrange sound unregister procedure to detect mixer busy
state and destroy it before anything else. This solve panic issue
during sound module unloading if the sound / mixer device being
held by external processes.

Approved by:	re (scottl), netchild (mentor)
Reviewed by:	andreas
2005-10-26 21:18:09 +00:00
Ariff Abdullah ff7bd1bebf Track every mixer device closing for proper refcount calculation.
This solve device busy and panic issues during sound module
unloading.

Approved by:	re (scottl), netchild (mentor)
Reviewed by:	andreas
2005-10-26 21:17:40 +00:00
Jung-uk Kim 3aafcdb5aa MFRELENG_6: Fix a longstanding buglet in bz-prefixed grep(1).
PR:		gnu/72200
Approved by:	re
2005-10-26 21:15:51 +00:00
Xin LI 0fcef6909b MFRELENG_6 (by alc) changesets that addresses several race conditions that
can cause a kernel compiled with ZERO_COPY_SOCKETS to panic under certain
circumstances:
	sys/kern/uipc_cow.c:	1.24 - 1.26
	sys/vm/vm_object.c:	1.351

Approved by:	re (scottl)
2005-10-26 20:22:00 +00:00
Pawel Jakub Dawidek b79874b1ac Call if_clone_detach() after vlan_clone_destroy() loop, as if_clone_detach()
is freeing ifc_units field, which is used in
vlan_clone_destroy()->ifc_free_unit().

This fixes panic: ifc_free_unit: bit is already cleared

The fix introduces a small race in that a new interface could be created
between the vlan_clone_destroy() loop and the call to if_clone_detach().
The race is probably too hard to trigger to be worry about it.

This is not an MFC, because better fix was committed to HEAD.
We decided to use this fix, as it is a low-risk fix, which fits just fine
for 6.0 at this stage.

Discussed with:	brooks, thompsa
Approved by:	re (scottl)
2005-10-26 19:57:04 +00:00
Peter Wemm 9a8c805f4e MFC: Fix fencepost error that made libkvm fail to read crashdumps.
Approved by: re
2005-10-26 00:07:25 +00:00
Nate Lawson ae4c6d68b3 MFC rev 1.11.2.1: set to 100% on boot
Approved by:	re (scottl)
2005-10-25 20:53:22 +00:00
Nate Lawson 75609203af MFC rev 1.214.2.1: Don't disable PCI link devices even when they're !enabled
Approved by:	re (scottl)
2005-10-25 20:51:58 +00:00
Kris Kennaway 9792749811 MFC r1.650:
Default to mpsafevfs=1 on sparc64

Approved by:    re (scottl)
2005-10-25 20:43:25 +00:00
Kris Kennaway a42a37b2b1 MFC 1.73:
Reflect mpsafety of the underlying filesystem in the nullfs image.

Approved by:    re (scottl)
2005-10-25 20:33:59 +00:00
John Baldwin a09f52b5b4 MF6: Don't panic if a spin lock is initialized that isn't in our static
order list.  Just warn about it instead.

Approved by:	re (scottl)
2005-10-25 20:17:11 +00:00
John Baldwin 12abcec092 MF6: Rename 'traceall' to 'alltrace' and add a 'bt' alias for 'trace'.
Approved by:	re (scottl)
2005-10-25 20:11:58 +00:00
Nate Lawson c46ee19798 MFC: powerd.c rev 1.6.2.3, powerd.8 rev 1.5.2.1
Approved by:	re (scottl)
2005-10-25 20:07:51 +00:00
Warner Losh a21bfc1306 MFC: 1.26
Approved by: re@ (scottl)
2005-10-25 20:07:47 +00:00
cvs2svn cfb0cdce75 This commit was manufactured by cvs2svn to create branch 'RELENG_6_0'. 2005-10-24 05:35:42 +00:00
Warner Losh 3e0b8fb346 MF RELENG_6: (1.2) reduce the memory page size to 1k. 2005-10-23 18:23:27 +00:00
Xin LI 1d64cdbb8b MFR6: Remove the "6.x is slow" note to reflect reality.
Approved by:	re (scottl)
2005-10-23 03:36:03 +00:00
Andrew Thompson 92ad66505c MFC ng_ether support for if_bridge and cleanup of bridge hooks.
bridgestp.c; r1.8
 if_bridge.c; r1.25, 1.27
 if_bridgevar.h; r1.5
 if_ethersubr.c; r1.201, 1.202, 1.206
 ng_ether.c; r1.52 - 1.54

Approved by:    re (scottl)
2005-10-23 02:37:28 +00:00
Gleb Smirnoff 38104e8617 Sync with HEAD. Revisions merged:
- rev. 1.76. Removed FreeBSD 4.x code.
  - rev. 1.77, 1.79. Together with rev. 1.71 (already merged) this
    fixes problems when some code is executed in driver when
    em_process_receive_interrupts() drops lock. This can occur
    at runtime, when polling(4) mode is changed to interrupt driver
    or vise versa, but more likely this can happen when administrator
    issues some ifconfig commands.
  - rev. 1.78. In em_process_receive_interrupts(), call bus_dmamap_sync()
    for the descriptors set each time we modify one descriptor, instead
    of doing it only at the function exit.
  - rev. 1.80. Loop in em_intr() until interrupt cause register is clear,
    don't mask overrun interrupt.
  - rev. 1.81. Several locking and other fixes.

See particular revision logs for more detailed information.

Approved by:	re
2005-10-22 22:07:20 +00:00
Yaroslav Tykhiy 34ffcac9fd MFC notes on ifconfig(8): -tunnel, -vlandev.
Approved by:    re (hrs)
2005-10-21 16:01:46 +00:00
SUZUKI Shinsuke a851385207 MFC 1.56 (added a missing unlock)
Approved by: re(scottl)
2005-10-21 11:10:46 +00:00
Stephan Uphoff fdd3ac39c8 MFC vm_machdep.c 1.261-1.263
Rev: 1.261

  Ensure that a thread stays on same CPU when calculating per CPU
  TLB shootdown requirements. Otherwise a CPU may not get the needed
  TLB invalidation.

  The PTE valid and access flags can not be used here to avoid TLB
  shootdowns unless sf->cpumask == all_cpus.
  ( Otherwise some CPUs may still hold an even older entry in the TLB)
  Since sf_buf_alloc mappings are normally always used this is
  also not really useful and presetting accessed and modified
  allows the CPU to speculatively load the entry into the TLB.

  Both bugs can cause random data corruption.

Rev: 1.262

  Restore optimizations to reduce TLB shootdowns.
  Alan Cox pointed out that they are really useful for
  sendfile().

Rev: 1.263
  Restore the UP optimization to reduce the number of TLB
  invalidations.  The
  previous revision only restored the MP optimization.

  Describe the optimization strategy for TLB invalidations in a comment.

Approved by:	re@ (scottl)
2005-10-20 01:03:23 +00:00
Poul-Henning Kamp 2ca115c41b MFC:
Use correct criteria to determine if dirent can be removed
        right away.

Approved by:	re@ (scottl)
2005-10-19 21:26:02 +00:00
Andrew Thompson 1101e1b905 MFC: if_bridge.c r1.26, if_ethersubr.c r1.205
>   Use bridge_ifdetach() to notify the bridge that a member has been detached.
>   The bridge can then remove it from its interface list and not try to send
>   out via a dead pointer.

Approved by:	re (scottl)
2005-10-19 20:46:16 +00:00
Don Lewis 063395a5a5 MFC ufs_lookup.c 1.78 and 1.79.
Original commit messages:
  Modified files:
    sys/ufs/ufs          ufs_lookup.c
  Log:
  Close a race in the ufs_lookup() code that handles the ISDOTDOT
  case by saving the value of dp->i_ino before unlocking the vnode
  for the current directory and passing the saved value to VFS_VGET().

  Without this change, another thread can overwrite dp->i_ino after
  the current directory is unlocked, causing  ufs_lookup() to lock
  and return the wrong vnode in place of the vnode for its parent
  directory.  A deadlock can occur if dp->i_ino was changed to a
  subdirectory of the current directory because the root to leaf vnode
  lock ordering will be violated.  A vnode lock can be leaked if
  dp->i_ino was changed to point to the current directory, which
  causes the current vnode lock for the current directory to be
  recursed, which confuses lookup() into calling vrele() when it
  should be calling vput().

  The probability of this bug being triggered seems to be quite low
  unless the sysctl variable debug.vfscache is set to 0.

  Reviewed by:    jhb
  MFC after:      2 weeks

  Revision  Changes    Path
  1.78      +3 -1      src/sys/ufs/ufs/ufs_lookup.c

  Modified files:
    sys/ufs/ufs          ufs_lookup.c
  Log:
  Correct the type of the temporary variable used by ufs_lookup.c:1.78
  to fix the race condition in the ufs_lookup() ISDOTDOT code.

  Noticed by:     bde
  MFC after:      12 days

  Revision  Changes    Path
  1.79      +1 -1      src/sys/ufs/ufs/ufs_lookup.c

Approved by:	re (scottl)
2005-10-19 20:31:45 +00:00
Don Lewis 1b3663cbaa MFC nwfs_lookup.c 1.42
Original commit message:
  Modified files:
    sys/fs/nwfs          nwfs_vnops.c
  Log:
  Update nwfs_lookup() to match the current cache_lookup() API.
  cache_lookup() has returned a ref'ed and locked vnode since
  vfs_cache.c:1.96, dated Tue Mar 29 12:59:06 2005 UTC.  This change
  is similar to the change made to smbfs_lookup() in smbfs_vnops.c:1.58.

  Tested by:      "Antony Mawer" ant AT mawer.org
  MFC after:      2 weeks

  Revision  Changes    Path
  1.42      +11 -26    src/sys/fs/nwfs/nwfs_vnops.c

Approved by:	re (scottl)
2005-10-19 20:20:42 +00:00
John Baldwin ede7fe23cb MF6: Update critical(9) with recently reality.
Approved by:	re (kensmith)
2005-10-17 18:52:50 +00:00
Poul-Henning Kamp daab09ff7d MF6: nanobsd.sh fixes
Approved by:	re@ (scottl)
2005-10-17 07:58:05 +00:00
Warner Losh 385a4b0a41 MF-RELENG_6: rtl8029 and qemu fixes.
>   1.2       +6 -5      src/sys/dev/ed/if_ed_rtl80x9.c
>   1.48      +9 -2      src/sys/dev/ed/if_ed_pci.c
Approved by: re@ (kensmith)
2005-10-17 02:25:26 +00:00
Kris Kennaway 191bfb282f MFC r1.20:
Add a default value for VM_BCACHE_SIZE_MAX of 400MB.  This is copied from
amd64, and is a factor of 3 less than the value previously auto-sized on
a 12GB machine, which would cause an overflow in calculations involving the
maxbcache int, causing bufinit() to loop forever at boot.

Approved by:	re (kensmith)
2005-10-17 00:19:30 +00:00
Kris Kennaway 5a02e2d3f6 MFC r1.72: Partially revert r1.67 which changed maxbcache and maxswzone
from int to long without updating the <sys/buf.h> version.  This broke the
corresponding tunables on sparc.

Approved by:    re (kensmith)
2005-10-17 00:17:22 +00:00
Robert Watson 3d0f46b8df Merge in.c:1.89,1.90 from HEAD to RELENG_6_0:
Acquire Giant conditionally in in_addmulti() and in_delmulti() based on
  whether the interface being accessed is IFF_NEEDSGIANT or not.  This
  avoids lock order reversals when calling into the interface ioctl
  handler, which could potentially lead to deadlock.

  The long term solution is to eliminate non-MPSAFE network drivers.

  Discussed with: jhb

  Unlock Giant symmetrically with respect to lock acquire order as that's
  generally nicer.

  Spotted by:     johan

Approved by:    re (kensmith)
2005-10-16 17:12:18 +00:00
Robert Watson 741347619e Merge ufs_extattr.c:1.82 from RELENG_6 to RELENG_6_0:
When performing a VOP_LOOKUP() as part of UFS1 extended attribute
  auto-start, set cnp.cn_lkflags to LK_EXCLUSIVE.  This flag must now
  be set so that lockmgr knows what kind of lock to acquire, and it
  will panic if not specified.  This resulted in a panic when using
  extended attributes on UFS1 as of locking work present in the 6.x
  branch.

  Reported by:    lofi

Approved by:    re (kensmith)
2005-10-16 16:52:14 +00:00
Hiroki Sato 07d746f573 Update version numbers for upcoming 6.0-RELEASE.
Approved by:	re (implicitly)
2005-10-16 14:07:44 +00:00
Hiroki Sato 32dc657349 Update various version numbers and entities
for upcoming 6.0-RELEASE.

Approved by:	re (implicitly)
2005-10-16 08:28:10 +00:00
Hiroki Sato 8051874cd7 Use RELENG_6_0 for standard-supfile.
Approved by:	re (implicitly)
2005-10-16 08:15:29 +00:00
Xin LI a8e6180850 MFR6 Release Notes Language Improvements
Approved by:	re (hrs)
2005-10-16 07:35:40 +00:00
Gleb Smirnoff 8b7a63f7e1 Merge the 'kldstat -q' functionality, that is required for proper
operation of the /etc/rc.d/pfsync script, that was merged before
the RELENG_6_0 has been forked.

Approved by:	re (kensmith)
2005-10-14 14:38:56 +00:00
Scott Long 75c7560dfb MFC: Sync the driver with RELENG_6 to pick up critical atapi-cd and ata-raid
fixes, as well as ATI support.

Submitted by:	sos
Approved by:	re
2005-10-14 09:34:50 +00:00
Xin LI f2adbc2073 MFC (by gibbs):
| Correct bug that caused the completed "recovery" scb to have its
| timer reset rather than the timer of an SCB still pending on the
| controller after recovery completed.  This should correct timeout
| loops seen in the field.
|
| Revision  Changes    Path
| 1.22      +2 -1      src/sys/dev/aic7xxx/aic79xx_osm.c
| 1.43      +2 -1      src/sys/dev/aic7xxx/aic7xxx_osm.c

Approved by:	re (kensmith)
2005-10-14 02:19:02 +00:00
Xin LI 4c096043ce MFRELENG_6 Simplified Chinese translation of Release Documentations
Approved by:	re (hrs)
2005-10-13 17:32:39 +00:00
David Xu e9c4c22b54 MFC revision 1.24:
> The pthread_attr_set_createsuspend_np was broken, fix it by
 > replacing THR_FLAGS_SUSPENDED with THR_FLAGS_NEED_SUSPEND.

Approved by: re (scottl)
2005-10-11 23:24:25 +00:00
Colin Percival 0f88086d1a Correct a man-in-the-middle SSL version rollback vulnerability.
Security:       FreeBSD-SA-05:21.openssl
Approved by:    re@ (scottl)
2005-10-11 11:53:03 +00:00
cvs2svn bdc8787cc2 This commit was manufactured by cvs2svn to create branch 'RELENG_6_0'. 2005-10-09 17:28:13 +00:00
cvs2svn 968d7a6a6d This commit was manufactured by cvs2svn to create branch 'RELENG_6_0'. 2005-10-07 14:00:07 +00:00
cvs2svn 4f345d81ac This commit was manufactured by cvs2svn to create branch 'RELENG_6_0'. 2005-07-11 04:14:44 +00:00
346 changed files with 9813 additions and 23130 deletions

No files matched your search

+1 -1
View File
@@ -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)
+113 -23
View File
@@ -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.
+2 -2
View File
@@ -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;
+28 -21
View File
@@ -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);
}
-705
View File
@@ -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.
-6
View File
@@ -1,6 +0,0 @@
Authors of GNU cpio
Phil Nelson <[email protected]>
David MacKenzie <[email protected]>
John Oleynick <[email protected]>
Sergey Poznyakoff <[email protected]>
-231
View File
@@ -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.
-14
View File
@@ -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]>
-356
View File
@@ -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
&#8216;/&#8217;).<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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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;
+2 -2
View File
@@ -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. */
-54
View File
@@ -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 */
-25
View File
@@ -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;
-31
View File
@@ -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;
-440
View File
@@ -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 */
-309
View File
@@ -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 */
-43
View File
@@ -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
-156
View File
@@ -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
-926
View File
@@ -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
-24
View File
@@ -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;
-31
View File
@@ -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;
-43
View File
@@ -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
-79
View File
@@ -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;
}
-121
View File
@@ -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
-47
View File
@@ -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_ */
-306
View File
@@ -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
-66
View File
@@ -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 */
-32
View File
@@ -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 */
-27
View File
@@ -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;
-20
View File
@@ -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;
-83
View File
@@ -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;
}
-35
View File
@@ -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
-174
View File
@@ -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 */
-227
View File
@@ -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 */
-131
View File
@@ -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 */
-68
View File
@@ -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 */
-4
View File
@@ -1,4 +0,0 @@
#define LOCALEDIR "/usr/local/share/locale"
#ifndef DEFAULT_RMT_COMMAND
# define DEFAULT_RMT_COMMAND "/usr/local/libexec/rmt"
#endif
-29
View File
@@ -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;
}
-36
View File
@@ -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
-99
View File
@@ -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))
-740
View File
@@ -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 */
}
}
-82
View File
@@ -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;
}
}
-25
View File
@@ -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);
-19
View File
@@ -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"
-25
View File
@@ -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);
-123
View File
@@ -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;
}
-26
View File
@@ -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
-47
View File
@@ -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 */
-30
View File
@@ -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;
}
-28
View File
@@ -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
-39
View File
@@ -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;
}
-55
View File
@@ -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
-30
View File
@@ -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
-48
View File
@@ -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
-524
View File
@@ -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
-137
View File
@@ -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 */
-45
View File
@@ -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 ();
}
-79
View File
@@ -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_ */
-229
View File
@@ -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
View File
@@ -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, &copy_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];
}
-69
View File
@@ -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 */
-90
View File
@@ -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 */
-42
View File
@@ -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);
}
-25
View File
@@ -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));
-107
View File
@@ -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');
}
-49
View File
@@ -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);
-242
View File
@@ -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);
}
-84
View File
@@ -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 ();
-206
View File
@@ -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;
}
-301
View File
@@ -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
View File
@@ -1 +0,0 @@
#define SAFE_STAT(path,pbuf) stat(path,pbuf)
-515
View File
@@ -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;
}
-112
View File
@@ -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 */
-62
View File
@@ -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 */
-259
View File
@@ -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
+8 -1
View File
@@ -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;
}
+1
View File
@@ -145,6 +145,7 @@ sm_flush(fp, timeout)
return SM_IO_EOF;
}
SM_IO_WR_TIMEOUT(fp, fd, *timeout);
t = 0;
}
}
return 0;
+10 -8
View File
@@ -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; \
}
+6 -3
View File
@@ -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)); \
}
+77 -88
View File
@@ -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.
**
+8 -11
View 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
View File
@@ -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;
+39 -26
View File
@@ -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
View File
@@ -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
+6 -6
View File
@@ -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
View File
@@ -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
**
+11 -11
View File
@@ -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
View File
@@ -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;
+2
View File
@@ -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 */
+9 -84
View File
@@ -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,
+24 -72
View File
@@ -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
View File
@@ -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));
+63 -2
View File
@@ -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